using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
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.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.Helpers.DialogObjects;
using SOD.Common.Helpers.SyncDiskObjects;
using UnityEngine;
using UnityStandardAssets.Characters.FirstPerson;
[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.1.0")]
[assembly: AssemblyInformationalVersion("0.12.1")]
[assembly: AssemblyProduct("SoDDiskPack")]
[assembly: AssemblyTitle("SoDDiskPack")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.12.1.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 SoDDiskPack
{
internal static class BigInventory
{
internal const int GameMax = 12;
internal const int Max = 18;
private static int target;
private static Vector3? baseScale;
private static Vector2? baseSize;
private static bool IsNormal(InventorySlot s)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
if (s != null)
{
return (int)s.isStatic == 0;
}
return false;
}
internal static List<InventorySlot> HoldAside(FirstPersonItemController fpc, int size)
{
target = size;
List<InventorySlot> list = new List<InventorySlot>();
List<InventorySlot> slots = fpc.slots;
int num = 0;
for (int i = 0; i < slots.Count; i++)
{
InventorySlot val = slots[i];
if (IsNormal(val))
{
num++;
if (num > 12)
{
list.Add(val);
slots.RemoveAt(i);
i--;
}
}
}
return list;
}
internal static void Restore(FirstPersonItemController fpc, List<InventorySlot>? held)
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Expected O, but got Unknown
try
{
List<InventorySlot> slots = fpc.slots;
if (held != null)
{
foreach (InventorySlot item in held)
{
slots.Add(item);
}
int i = 0;
for (int j = 0; j < slots.Count; j++)
{
if (IsNormal(slots[j]))
{
i++;
}
}
for (; i < target; i++)
{
InventorySlot val = new InventorySlot();
val.interactableID = -1;
slots.Add(val);
}
for (int k = 0; k < slots.Count; k++)
{
if (i <= target)
{
break;
}
InventorySlot val2 = slots[k];
if (IsNormal(val2) && val2.interactableID < 0)
{
if ((Object)(object)val2.spawnedSegment != (Object)null)
{
Object.Destroy((Object)(object)((Component)val2.spawnedSegment).gameObject);
}
slots.RemoveAt(k);
k--;
i--;
}
}
for (int l = 1; l < 2; l++)
{
if (i <= target)
{
break;
}
int num = slots.Count - 1;
while (num >= 0 && i > target)
{
InventorySlot val3 = slots[num];
if (IsNormal(val3))
{
if (val3.interactableID >= 0)
{
fpc.EmptySlot(val3, false, false, true, true);
}
if ((Object)(object)val3.spawnedSegment != (Object)null)
{
Object.Destroy((Object)(object)((Component)val3.spawnedSegment).gameObject);
}
slots.RemoveAt(num);
i--;
}
num--;
}
}
BioScreenController instance = BioScreenController.Instance;
for (int m = 0; m < slots.Count; m++)
{
InventorySlot val4 = slots[m];
val4.index = m;
if ((Object)(object)val4.spawnedSegment == (Object)null && (Object)(object)instance != (Object)null)
{
InventorySquareController spawnedSegment = instance.SpawnSlotObject(val4);
if ((Object)(object)val4.spawnedSegment == (Object)null)
{
val4.spawnedSegment = spawnedSegment;
}
}
if ((Object)(object)val4.spawnedSegment != (Object)null)
{
val4.spawnedSegment.OnUpdateContent();
}
}
}
Layout(fpc);
}
catch (Exception ex)
{
Plugin.L.LogError((object)("[SLOTS] could not restore the extra slots: " + ex));
}
}
private static void Layout(FirstPersonItemController fpc)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: 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_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: 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_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: 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)
//IL_00cc: 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)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
BioScreenController instance = BioScreenController.Instance;
RectTransform val = ((instance != null) ? instance.itemsParentRect : null);
if ((Object)(object)val == (Object)null)
{
return;
}
Vector3 valueOrDefault = baseScale.GetValueOrDefault();
if (!baseScale.HasValue)
{
valueOrDefault = ((Transform)val).localScale;
baseScale = valueOrDefault;
}
Vector2 valueOrDefault2 = baseSize.GetValueOrDefault();
if (!baseSize.HasValue)
{
Rect rect = val.rect;
valueOrDefault2 = ((Rect)(ref rect)).size;
baseSize = valueOrDefault2;
}
int num = 0;
for (int i = 0; i < fpc.slots.Count; i++)
{
if (IsNormal(fpc.slots[i]))
{
num++;
}
}
float num2 = ((num > 12) ? 1.5f : 1f);
((Transform)val).localScale = baseScale.Value / num2;
val.SetSizeWithCurrentAnchors((Axis)0, baseSize.Value.x * num2);
val.SetSizeWithCurrentAnchors((Axis)1, baseSize.Value.y * num2);
}
}
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 bool Retired;
}
public static class Disks
{
public static readonly DiskDef[] All = new DiskDef[27]
{
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 = "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 = 4000,
Rarity = (Rarity)3,
Manufacturer = (Manufacturer)5,
SaleLocations = new string[1] { "BlackmarketSyncClinic" },
TierDescs = new string[2] { "Your pockets hold more.", "You find room for more again." },
TiersInCode = true
},
new DiskDef
{
Key = "TailoredCoat",
DiskName = "Tailored Coat",
EffectName = "Tailored Coat",
EffectDesc = "A coat cut with extra pockets.",
Effect = (Effect)11,
Value = 1f,
Price = 3000,
Rarity = (Rarity)2,
Manufacturer = (Manufacturer)2,
SaleLocations = new string[1] { "SyncClinic" },
TierDescs = new string[1] { "A second inside pocket is sewn in." },
TiersInCode = true
},
new DiskDef
{
Key = "SmugglersLining",
DiskName = "Smuggler's Lining",
EffectName = "Hidden Lining",
EffectDesc = "Your clothes hide pockets nobody would think to check.",
Effect = (Effect)11,
Value = 1f,
Price = 3500,
Rarity = (Rarity)2,
Manufacturer = (Manufacturer)5,
SaleLocations = new string[1] { "BlackmarketSyncClinic" },
TierDescs = new string[1] { "The lining hides a second compartment." },
TiersInCode = true
},
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 = null,
Retired = true,
TierDescs = null
},
new DiskDef
{
Key = "Thumbscrews",
DiskName = "Thumbscrews",
EffectName = "Thumbscrews",
EffectDesc = "When a witness says your description is not enough to go on, you can press them, and they name someone they know who fits it. They are not always right.",
Effect = (Effect)0,
Value = 0f,
Price = 1750,
Rarity = (Rarity)2,
Manufacturer = (Manufacturer)5,
SaleLocations = new string[1] { "BlackmarketSyncClinic" },
TierDescs = null
},
new DiskDef
{
Key = "LowProfileDisk",
DiskName = "Low Profile",
EffectName = "Low Profile",
EffectDesc = "Fines cost you less.",
Effect = (Effect)0,
Value = 0f,
Price = 2000,
Rarity = (Rarity)2,
Manufacturer = (Manufacturer)5,
SaleLocations = new string[1] { "BlackmarketSyncClinic" },
TierDescs = new string[2] { "Your footsteps carry less far.", "Frightened people sometimes cower instead of running for help or joining a fight against you." },
TiersInCode = true
},
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.", "Nothing on the shelf is out of your reach." },
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
},
new DiskDef
{
Key = "Prowler",
DiskName = "Prowler",
EffectName = "Prowler",
EffectDesc = "You move faster while crouched.",
Effect = (Effect)0,
Value = 0f,
Price = 1500,
Rarity = (Rarity)1,
Manufacturer = (Manufacturer)5,
SaleLocations = new string[1] { "BlackmarketSyncClinic" },
TierDescs = null,
TiersInCode = true
},
new DiskDef
{
Key = "Heavyweight",
DiskName = "Fractured Tranquility",
EffectName = "Fractured Tranquility",
EffectDesc = "Your blows send people flying.",
Effect = (Effect)0,
Value = 0f,
Price = 2000,
Rarity = (Rarity)2,
Manufacturer = (Manufacturer)5,
SaleLocations = new string[1] { "BlackmarketSyncClinic" },
TierDescs = new string[3] { "Your hits land harder.", "People fly further when you hit them.", "Your blows throw people across the room." },
TiersInCode = true
},
new DiskDef
{
Key = "SlowBurn",
DiskName = "Slow Burn",
EffectName = "Slow Burn",
EffectDesc = "Your alertness and energy fade more slowly.",
Effect = (Effect)0,
Value = 0f,
Price = 1500,
Rarity = (Rarity)1,
Manufacturer = (Manufacturer)1,
SaleLocations = new string[1] { "SyncClinic" },
TierDescs = new string[3] { "A cup of coffee keeps you going longer.", "Your reserves fade more slowly still.", "You stay sharp long after others flag." },
TiersInCode = true
},
new DiskDef
{
Key = "Connoisseur",
DiskName = "Connoisseur",
EffectName = "Connoisseur",
EffectDesc = "Food and drink do you more good.",
Effect = (Effect)0,
Value = 0f,
Price = 1200,
Rarity = (Rarity)0,
Manufacturer = (Manufacturer)3,
SaleLocations = new string[1] { "SyncClinic" },
TierDescs = new string[3] { "You get more from every meal.", "Every drink refreshes you further.", "You get the very most out of everything you eat and drink." },
TiersInCode = true
},
new DiskDef
{
Key = "Deadlift",
DiskName = "Deadlift",
EffectName = "Deadlift",
EffectDesc = "You drag bodies faster.",
Effect = (Effect)0,
Value = 0f,
Price = 1500,
Rarity = (Rarity)1,
Manufacturer = (Manufacturer)5,
SaleLocations = new string[1] { "BlackmarketSyncClinic" },
TierDescs = new string[3] { "You haul a body with less effort.", "Dead weight barely slows you down.", "You drag a body almost as fast as you walk." },
TiersInCode = true
}
};
}
internal static class LowProfile
{
internal static ConfigEntry<float> FineCut = null;
internal static ConfigEntry<float> StepCut = null;
internal static ConfigEntry<float> CowerChance = null;
private static int level = -1;
private static float levelAt = -10f;
internal static void Bind()
{
FineCut = Plugin.Cfg.Bind<float>("LowProfileDisk", "FineReduction", 0.25f, "Installed: fines are this much cheaper (0.25 = 25% off).");
StepCut = Plugin.Cfg.Bind<float>("LowProfileDisk", "FootstepRangeCut", 3f, "Tier 1: how many metres less far your footsteps carry. A walk is usually heard 5 to 15 m away depending on the floor, crouching 5 m less, running 5 m more.");
CowerChance = Plugin.Cfg.Bind<float>("LowProfileDisk", "CowerChance", 0.4f, "Tier 2: chance that a frightened citizen cowers instead of running, raising the alarm, calling the enforcers or joining a fight against you (0.4 = 40%).");
}
internal static int Level()
{
if (Time.unscaledTime - levelAt > 1f)
{
levelAt = Time.unscaledTime;
level = Plugin.LevelOf("_Low Profile");
}
return level;
}
}
[HarmonyPatch]
internal static class LowProfileHooks
{
private static readonly HashSet<string> Swappable = new HashSet<string> { "RunAway", "TriggerAlarm", "CallEnforcers", "Attack", "Chase" };
private static readonly Dictionary<int, (bool cower, float until)> decided = new Dictionary<int, (bool, float)>();
private static AIActionPreset? cowering;
[HarmonyPostfix]
[HarmonyPatch(typeof(StatusCount), "GetPenaltyAmount")]
private static void Fine(ref int __result)
{
try
{
if (__result > 0 && LowProfile.Level() >= 0)
{
__result = Mathf.RoundToInt((float)__result * (1f - Mathf.Clamp01(LowProfile.FineCut.Value)));
}
}
catch
{
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(AudioController), "PlayWorldFootstep")]
private static void StepOn(AudioEvent eventPreset, Actor actor, out float __state)
{
__state = float.NaN;
try
{
if (!((SoCustomComparison)(object)eventPreset == (SoCustomComparison)null) && !((Object)(object)actor == (Object)null) && actor.isPlayer && LowProfile.Level() >= 1)
{
__state = eventPreset.hearingRange;
eventPreset.hearingRange = __state - Mathf.Max(0f, LowProfile.StepCut.Value);
}
}
catch
{
}
}
[HarmonyFinalizer]
[HarmonyPatch(typeof(AudioController), "PlayWorldFootstep")]
private static void StepOff(AudioEvent eventPreset, float __state)
{
try
{
if (!float.IsNaN(__state) && (SoCustomComparison)(object)eventPreset != (SoCustomComparison)null)
{
eventPreset.hearingRange = __state;
}
}
catch
{
}
}
[HarmonyPrefix]
[HarmonyPatch(typeof(NewAIController), "CreateNewAction")]
private static void Action(NewAIController __instance, NewAIGoal newGoal, ref AIActionPreset newPreset)
{
try
{
if ((SoCustomComparison)(object)newPreset == (SoCustomComparison)null || !Swappable.Contains(((Object)newPreset).name) || LowProfile.Level() < 2)
{
return;
}
Human human = __instance.human;
if ((Object)(object)human == (Object)null || ((Actor)human).isPlayer || ((Actor)human).isEnforcer)
{
return;
}
object obj;
if (newGoal == null)
{
obj = null;
}
else
{
AIGoalPreset preset = newGoal.preset;
obj = ((preset != null) ? ((Object)preset).name : null);
}
if (obj == null)
{
obj = "";
}
switch ((string)obj)
{
default:
return;
case "Investigate":
if (!((Object)(object)__instance.persuitTarget != (Object)null) || !__instance.persuitTarget.isPlayer)
{
return;
}
break;
case "Flee":
case "ReactToBody":
break;
}
float unscaledTime = Time.unscaledTime;
if (!decided.TryGetValue(human.humanID, out (bool, float) value) || unscaledTime > value.Item2)
{
value = (Random.value < Mathf.Clamp01(LowProfile.CowerChance.Value), unscaledTime + 60f);
decided[human.humanID] = value;
}
if (value.Item1)
{
if (cowering == null)
{
cowering = Find("Cowering");
}
if (!((SoCustomComparison)(object)cowering == (SoCustomComparison)null))
{
newPreset = cowering;
}
}
}
catch
{
}
}
private static AIActionPreset? Find(string name)
{
try
{
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<AIActionPreset>()))
{
AIActionPreset val = ((Il2CppObjectBase)item).TryCast<AIActionPreset>();
if ((SoCustomComparison)(object)val != (SoCustomComparison)null && ((Object)val).name == name)
{
return val;
}
}
}
catch
{
}
Plugin.L.LogWarning((object)("Low Profile: no '" + name + "' action found; citizens will not cower"));
return null;
}
}
internal static class NewDisks
{
internal static ConfigEntry<float> HeavyPush = null;
internal static ConfigEntry<string> ProwlerTiers = null;
internal static ConfigEntry<string> HeavyTiers = null;
internal static ConfigEntry<string> SlowBurnTiers = null;
internal static ConfigEntry<string> ConnoisseurTiers = null;
internal static ConfigEntry<string> DeadliftTiers = null;
internal static float CrouchMult = 1f;
internal static float HitMult = 1f;
internal static float DragMult = 1f;
private static float? baseKOForce;
private static readonly Dictionary<IntPtr, (RetailItemPreset p, float n, float h, float a, float e)> food = new Dictionary<IntPtr, (RetailItemPreset, float, float, float, float)>();
private static float foodMult = 1f;
internal static void Bind(ConfigFile cfg)
{
ProwlerTiers = cfg.Bind<string>("Prowler", "CrouchSpeed", "1.75", "Crouch-walk speed multiplier while Prowler is installed (it has no upgrades).");
if (ProwlerTiers.Value == "1.25,1.4,1.55,1.75")
{
ProwlerTiers.Value = "1.75";
}
HeavyPush = cfg.Bind<float>("FracturedTranquility", "PushPerStep", 4f, "Extra speed (metres per second) given to a body you knock out, per step of HitForce above 1. At 3 that is 8.");
HeavyTiers = cfg.Bind<string>("FracturedTranquility", "HitForce", "1.5,2,2.5,3", "How hard your hits throw people (ragdoll force multiplier): installed, tier 1, tier 2, tier 3.");
SlowBurnTiers = cfg.Bind<string>("SlowBurn", "DrainFraction", "-0.15,-0.25,-0.35,-0.45", "Change to how fast alertness and energy drain (-0.15 = 15% slower): installed, tier 1, tier 2, tier 3. Summed with the other disks that write the same fields.");
DeadliftTiers = cfg.Bind<string>("Deadlift", "DragSpeed", "1.3,1.5,1.75,2", "Walk and run speed multiplier while dragging a body: installed, tier 1, tier 2, tier 3. The game slows you to about a third while dragging, so 2 roughly doubles that. Capped at 3.");
ConnoisseurTiers = cfg.Bind<string>("Connoisseur", "FoodMultiplier", "1.2,1.3,1.4,1.5", "Multiplier on what food and drink give (nourishment, hydration, alertness, energy): installed, tier 1, tier 2, tier 3.");
}
internal static float Pick(ConfigEntry<string> e, int level, float neutral)
{
if (level < 0)
{
return neutral;
}
string[] array = (e.Value ?? "").Split(',');
int num = Math.Min(level, array.Length - 1);
if (num < 0 || !float.TryParse(array[num].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
{
return neutral;
}
return result;
}
internal static void Apply(GameplayControls gc, int prowler, int heavy, int connoisseur, int deadlift)
{
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0232: Expected O, but got Unknown
DragMult = Mathf.Clamp(Pick(DeadliftTiers, deadlift, 1f), 1f, 3f);
CrouchMult = Pick(ProwlerTiers, prowler, 1f);
HitMult = Pick(HeavyTiers, heavy, 1f);
float valueOrDefault = baseKOForce.GetValueOrDefault();
if (!baseKOForce.HasValue)
{
valueOrDefault = gc.playerKOPunchForce;
baseKOForce = valueOrDefault;
}
gc.playerKOPunchForce = baseKOForce.Value * HitMult;
float num = Pick(ConnoisseurTiers, connoisseur, 1f);
if (food.Count == 0)
{
foreach (Object item in (Il2CppArrayBase<Object>)(object)Resources.FindObjectsOfTypeAll(Il2CppType.Of<RetailItemPreset>()))
{
RetailItemPreset val = ((Il2CppObjectBase)item).TryCast<RetailItemPreset>();
if ((SoCustomComparison)(object)val != (SoCustomComparison)null)
{
food[((Il2CppObjectBase)val).Pointer] = (val, val.nourishment, val.hydration, val.alertness, val.energy);
}
}
}
if (Math.Abs(num - foodMult) > 0.0001f)
{
foodMult = num;
foreach (var value in food.Values)
{
try
{
value.p.nourishment = ((value.n > 0f) ? (value.n * num) : value.n);
value.p.hydration = ((value.h > 0f) ? (value.h * num) : value.h);
value.p.alertness = ((value.a > 0f) ? (value.a * num) : value.a);
value.p.energy = ((value.e > 0f) ? (value.e * num) : value.e);
}
catch
{
}
}
}
ManualLogSource l = Plugin.L;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(105, 10, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[TIER] prowler=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(prowler);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" crouch x");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(CrouchMult);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" | heavyweight=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(heavy);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" hits x");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(HitMult);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" koForce=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(gc.playerKOPunchForce);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" | connoisseur=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(connoisseur);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" food x");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(foodMult);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(food.Count);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" items) | deadlift=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(deadlift);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" drag x");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(DragMult);
}
l.LogInfo(val2);
}
}
public class ProwlerMover : MonoBehaviour
{
private float nextLog;
private float? baseWalk;
private bool raised;
public ProwlerMover(IntPtr p)
: base(p)
{
}
private void Update()
{
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Expected O, but got Unknown
try
{
Player instance = Player.Instance;
FirstPersonController val = ((instance != null) ? instance.fps : null);
Player instance2 = Player.Instance;
if ((Object)(object)val == (Object)null || (Object)(object)instance2 == (Object)null)
{
return;
}
bool flag = ((Actor)instance2).isCrouched || instance2.crouchedTransition > 0.5f;
if (NewDisks.CrouchMult > 1f && flag)
{
if (!raised)
{
baseWalk = val.m_WalkSpeed;
raised = true;
}
val.m_WalkSpeed = baseWalk.Value * NewDisks.CrouchMult;
if (Time.unscaledTime > nextLog)
{
nextLog = Time.unscaledTime + 3f;
ManualLogSource l = Plugin.L;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(41, 3, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[PROWLER] crouched, walk ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(baseWalk.Value, "0.00");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(val.m_WalkSpeed, "0.00");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", speed now ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(val.speed, "0.00");
}
l.LogInfo(val2);
}
}
else if (raised)
{
val.m_WalkSpeed = baseWalk.Value;
raised = false;
}
}
catch (Exception ex)
{
if (Time.unscaledTime > nextLog)
{
nextLog = Time.unscaledTime + 10f;
Plugin.L.LogInfo((object)("[PROWLER] " + ex.Message));
}
}
}
}
[HarmonyPatch(typeof(Citizen), "RecieveDamage")]
internal static class HeavyweightPatch
{
internal static bool PlayerHit;
private static int logged;
private static void Prefix(Actor fromWho, ref float ragdollForceMP)
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
PlayerHit = false;
if (NewDisks.HitMult == 1f || (Object)(object)fromWho == (Object)null)
{
return;
}
try
{
if (!fromWho.isPlayer)
{
return;
}
PlayerHit = true;
ragdollForceMP *= NewDisks.HitMult;
if (logged++ < 5)
{
ManualLogSource l = Plugin.L;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(35, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[HEAVY] player hit, ragdoll force x");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(NewDisks.HitMult);
}
l.LogInfo(val);
}
}
catch
{
}
}
private static void Postfix()
{
PlayerHit = false;
}
}
[HarmonyPatch(typeof(NewAIController), "SetKO")]
internal static class HeavyweightKOPatch
{
private static int logged;
private static void Prefix(NewAIController __instance, bool val, Vector3 impactDirection, ref float forceMultiplier)
{
//IL_0021: 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)
//IL_0050: 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_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Expected O, but got Unknown
//IL_0048: 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)
if (!val || !HeavyweightPatch.PlayerHit || NewDisks.HitMult <= 1f)
{
return;
}
forceMultiplier *= NewDisks.HitMult;
try
{
Vector3 val2 = impactDirection;
if (((Vector3)(ref val2)).sqrMagnitude < 0.01f && (Object)(object)Player.Instance != (Object)null)
{
val2 = ((Component)Player.Instance).transform.forward;
}
val2.y = Mathf.Max(val2.y, 0f) + 0.25f;
HeavyweightPush.Queue(__instance.human, ((Vector3)(ref val2)).normalized * ((NewDisks.HitMult - 1f) * NewDisks.HeavyPush.Value));
if (logged++ < 5)
{
ManualLogSource l = Plugin.L;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(36, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[HEAVY] knockout x");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(NewDisks.HitMult);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": push ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>((NewDisks.HitMult - 1f) * NewDisks.HeavyPush.Value, "0.0");
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" m/s queued");
}
l.LogInfo(val3);
}
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("[HEAVY] " + ex.Message));
}
}
}
public class HeavyweightPush : MonoBehaviour
{
private static readonly List<(Human who, Vector3 v, int frames)> queue = new List<(Human, Vector3, int)>();
private static int logged;
public HeavyweightPush(IntPtr p)
: base(p)
{
}
internal static void Queue(Human who, Vector3 v)
{
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)who != (Object)null)
{
queue.Add((who, v, 2));
}
}
private void FixedUpdate()
{
//IL_0084: 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)
//IL_00cd: Expected O, but got Unknown
bool flag = default(bool);
for (int num = queue.Count - 1; num >= 0; num--)
{
(Human, Vector3, int) value = queue[num];
if (--value.Item3 > 0)
{
queue[num] = value;
}
else
{
queue.RemoveAt(num);
try
{
Il2CppArrayBase<Rigidbody> componentsInChildren = ((Component)value.Item1).GetComponentsInChildren<Rigidbody>();
int num2 = 0;
foreach (Rigidbody item in componentsInChildren)
{
if (!((Object)(object)item == (Object)null) && !item.isKinematic)
{
item.AddForce(value.Item2, (ForceMode)2);
num2++;
}
}
if (logged++ < 5)
{
ManualLogSource l = Plugin.L;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(38, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[HEAVY] pushed ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num2);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" of ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(componentsInChildren.Length);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" body parts at ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(((Vector3)(ref value.Item2)).magnitude, "0.0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m/s");
}
l.LogInfo(val);
}
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("[HEAVY] push: " + ex.Message));
}
}
}
}
}
public class DeadliftMover : MonoBehaviour
{
private float baseWalk = -1f;
private float baseRun = -1f;
private float nextLog;
public DeadliftMover(IntPtr p)
: base(p)
{
}
private void Update()
{
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Expected O, but got Unknown
try
{
Player instance = Player.Instance;
FirstPersonController val = ((instance != null) ? instance.fps : null);
if ((Object)(object)val == (Object)null || (Object)(object)instance == (Object)null)
{
return;
}
InteractionController instance2 = InteractionController.Instance;
RigidbodyDragObject val2 = ((instance2 != null) ? instance2.currentlyDragging : null);
if (NewDisks.DragMult > 1f && (Object)(object)val2 != (Object)null && val2.dragIsActive)
{
if (baseWalk < 0f)
{
float desiredWalkSpeed = instance.desiredWalkSpeed;
float desiredRunSpeed = instance.desiredRunSpeed;
if (desiredWalkSpeed > 0.1f && desiredWalkSpeed < 20f && desiredRunSpeed > 0.1f && desiredRunSpeed < 40f)
{
baseWalk = desiredWalkSpeed;
baseRun = desiredRunSpeed;
}
}
if (!(baseWalk > 0f))
{
return;
}
val.m_WalkSpeed = baseWalk * NewDisks.DragMult;
val.m_RunSpeed = baseRun * NewDisks.DragMult;
if (Time.unscaledTime > nextLog)
{
nextLog = Time.unscaledTime + 5f;
ManualLogSource l = Plugin.L;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(30, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[DEADLIFT] dragging, walk ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(baseWalk, "0.00");
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" -> ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(val.m_WalkSpeed, "0.00");
}
l.LogInfo(val3);
}
}
else if (baseWalk > 0f)
{
val.m_WalkSpeed = instance.desiredWalkSpeed;
val.m_RunSpeed = instance.desiredRunSpeed;
baseWalk = (baseRun = -1f);
}
}
catch (Exception ex)
{
if (Time.unscaledTime > nextLog)
{
nextLog = Time.unscaledTime + 10f;
Plugin.L.LogInfo((object)("[DEADLIFT] " + ex.Message));
}
}
}
}
[BepInPlugin("ta.sod.syncdiskpack", "SoD Disk Pack", "0.15.1")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BasePlugin
{
public const string GUID = "ta.sod.syncdiskpack";
public const string VER = "0.18.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> LaInteractionRange2;
internal static ConfigEntry<float> SwRecovery;
internal static ConfigEntry<float> SwEnergy;
internal static ConfigEntry<float> SwBruised;
internal static ConfigEntry<string> DpTierSlots;
internal static ConfigEntry<int> CoatUpgradeSlots;
internal static ConfigEntry<int> LiningUpgradeSlots;
internal static ConfigEntry<int> MaxInventorySlots;
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;
internal static ConfigFile Cfg;
private ConfigFile OpenSettings(string newFileName)
{
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Expected O, but got Unknown
string text = Path.Combine(Paths.ConfigPath, newFileName);
try
{
string text2 = Path.Combine(Paths.ConfigPath, "ta.sod.syncdiskpack.cfg");
if (File.Exists(text2))
{
if (!File.Exists(text))
{
File.Copy(text2, text);
}
if (File.ReadAllText(text2) == File.ReadAllText(text))
{
File.Delete(text2);
((BasePlugin)this).Log.LogInfo((object)("Moved settings from the old config file to " + newFileName));
}
}
}
catch (Exception ex)
{
((BasePlugin)this).Log.LogWarning((object)("Could not move the old settings file: " + ex.Message));
}
return new ConfigFile(text, true);
}
public override void Load()
{
Cfg = OpenSettings("sm3gm.sod.syncdiskpack.cfg");
L = ((BasePlugin)this).Log;
L.LogInfo((object)"=== SoDDiskPack 0.18.0 starting ===");
DisableList = Cfg.Bind<string>("_Experimental", "DisableVanillaDisks", "", "TEST ONLY. Comma-separated vanilla preset names to set disabled=true. Leave empty to change nothing.");
RemoveList = Cfg.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 = Cfg.Bind<float>("Quickstep", "Tier1RunSpeedFraction", 0.05f, "Quickstep tier 1. Fraction added to base playerRunSpeed. Cumulative.");
QsTier2 = Cfg.Bind<float>("Quickstep", "Tier2RunSpeedFraction", 0.05f, "Quickstep tier 2. Fraction added to base playerRunSpeed. Cumulative.");
QsTier3 = Cfg.Bind<float>("Quickstep", "Tier3RunSpeedFraction", 0.1f, "Quickstep tier 3. Fraction added to base playerRunSpeed. Cumulative.");
LeapJump0 = Cfg.Bind<float>("Leap", "JumpHeightInstalled", 6f, "GameplayControls.jumpHeight while Leap is installed, unupgraded. Game baseline is 4.5. Absolute value, not a fraction.");
LeapJump1 = Cfg.Bind<float>("Leap", "JumpHeightTier1", 7f, "jumpHeight at tier 1. Absolute.");
LeapJump2 = Cfg.Bind<float>("Leap", "JumpHeightTier2", 8f, "jumpHeight at tier 2. Absolute.");
LeapJump3 = Cfg.Bind<float>("Leap", "JumpHeightTier3", 9f, "jumpHeight at tier 3. Absolute. 9.0 was play-tested as a good ceiling.");
LeapFall0 = Cfg.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 = Cfg.Bind<float>("Leap", "FallDamageTier1", 1.1f, "fallDamageMultiplier at tier 1.");
LeapFall2 = Cfg.Bind<float>("Leap", "FallDamageTier2", 1.2f, "fallDamageMultiplier at tier 2.");
LeapFall3 = Cfg.Bind<float>("Leap", "FallDamageTier3", 1.3f, "fallDamageMultiplier at tier 3.");
IlTiredness = Cfg.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 = Cfg.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 = Cfg.Bind<float>("IronLung", "Tier3HungerFraction", -0.2f, "Iron Lung tier 3. Fraction applied to base playerHungerRate (0.125).");
IlThirst = Cfg.Bind<float>("IronLung", "Tier3ThirstFraction", -0.2f, "Iron Lung tier 3. Fraction applied to base playerThirstRate (0.15).");
IlGaitCure = Cfg.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 = Cfg.Bind<float>("SprintersCurse", "SpeedFractionPerTier", 0.08f, "Sprinter's Curse. Fraction added to base playerRunSpeed per tier. Cumulative.");
ScTiredness = Cfg.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 = Cfg.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 = Cfg.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 = Cfg.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 = Cfg.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 = Cfg.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 = Cfg.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. Confirmed read live and observed in play.");
LaCarryDistance = Cfg.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.");
LaInteractionRange2 = Cfg.Bind<float>("LongArm", "Tier2InteractionRangeFraction", 0.1f, "Long Arm tier 2 as of 0.17.1. Fraction applied to base interactionRange (1.585), on top of tier 1.");
LaThrowForce = Cfg.Bind<float>("LongArm", "Tier3ThrowForceFraction", 0.4f, "UNUSED as of 0.17.1 (tier 2 is reach now; Brawn covers throwing). Before that: 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 = Cfg.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 = Cfg.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 = Cfg.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.");
NewDisks.Bind(Cfg);
DpTierSlots = Cfg.Bind<string>("DeepPockets", "TierSlots", "1,1", "Deep Pockets. Extra inventory slots added by upgrade tiers 1 and 2, on top of the disk's own slot (two tiers since 1.3.0).");
CoatUpgradeSlots = Cfg.Bind<int>("TailoredCoat", "UpgradeSlots", 1, "Tailored Coat. Extra inventory slots added by its upgrade, on top of the disk's own slot.");
LiningUpgradeSlots = Cfg.Bind<int>("SmugglersLining", "UpgradeSlots", 1, "Smuggler's Lining. Extra inventory slots added by its upgrade, on top of the disk's own slot.");
if (DpTierSlots.Value == "1,1,1" || DpTierSlots.Value == "2,2,3")
{
DpTierSlots.Value = "1,1";
}
if (CoatUpgradeSlots.Value == 2)
{
CoatUpgradeSlots.Value = 1;
}
if (LiningUpgradeSlots.Value == 2)
{
LiningUpgradeSlots.Value = 1;
}
MaxInventorySlots = Cfg.Bind<int>("Inventory", "MaxInventorySlots", 18, "Ceiling for the inventory size from all disks together (at most 18). Above 12 the inventory screen shows a third row. Never lowers a size set by the game or another mod.");
int num = 0;
int num2 = 0;
DiskDef[] all = Disks.All;
foreach (DiskDef diskDef in all)
{
if (!Cfg.Bind<bool>(diskDef.Key, "Enabled", diskDef.Enabled, "Register this disk.").Value)
{
L.LogInfo((object)("skipped: " + diskDef.DiskName));
continue;
}
int value = Cfg.Bind<int>(diskDef.Key, "Price", diskDef.Price, "Purchase price.").Value;
float value2 = Cfg.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));
}
}
Thumbscrews.Register();
LowProfile.Bind();
Harmony.CreateAndPatchAll(typeof(LowProfileHooks), (string)null);
Harmony.CreateAndPatchAll(typeof(ThumbscrewsHooks), (string)null);
Harmony.CreateAndPatchAll(typeof(DisablePatch), (string)null);
Harmony.CreateAndPatchAll(typeof(TierPatch), (string)null);
Harmony.CreateAndPatchAll(typeof(InventoryPatch), (string)null);
Harmony.CreateAndPatchAll(typeof(HeavyweightPatch), (string)null);
Harmony.CreateAndPatchAll(typeof(HeavyweightKOPatch), (string)null);
((BasePlugin)this).AddComponent<ProwlerMover>();
((BasePlugin)this).AddComponent<DeadliftMover>();
((BasePlugin)this).AddComponent<HeavyweightPush>();
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_01e3: Unknown result type (might be due to invalid IL or missing references)
//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0222: 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_0243: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_0110: Invalid comparison between Unknown and I4
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: 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.Retired)
{
val.SetWorldSpawnOption(false).SetCanBeSideJobReward(false);
}
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 = !d.Retired;
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" : "")));
}
internal 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");
int level = LevelOf("_Slow Burn");
NewDisks.Apply(instance, LevelOf("_Prowler"), LevelOf("_Fractured Tranquility"), LevelOf("_Connoisseur"), LevelOf("_Deadlift"));
float num8 = NewDisks.Pick(NewDisks.SlowBurnTiers, level, 0f);
float num9 = 0f;
if (num >= 1)
{
num9 += QsTier1.Value;
}
if (num >= 2)
{
num9 += QsTier2.Value;
}
if (num >= 3)
{
num9 += QsTier3.Value;
}
if (num4 >= 1)
{
num9 += ScSpeedPerTier.Value;
}
if (num4 >= 2)
{
num9 += ScSpeedPerTier.Value;
}
if (num4 >= 3)
{
num9 += ScSpeedPerTier.Value;
}
if (num3 >= 3)
{
num9 += IlGaitCure.Value;
}
instance.playerRunSpeed = BaseRunSpeed.Value * (1f + num9);
float value = BaseJumpHeight.Value;
float num10 = BaseFallDamage.Value;
if (num2 == 0)
{
value = LeapJump0.Value;
num10 = LeapFall0.Value;
}
else if (num2 == 1)
{
value = LeapJump1.Value;
num10 = LeapFall1.Value;
}
else if (num2 == 2)
{
value = LeapJump2.Value;
num10 = LeapFall2.Value;
}
else if (num2 >= 3)
{
value = LeapJump3.Value;
num10 = LeapFall3.Value;
}
if (num4 >= 3)
{
num10 *= 1f + ScFallDamage.Value;
}
instance.jumpHeight = value;
instance.fallDamageMultiplier = num10;
float num11 = 0f;
if (num3 >= 1)
{
num11 += IlTiredness.Value;
}
if (num4 >= 1)
{
num11 += ScTiredness.Value;
}
num11 += num8;
instance.playerTirednessRate = BaseTiredness.Value * (1f + num11);
float num12 = 0f;
if (num3 >= 2)
{
num12 += IlRecovery.Value;
}
if (num7 >= 1)
{
num12 += SwRecovery.Value;
}
instance.playerRecoveryRate = BaseRecovery.Value * (1f + num12);
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) + ((num6 >= 2) ? LaInteractionRange2.Value : 0f));
instance.carryDistance = BaseCarryDistance.Value;
instance.throwForce = BaseThrowForce.Value;
instance.playerEnergyRate = BaseEnergyRate.Value * (1f + ((num7 >= 2) ? SwEnergy.Value : 0f) + num8);
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(FirstPersonItemController), "SetSlotSize")]
public static class InventoryPatch
{
private static int lastLogged = -1;
private static int TierSlots(int level)
{
int num = 0;
string[] array = (Plugin.DpTierSlots.Value ?? "").Split(',');
for (int i = 0; i < level && i < array.Length; i++)
{
if (int.TryParse(array[i].Trim(), out var result))
{
num += result;
}
}
return num;
}
private static void LogInventoryDisks()
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0061: Invalid comparison between Unknown and I4
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Invalid comparison between Unknown and I4
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Invalid comparison between Unknown and I4
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Invalid comparison between Unknown and I4
//IL_019c: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
try
{
UpgradesController instance = UpgradesController.Instance;
if (((instance != null) ? instance.upgrades : null) == null)
{
return;
}
Enumerator<Upgrades> enumerator = instance.upgrades.GetEnumerator();
while (enumerator.MoveNext())
{
Upgrades current = enumerator.Current;
SyncDiskPreset val = ((current != null) ? current.preset : null);
List<string> parts;
if (!((SoCustomComparison)(object)val == (SoCustomComparison)null))
{
parts = new List<string>();
if ((int)val.mainEffect1 == 11)
{
parts.Add("main1 " + val.mainEffect1Value);
}
if ((int)val.mainEffect2 == 11)
{
parts.Add("main2 " + val.mainEffect2Value);
}
if ((int)val.mainEffect3 == 11)
{
parts.Add("main3 " + val.mainEffect3Value);
}
if ((int)val.sideEffect == 11)
{
parts.Add("side " + val.sideEffectValue);
}
Opt("opt1", val.option1UpgradeEffects, val.option1UpgradeValues);
Opt("opt2", val.option2UpgradeEffects, val.option2UpgradeValues);
Opt("opt3", val.option3UpgradeEffects, val.option3UpgradeValues);
if (parts.Count > 0)
{
Plugin.L.LogInfo((object)("[SLOTS] disk " + ((Object)val).name + " state " + ((object)current.state/*cast due to .constrained prefix*/).ToString() + " level " + current.level + ": " + string.Join(", ", parts)));
}
}
void Opt(string tag, List<UpgradeEffect> fx, List<float> vals)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
int num = 0;
while (fx != null && num < fx.Count)
{
if (((object)fx[num]/*cast due to .constrained prefix*/).ToString().IndexOf("nventory", StringComparison.OrdinalIgnoreCase) >= 0)
{
parts.Add(tag + " " + ((object)fx[num]/*cast due to .constrained prefix*/).ToString() + " " + ((vals != null && num < vals.Count) ? vals[num] : 0f));
}
num++;
}
}
}
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("[SLOTS] disk list failed: " + ex.Message));
}
}
private static void Prefix(FirstPersonItemController __instance, ref int newSize, out List<InventorySlot> __state)
{
__state = null;
int num = newSize;
int level = Plugin.LevelOf("_Deep Pockets");
int num2 = TierSlots(level);
if (Plugin.LevelOf("_Tailored Coat") >= 1)
{
num2 += Plugin.CoatUpgradeSlots.Value;
}
if (Plugin.LevelOf("_Smuggler's Lining") >= 1)
{
num2 += Plugin.LiningUpgradeSlots.Value;
}
int val = Math.Min(Plugin.MaxInventorySlots.Value, 18);
int num3 = Math.Max(num, Math.Min(num + num2, val));
if (num3 != lastLogged)
{
lastLogged = num3;
LogInventoryDisks();
ManualLogSource l = Plugin.L;
string[] obj = new string[11]
{
"[SLOTS] game asked ",
num.ToString(),
", Deep Pockets tier ",
level.ToString(),
", upgrades add ",
num2.ToString(),
", size ",
num3.ToString(),
" (default ",
null,
null
};
GameplayControls instance = GameplayControls.Instance;
obj[9] = ((instance != null) ? instance.defaultInventorySlots : (-1)).ToString();
obj[10] = ")";
l.LogInfo((object)string.Concat(obj));
}
newSize = num3;
if (num3 > 12)
{
__state = BigInventory.HoldAside(__instance, num3);
newSize = 12;
}
}
private static void Postfix(FirstPersonItemController __instance, List<InventorySlot> __state)
{
BigInventory.Restore(__instance, __state);
}
}
[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 ==="));
}
}
internal static class Thumbscrews
{
internal static ConfigEntry<int> MinClues = null;
internal static Human? Witness;
internal static Human? Target;
internal static List<DataKey> Keys = new List<DataKey>();
internal static float At = -1f;
internal static bool Fresh(Citizen saysTo)
{
if ((Object)(object)Witness != (Object)null && (Object)(object)saysTo != (Object)null && Witness.humanID == ((Human)saysTo).humanID)
{
return Time.unscaledTime - At < 120f;
}
return false;
}
internal static bool Installed()
{
return Plugin.LevelOf("_Thumbscrews") >= 0;
}
internal static void Register()
{
MinClues = Plugin.Cfg.Bind<int>("Thumbscrews", "MinimumClues", 2, "How many things about the person's looks or whereabouts the card must show before the witness can name anyone. Any part of the name is enough on its own.");
try
{
ThumbscrewsDialog.MsgId = Lib.Dialogs.Builder((string)null).SetText("[Thumbscrews] Think harder. Anyone you know fit this?").ModifyDialogOptions((Action<DialogPreset>)delegate(DialogPreset p)
{
p.ranking = int.MaxValue;
})
.SetDialogLogic((IDialogLogic)(object)new ThumbscrewsDialog())
.CreateAndRegister()
.Preset.msgID;
ThumbscrewsDialog.Tabbed = ThumbscrewsDialog.Tab();
}
catch (Exception ex)
{
Plugin.L.LogError((object)("Thumbscrews dialog: " + ex));
}
}
}
[HarmonyPatch]
internal static class ThumbscrewsHooks
{
private static PhotoSelectButtonController? clicking;
private const string NotEnough = "a6815309-f9d4-40b0-8a1e-3ec3550c64a2";
[HarmonyPrefix]
[HarmonyPatch(typeof(PhotoSelectButtonController), "OnLeftClick")]
private static void ClickOn(PhotoSelectButtonController __instance)
{
clicking = __instance;
}
[HarmonyFinalizer]
[HarmonyPatch(typeof(PhotoSelectButtonController), "OnLeftClick")]
private static void ClickOff()
{
clicking = null;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(SpeechController), "Speak", new Type[]
{
typeof(string),
typeof(bool),
typeof(bool),
typeof(Human),
typeof(SideJob),
typeof(InteractionDialogInstance)
})]
private static void Speak(SpeechController __instance, string ddsMessage)
{
//IL_00b5: 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)
try
{
if ((Object)(object)clicking == (Object)null || ddsMessage != "a6815309-f9d4-40b0-8a1e-3ec3550c64a2" || !Thumbscrews.Installed())
{
return;
}
Human val = (((Object)(object)__instance.actor != (Object)null) ? ((Il2CppObjectBase)__instance.actor).TryCast<Human>() : null);
Human citizen = clicking.citizen;
if ((Object)(object)val == (Object)null || (Object)(object)citizen == (Object)null || ((Actor)val).isPlayer)
{
return;
}
List<DataKey> list = new List<DataKey>();
List<DataKey> val2 = ((clicking.element != null) ? clicking.element.dk : null);
EvidenceWitness evidenceEntry = ((Actor)citizen).evidenceEntry;
if (val2 != null && evidenceEntry != null)
{
List<DataKey> tiedKeys = ((Evidence)evidenceEntry).GetTiedKeys(val2);
int num = 0;
while (tiedKeys != null && num < tiedKeys.Count)
{
if (!list.Contains(tiedKeys[num]))
{
list.Add(tiedKeys[num]);
}
num++;
}
}
Thumbscrews.Witness = val;
Thumbscrews.Target = citizen;
Thumbscrews.Keys = list;
Thumbscrews.At = Time.unscaledTime;
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("Thumbscrews: " + ex.Message));
}
}
}
internal sealed class ThumbscrewsDialog : IDialogLogic
{
internal static string MsgId = "";
internal static bool Tabbed;
internal static bool Retried;
internal static bool Tab()
{
try
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
MethodInfo methodInfo = assemblies[i].GetType("DialogUIRework.TabbedDialogUI")?.GetMethod("AddIDs");
if (!(methodInfo == null))
{
methodInfo.Invoke(null, new object[2]
{
"Investigation",
new string[1] { MsgId }
});
return true;
}
}
}
catch
{
}
return false;
}
public bool IsDialogShown(DialogPreset preset, Citizen saysTo, SideJob jobRef)
{
if (!Tabbed && !Retried)
{
Retried = true;
Tabbed = Tab();
}
if (Thumbscrews.Installed())
{
return Thumbscrews.Fresh(saysTo);
}
return false;
}
public ForceSuccess ShouldDialogSucceedOverride(DialogController instance, DialogOption dialog, Citizen saysTo, NewNode where, Actor saidBy)
{
return (ForceSuccess)1;
}
public void OnDialogExecute(DialogController instance, Citizen saysTo, Interactable saysToInteractable, NewNode where, Actor saidBy, bool success, NewRoom roomRef, SideJob jobRef)
{
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
try
{
if (!Thumbscrews.Fresh(saysTo) || (Object)(object)Thumbscrews.Target == (Object)null)
{
Lib.Dialogs.Speak(saysTo, "Who are we talking about again?", true);
return;
}
Human target = Thumbscrews.Target;
List<DataKey> keys = Thumbscrews.Keys;
Thumbscrews.Witness = null;
if (target.humanID == ((Human)saysTo).humanID)
{
Lib.Dialogs.Speak(saysTo, "Are you serious? That's me.", true);
return;
}
if (((Actor)target).isPlayer)
{
Lib.Dialogs.Speak(saysTo, "Is this a joke? That's you.", true);
return;
}
List<DataKey> list = new List<DataKey>();
foreach (DataKey item in keys)
{
if (ThumbscrewsMatch.IsClue(item))
{
list.Add(item);
}
}
if (list.Count < Thumbscrews.MinClues.Value && !list.Exists(ThumbscrewsMatch.IsName))
{
Lib.Dialogs.Speak(saysTo, "Ease up! That could be half the city.", true);
return;
}
List<(Human, float)> list2 = new List<(Human, float)>();
float num = 0f;
List<Acquaintance> acquaintances = ((Human)saysTo).acquaintances;
int num2 = 0;
while (acquaintances != null && num2 < acquaintances.Count)
{
Acquaintance val = acquaintances[num2];
if (val != null)
{
Human val2 = null;
try
{
val2 = val.GetOther((Human)(object)saysTo);
}
catch
{
}
if (!((Object)(object)val2 == (Object)null) && val2.humanID != ((Human)saysTo).humanID && !((Actor)val2).isPlayer && ThumbscrewsMatch.Fits(val2, target, list))
{
float num3 = Mathf.Max(0.05f, val.known);
list2.Add((val2, num3));
num += num3;
}
}
num2++;
}
if (ThumbscrewsMatch.Fits(target, target, list) && !list2.Exists(((Human h, float w) p) => p.h.humanID == target.humanID))
{
try
{
Acquaintance val3 = default(Acquaintance);
if (target.FindAcquaintanceExists((Human)(object)saysTo, ref val3) && val3 != null)
{
float num4 = Mathf.Max(0.05f, val3.known);
list2.Add((target, num4));
num += num4;
}
}
catch
{
}
}
if (list2.Count == 0)
{
Lib.Dialogs.Speak(saysTo, "I swear, I don't know anyone like that!", true);
return;
}
float num5 = Random.Range(0f, num);
Human val4 = list2[list2.Count - 1].Item1;
foreach (var item2 in list2)
{
num5 -= item2.Item2;
if (num5 <= 0f)
{
(val4, _) = item2;
break;
}
}
Lib.Dialogs.Speak(saysTo, "Alright, alright! Sounds like " + val4.GetCitizenName() + ".", false);
try
{
((Human)saysTo).RevealSighting(val4, true, false, ((Actor)saysTo).speechController, true);
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("Thumbscrews sighting: " + ex.Message));
}
}
catch (Exception ex2)
{
Plugin.L.LogInfo((object)("Thumbscrews: " + ex2));
}
}
}
internal static class ThumbscrewsMatch
{
internal static bool IsName(DataKey k)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Invalid comparison between Unknown and I4
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Invalid comparison between Unknown and I4
if ((int)k != 39 && (int)k != 38 && (int)k != 40)
{
return (int)k == 41;
}
return true;
}
internal static bool IsClue(DataKey k)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Expected I4, but got Unknown
bool flag = IsName(k);
if (!flag)
{
bool flag2;
switch (k - 5)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 7:
case 8:
case 9:
case 10:
case 13:
case 14:
case 19:
case 20:
case 25:
case 27:
case 29:
case 30:
flag2 = true;
break;
default:
flag2 = false;
break;
}
flag = flag2;
}
return flag;
}
internal static bool Fits(Human c, Human t, List<DataKey> clues)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Expected I4, but got Unknown
//IL_014d: 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_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0168: Unknown result type (might be due to invalid IL or missing references)
//IL_0188: 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_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0138: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0170: Unknown result type (might be due to invalid IL or missing references)
//IL_0176: Unknown result type (might be due to invalid IL or missing references)
Descriptors descriptors = c.descriptors;
Descriptors descriptors2 = t.descriptors;
if (descriptors == null || descriptors2 == null)
{
return false;
}
foreach (DataKey clue in clues)
{
bool flag;
int num3;
int num2;
int num;
switch (clue - 5)
{
case 3:
flag = c.gender == t.gender;
break;
case 2:
flag = Mathf.Abs(c.GetAge() - t.GetAge()) <= 2;
break;
case 19:
flag = c.GetAgeGroup() == t.GetAgeGroup();
break;
case 0:
flag = Mathf.Abs(descriptors.heightCM - descriptors2.heightCM) <= 3f;
break;
case 25:
flag = descriptors.height == descriptors2.height;
break;
case 1:
flag = descriptors.build == descriptors2.build;
break;
case 4:
flag = descriptors.hairColourCategory == descriptors2.hairColourCategory && descriptors.hairType == descriptors2.hairType;
break;
case 5:
flag = descriptors.eyeColour == descriptors2.eyeColour;
break;
case 7:
flag = descriptors.shoeSize == descriptors2.shoeSize;
break;
case 13:
flag = Math.Abs(descriptors.shoeSize - descriptors2.shoeSize) <= 1;
break;
case 20:
flag = Initial(c) == Initial(t);
break;
case 14:
flag = Has(descriptors, (FacialFeature)5) == Has(descriptors2, (FacialFeature)5);
break;
case 8:
flag = Has(descriptors, (FacialFeature)1) == Has(descriptors2, (FacialFeature)1) && Has(descriptors, (FacialFeature)2) == Has(descriptors2, (FacialFeature)2);
break;
case 9:
flag = (Object)(object)c.home != (Object)null && (Object)(object)t.home != (Object)null && c.home.id == t.home.id;
break;
case 29:
{
NewAddress home = c.home;
if ((Object)(object)((home != null) ? ((NewGameLocation)home).building : null) != (Object)null)
{
NewAddress home2 = t.home;
if ((Object)(object)((home2 != null) ? ((NewGameLocation)home2).building : null) != (Object)null)
{
num3 = ((((Il2CppObjectBase)((NewGameLocation)c.home).building).Pointer == ((Il2CppObjectBase)((NewGameLocation)t.home).building).Pointer) ? 1 : 0);
goto IL_02c0;
}
}
num3 = 0;
goto IL_02c0;
}
case 27:
{
NewAddress home3 = c.home;
if ((Object)(object)((home3 != null) ? ((NewGameLocation)home3).floor : null) != (Object)null)
{
NewAddress home4 = t.home;
if ((Object)(object)((home4 != null) ? ((NewGameLocation)home4).floor : null) != (Object)null)
{
num2 = ((((Il2CppObjectBase)((NewGameLocation)c.home).floor).Pointer == ((Il2CppObjectBase)((NewGameLocation)t.home).floor).Pointer) ? 1 : 0);
goto IL_0323;
}
}
num2 = 0;
goto IL_0323;
}
case 10:
{
Occupation job = c.job;
if (((job != null) ? job.employer : null) != null)
{
Occupation job2 = t.job;
if (((job2 != null) ? job2.employer : null) != null)
{
num = ((((Il2CppObjectBase)c.job.employer).Pointer == ((Il2CppObjectBase)t.job.employer).Pointer) ? 1 : 0);
goto IL_037a;
}
}
num = 0;
goto IL_037a;
}
case 30:
flag = (Object)(object)Work(c) != (Object)null && (Object)(object)Work(t) != (Object)null && ((Il2CppObjectBase)Work(c)).Pointer == ((Il2CppObjectBase)Work(t)).Pointer;
break;
case 34:
flag = Same(c.GetSurName(), t.GetSurName());
break;
case 33:
flag = Same(c.GetFirstName(), t.GetFirstName());
break;
case 35:
flag = Same(c.GetInitialledName(), t.GetInitialledName());
break;
case 36:
flag = Same(c.GetInitials(), t.GetInitials());
break;
default:
{
flag = true;
break;
}
IL_0323:
flag = (byte)num2 != 0;
break;
IL_02c0:
flag = (byte)num3 != 0;
break;
IL_037a:
flag = (byte)num != 0;
break;
}
if (!flag)
{
return false;
}
}
return true;
}
private static bool Same(string a, string b)
{
if (!string.IsNullOrEmpty(a))
{
return string.Equals(a.Trim(), b?.Trim(), StringComparison.OrdinalIgnoreCase);
}
return false;
}
private static char Initial(Human h)
{
string firstName = h.GetFirstName();
if (!string.IsNullOrEmpty(firstName))
{
return char.ToUpperInvariant(firstName[0]);
}
return ' ';
}
private static bool Has(Descriptors d, FacialFeature f)
{
//IL_000d: 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_0017: Unknown result type (might be due to invalid IL or missing references)
List<FacialFeaturesSetting> facialFeatures = d.facialFeatures;
int num = 0;
while (facialFeatures != null && num < facialFeatures.Count)
{
if (facialFeatures[num].feature == f)
{
return true;
}
num++;
}
return false;
}
private static NewBuilding? Work(Human h)
{
try
{
Occupation job = h.job;
object result;
if (job == null)
{
result = null;
}
else
{
Company employer = job.employer;
if (employer == null)
{
result = null;
}
else
{
NewAddress address = employer.address;
result = ((address != null) ? ((NewGameLocation)address).building : null);
}
}
return (NewBuilding?)result;
}
catch
{
return null;
}
}
}
}