using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using UnityEngine;
using UnityEngine.AI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Sadistic Company")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Sadistic Company")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("b545d1b4-c426-4c7a-83de-3259a76823f5")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SadisticCompany;
[BepInPlugin("kviks.sadisticcompany", "Sadistic Company", "1.0.0")]
public class SadisticCompanyPlugin : BaseUnityPlugin
{
internal static ManualLogSource Log;
internal static bool DebugEnabled;
internal static float FactorySizeMultiplier;
internal static float DaySpeedMultiplier;
internal static float InsidePowerMultiplier;
internal static float OutsidePowerMultiplier;
internal static float DaytimePowerMultiplier;
internal static float InsideDiversityMultiplier;
internal static float OutsideDiversityMultiplier;
internal static float SpawnRangeBonus;
internal static float DaytimeSpawnRangeBonus;
internal static float HazardMultiplier;
internal static float OutsidePropMultiplier;
internal static float DoorLockTimeMultiplier;
internal static float ExtraDoorLockChance;
internal static float EnemyMaxCountMultiplier;
internal static float EnemyDoorSpeedMultiplier;
internal static float EnemyProbabilityMultiplier;
internal static float EnemyPowerBudgetMultiplier;
internal static float EnemyRarityMultiplier;
internal static float EnemyStunTimeMultiplier;
internal static float EnemyPushForceMultiplier;
internal static float EnemyVentDelayMultiplier;
internal static float EnemyNavSpeedMultiplier;
internal static float EnemyNavAccelerationMultiplier;
internal static float EnemyNavAngularSpeedMultiplier;
internal static int EnemySpawnGroupBonus;
internal static bool EnemiesIgnoreFog;
internal static bool DisableEnemyStuns;
internal static bool UseNamedEnemyBiases;
internal static float PlayerDamageMultiplier;
internal static float ScrapWeightMultiplier;
internal static float ScrapWeightExtraCap;
internal static float ScrapAmountMultiplier;
internal static float ScrapValueMultiplier;
internal static float BatteryLifeMultiplier;
private static readonly HashSet<int> PatchedLevels = new HashSet<int>();
private static readonly HashSet<int> PatchedEnemies = new HashSet<int>();
private static readonly HashSet<int> PatchedItems = new HashSet<int>();
private static readonly HashSet<int> PatchedEnemyInstances = new HashSet<int>();
private static Harmony _harmony;
private ConfigEntry<bool> _debug;
private ConfigEntry<float> _factorySizeMultiplier;
private ConfigEntry<float> _daySpeedMultiplier;
private ConfigEntry<float> _insidePowerMultiplier;
private ConfigEntry<float> _outsidePowerMultiplier;
private ConfigEntry<float> _daytimePowerMultiplier;
private ConfigEntry<float> _insideDiversityMultiplier;
private ConfigEntry<float> _outsideDiversityMultiplier;
private ConfigEntry<float> _spawnRangeBonus;
private ConfigEntry<float> _daytimeSpawnRangeBonus;
private ConfigEntry<float> _hazardMultiplier;
private ConfigEntry<float> _outsidePropMultiplier;
private ConfigEntry<float> _doorLockTimeMultiplier;
private ConfigEntry<float> _extraDoorLockChance;
private ConfigEntry<float> _enemyMaxCountMultiplier;
private ConfigEntry<float> _enemyDoorSpeedMultiplier;
private ConfigEntry<float> _enemyProbabilityMultiplier;
private ConfigEntry<float> _enemyPowerBudgetMultiplier;
private ConfigEntry<float> _enemyRarityMultiplier;
private ConfigEntry<float> _enemyStunTimeMultiplier;
private ConfigEntry<float> _enemyPushForceMultiplier;
private ConfigEntry<float> _enemyVentDelayMultiplier;
private ConfigEntry<float> _enemyNavSpeedMultiplier;
private ConfigEntry<float> _enemyNavAccelerationMultiplier;
private ConfigEntry<float> _enemyNavAngularSpeedMultiplier;
private ConfigEntry<int> _enemySpawnGroupBonus;
private ConfigEntry<bool> _enemiesIgnoreFog;
private ConfigEntry<bool> _disableEnemyStuns;
private ConfigEntry<bool> _useNamedEnemyBiases;
private ConfigEntry<float> _playerDamageMultiplier;
private ConfigEntry<float> _scrapWeightMultiplier;
private ConfigEntry<float> _scrapWeightExtraCap;
private ConfigEntry<float> _scrapAmountMultiplier;
private ConfigEntry<float> _scrapValueMultiplier;
private ConfigEntry<float> _batteryLifeMultiplier;
private void Awake()
{
//IL_051a: Unknown result type (might be due to invalid IL or missing references)
//IL_0524: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
_debug = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableDebugLogging", false, "Enables debug logging.");
_factorySizeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Level", "FactorySizeMultiplier", 1.55f, "Bigger factory generation.");
_daySpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Level", "DaySpeedMultiplier", 1.45f, "Higher means the day moves faster.");
_insidePowerMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Spawns", "InsidePowerMultiplier", 2.8f, "Multiplies inside enemy power budget.");
_outsidePowerMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Spawns", "OutsidePowerMultiplier", 2.35f, "Multiplies outside enemy power budget.");
_daytimePowerMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Spawns", "DaytimePowerMultiplier", 2.1f, "Multiplies daytime enemy power budget.");
_insideDiversityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Spawns", "InsideDiversityMultiplier", 1.9f, "Multiplies inside diversity budget.");
_outsideDiversityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Spawns", "OutsideDiversityMultiplier", 1.75f, "Multiplies outside diversity budget.");
_spawnRangeBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Spawns", "InsideSpawnRangeBonus", 5f, "Adds to level spawnProbabilityRange.");
_daytimeSpawnRangeBonus = ((BaseUnityPlugin)this).Config.Bind<float>("Spawns", "DaytimeSpawnRangeBonus", 12f, "Adds to daytimeEnemiesProbabilityRange.");
_hazardMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Map", "IndoorHazardMultiplier", 2.8f, "Multiplies indoor hazard counts.");
_outsidePropMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Map", "OutsidePropMultiplier", 2.2f, "Multiplies outside hazard or object counts.");
_doorLockTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Map", "DoorLockTimeMultiplier", 2.25f, "Higher locked-door pick time.");
_extraDoorLockChance = ((BaseUnityPlugin)this).Config.Bind<float>("Map", "ExtraDoorLockChance", 0.58f, "Chance to lock additional lockable doors after vanilla setup.");
_enemyMaxCountMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyMaxCountMultiplier", 2.2f, "Higher per-enemy max count.");
_enemyDoorSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyDoorSpeedMultiplier", 1.65f, "Enemies open doors faster.");
_enemyProbabilityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyProbabilityMultiplier", 1.45f, "Multiplies enemy probability curves.");
_enemyPowerBudgetMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyPowerLevelMultiplier", 0.72f, "Lower values let more enemies fit into the power budget.");
_enemyRarityMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyRarityMultiplier", 1.45f, "Multiplies spawn rarity in level enemy lists.");
_enemyStunTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyStunTimeMultiplier", 0.55f, "Lower means enemies recover from stun faster.");
_enemyPushForceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyPushForceMultiplier", 1.35f, "Higher push force and distance from enemies.");
_enemyVentDelayMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyVentDelayMultiplier", 0.7f, "Lower means less warning before vent audio and spawn pressure.");
_enemyNavSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyNavSpeedMultiplier", 1.18f, "Multiplies spawned enemy nav speed.");
_enemyNavAccelerationMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyNavAccelerationMultiplier", 1.25f, "Multiplies spawned enemy nav acceleration.");
_enemyNavAngularSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Enemies", "EnemyNavAngularSpeedMultiplier", 1.18f, "Multiplies spawned enemy turn speed.");
_enemySpawnGroupBonus = ((BaseUnityPlugin)this).Config.Bind<int>("Enemies", "EnemySpawnGroupBonus", 1, "Adds to spawnInGroupsOf where applicable.");
_enemiesIgnoreFog = ((BaseUnityPlugin)this).Config.Bind<bool>("Enemies", "EnemiesIgnoreFog", true, "Enemies can see through fog.");
_disableEnemyStuns = ((BaseUnityPlugin)this).Config.Bind<bool>("Enemies", "DisableEnemyStuns", false, "Enemies cannot be stunned.");
_useNamedEnemyBiases = ((BaseUnityPlugin)this).Config.Bind<bool>("Enemies", "UseNamedEnemyBiases", true, "Extra buffs for iconic high-threat enemies.");
_playerDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Player", "DamageTakenMultiplier", 1.35f, "All received damage multiplier.");
_scrapWeightMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Rewards", "ExtraScrapBurdenMultiplier", 1.08f, "Only scales the weight above vanilla baseline so light scrap stays light.");
_scrapWeightExtraCap = ((BaseUnityPlugin)this).Config.Bind<float>("Rewards", "ExtraScrapBurdenCap", 0.3f, "Maximum added weight above vanilla baseline.");
_scrapAmountMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Rewards", "ScrapAmountMultiplier", 1.3f, "Higher means more scrap spawns in the level.");
_scrapValueMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Rewards", "ScrapValueMultiplier", 1.4f, "Higher means scrap rolls more cash value.");
_batteryLifeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Player", "BatteryLifeMultiplier", 0.75f, "Lower means batteries drain faster.");
ApplyConfig();
HookConfig();
_harmony = new Harmony("kviks.sadisticcompany");
_harmony.PatchAll();
if (DebugEnabled)
{
Log.LogInfo((object)"[SC] Loaded risk/reward balanced preset.");
}
}
private void ApplyConfig()
{
DebugEnabled = _debug.Value;
FactorySizeMultiplier = Mathf.Max(1f, _factorySizeMultiplier.Value);
DaySpeedMultiplier = Mathf.Max(0.5f, _daySpeedMultiplier.Value);
InsidePowerMultiplier = Mathf.Max(1f, _insidePowerMultiplier.Value);
OutsidePowerMultiplier = Mathf.Max(1f, _outsidePowerMultiplier.Value);
DaytimePowerMultiplier = Mathf.Max(1f, _daytimePowerMultiplier.Value);
InsideDiversityMultiplier = Mathf.Max(1f, _insideDiversityMultiplier.Value);
OutsideDiversityMultiplier = Mathf.Max(1f, _outsideDiversityMultiplier.Value);
SpawnRangeBonus = Mathf.Max(0f, _spawnRangeBonus.Value);
DaytimeSpawnRangeBonus = Mathf.Max(0f, _daytimeSpawnRangeBonus.Value);
HazardMultiplier = Mathf.Max(1f, _hazardMultiplier.Value);
OutsidePropMultiplier = Mathf.Max(1f, _outsidePropMultiplier.Value);
DoorLockTimeMultiplier = Mathf.Max(1f, _doorLockTimeMultiplier.Value);
ExtraDoorLockChance = Mathf.Clamp01(_extraDoorLockChance.Value);
EnemyMaxCountMultiplier = Mathf.Max(1f, _enemyMaxCountMultiplier.Value);
EnemyDoorSpeedMultiplier = Mathf.Max(1f, _enemyDoorSpeedMultiplier.Value);
EnemyProbabilityMultiplier = Mathf.Max(1f, _enemyProbabilityMultiplier.Value);
EnemyPowerBudgetMultiplier = Mathf.Clamp(_enemyPowerBudgetMultiplier.Value, 0.2f, 2f);
EnemyRarityMultiplier = Mathf.Max(1f, _enemyRarityMultiplier.Value);
EnemyStunTimeMultiplier = Mathf.Clamp(_enemyStunTimeMultiplier.Value, 0.1f, 3f);
EnemyPushForceMultiplier = Mathf.Max(1f, _enemyPushForceMultiplier.Value);
EnemyVentDelayMultiplier = Mathf.Clamp(_enemyVentDelayMultiplier.Value, 0.1f, 2f);
EnemyNavSpeedMultiplier = Mathf.Max(1f, _enemyNavSpeedMultiplier.Value);
EnemyNavAccelerationMultiplier = Mathf.Max(1f, _enemyNavAccelerationMultiplier.Value);
EnemyNavAngularSpeedMultiplier = Mathf.Max(1f, _enemyNavAngularSpeedMultiplier.Value);
EnemySpawnGroupBonus = Mathf.Clamp(_enemySpawnGroupBonus.Value, 0, 5);
EnemiesIgnoreFog = _enemiesIgnoreFog.Value;
DisableEnemyStuns = _disableEnemyStuns.Value;
UseNamedEnemyBiases = _useNamedEnemyBiases.Value;
PlayerDamageMultiplier = Mathf.Max(1f, _playerDamageMultiplier.Value);
ScrapWeightMultiplier = Mathf.Clamp(_scrapWeightMultiplier.Value, 1f, 1.5f);
ScrapWeightExtraCap = Mathf.Clamp(_scrapWeightExtraCap.Value, 0f, 0.5f);
ScrapAmountMultiplier = Mathf.Clamp(_scrapAmountMultiplier.Value, 1f, 4f);
ScrapValueMultiplier = Mathf.Clamp(_scrapValueMultiplier.Value, 1f, 4f);
BatteryLifeMultiplier = Mathf.Clamp(_batteryLifeMultiplier.Value, 0.1f, 1f);
}
private void HookConfig()
{
_debug.SettingChanged += delegate
{
ApplyConfig();
};
_factorySizeMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_daySpeedMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_insidePowerMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_outsidePowerMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_daytimePowerMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_insideDiversityMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_outsideDiversityMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_spawnRangeBonus.SettingChanged += delegate
{
ApplyConfig();
};
_daytimeSpawnRangeBonus.SettingChanged += delegate
{
ApplyConfig();
};
_hazardMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_outsidePropMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_doorLockTimeMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_extraDoorLockChance.SettingChanged += delegate
{
ApplyConfig();
};
_enemyMaxCountMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyDoorSpeedMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyProbabilityMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyPowerBudgetMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyRarityMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyStunTimeMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyPushForceMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyVentDelayMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyNavSpeedMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyNavAccelerationMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemyNavAngularSpeedMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_enemySpawnGroupBonus.SettingChanged += delegate
{
ApplyConfig();
};
_enemiesIgnoreFog.SettingChanged += delegate
{
ApplyConfig();
};
_disableEnemyStuns.SettingChanged += delegate
{
ApplyConfig();
};
_useNamedEnemyBiases.SettingChanged += delegate
{
ApplyConfig();
};
_playerDamageMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_scrapWeightMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_scrapWeightExtraCap.SettingChanged += delegate
{
ApplyConfig();
};
_scrapAmountMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_scrapValueMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
_batteryLifeMultiplier.SettingChanged += delegate
{
ApplyConfig();
};
}
internal static void TuneItems(StartOfRound startOfRound)
{
if (!((Object)(object)startOfRound == (Object)null) && !((Object)(object)startOfRound.allItemsList == (Object)null) && startOfRound.allItemsList.itemsList != null)
{
for (int i = 0; i < startOfRound.allItemsList.itemsList.Count; i++)
{
TuneItem(startOfRound.allItemsList.itemsList[i]);
}
}
}
internal static void TuneLevel(SelectableLevel level)
{
if ((Object)(object)level == (Object)null)
{
return;
}
int instanceID = ((Object)level).GetInstanceID();
if (!PatchedLevels.Add(instanceID))
{
return;
}
level.factorySizeMultiplier *= FactorySizeMultiplier;
level.DaySpeedMultiplier *= DaySpeedMultiplier;
level.maxEnemyPowerCount = Mathf.Max(1, Mathf.RoundToInt((float)level.maxEnemyPowerCount * InsidePowerMultiplier));
level.maxOutsideEnemyPowerCount = Mathf.Max(1, Mathf.RoundToInt((float)level.maxOutsideEnemyPowerCount * OutsidePowerMultiplier));
level.maxDaytimeEnemyPowerCount = Mathf.Max(1, Mathf.RoundToInt((float)level.maxDaytimeEnemyPowerCount * DaytimePowerMultiplier));
level.maxInsideDiversityPowerCount = Mathf.Max(1, Mathf.RoundToInt((float)level.maxInsideDiversityPowerCount * InsideDiversityMultiplier));
level.maxOutsideDiversityPowerCount = Mathf.Max(1, Mathf.RoundToInt((float)level.maxOutsideDiversityPowerCount * OutsideDiversityMultiplier));
level.spawnProbabilityRange += SpawnRangeBonus;
level.daytimeEnemiesProbabilityRange += DaytimeSpawnRangeBonus;
level.minScrap = Mathf.Max(0, Mathf.RoundToInt((float)level.minScrap * ScrapAmountMultiplier));
level.maxScrap = Mathf.Max(level.minScrap + 1, Mathf.RoundToInt((float)level.maxScrap * ScrapAmountMultiplier));
if (level.enemySpawnChanceThroughoutDay != null)
{
level.enemySpawnChanceThroughoutDay = ScaleCurve(level.enemySpawnChanceThroughoutDay, 1.45f, 0f, 0f, 40f);
}
if (level.outsideEnemySpawnChanceThroughDay != null)
{
level.outsideEnemySpawnChanceThroughDay = ScaleCurve(level.outsideEnemySpawnChanceThroughDay, 1.35f, 0f, 0f, 40f);
}
if (level.daytimeEnemySpawnChanceThroughDay != null)
{
level.daytimeEnemySpawnChanceThroughDay = ScaleCurve(level.daytimeEnemySpawnChanceThroughDay, 1.3f, 0f, 0f, 40f);
}
if (level.indoorMapHazards != null)
{
for (int i = 0; i < level.indoorMapHazards.Length; i++)
{
if (level.indoorMapHazards[i] != null && level.indoorMapHazards[i].numberToSpawn != null)
{
level.indoorMapHazards[i].numberToSpawn = ScaleCurve(level.indoorMapHazards[i].numberToSpawn, HazardMultiplier, 0f, 0f, 200f);
}
}
}
if (level.spawnableOutsideObjects != null)
{
for (int j = 0; j < level.spawnableOutsideObjects.Length; j++)
{
if (level.spawnableOutsideObjects[j] != null && level.spawnableOutsideObjects[j].randomAmount != null)
{
level.spawnableOutsideObjects[j].randomAmount = ScaleCurve(level.spawnableOutsideObjects[j].randomAmount, OutsidePropMultiplier, 0f, 0f, 200f);
}
}
}
TuneEnemyList(level.Enemies);
TuneEnemyList(level.OutsideEnemies);
TuneEnemyList(level.DaytimeEnemies);
if (DebugEnabled)
{
Log.LogInfo((object)("[SC] Tuned level " + level.PlanetName));
}
}
internal static void ApplyRoundBudgets(RoundManager roundManager)
{
if (!((Object)(object)roundManager == (Object)null))
{
roundManager.currentMaxInsidePower = Mathf.Max(roundManager.currentMaxInsidePower, roundManager.currentMaxInsidePower * InsidePowerMultiplier);
roundManager.currentMaxOutsidePower = Mathf.Max(roundManager.currentMaxOutsidePower, roundManager.currentMaxOutsidePower * OutsidePowerMultiplier);
roundManager.currentMaxInsideDiversityLevel = Mathf.Max(roundManager.currentMaxInsideDiversityLevel, Mathf.RoundToInt((float)roundManager.currentMaxInsideDiversityLevel * InsideDiversityMultiplier));
roundManager.currentMaxOutsideDiversityLevel = Mathf.Max(roundManager.currentMaxOutsideDiversityLevel, Mathf.RoundToInt((float)roundManager.currentMaxOutsideDiversityLevel * OutsideDiversityMultiplier));
roundManager.scrapAmountMultiplier = Mathf.Max(roundManager.scrapAmountMultiplier, ScrapAmountMultiplier);
roundManager.scrapValueMultiplier = Mathf.Max(roundManager.scrapValueMultiplier, ScrapValueMultiplier);
roundManager.minEnemiesToSpawn = Mathf.Max(roundManager.minEnemiesToSpawn, 2);
}
}
internal static void InflateExtraDoorLocks(Vector3 mainEntrancePosition)
{
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
if (ExtraDoorLockChance <= 0f || (Object)(object)StartOfRound.Instance == (Object)null)
{
return;
}
Random random = new Random(StartOfRound.Instance.randomMapSeed + 9124);
DoorLock[] array = Object.FindObjectsOfType<DoorLock>();
if (array == null || array.Length == 0)
{
return;
}
foreach (DoorLock val in array)
{
if (!((Object)(object)val == (Object)null) && !val.isLocked && val.canBeLocked && !(((Component)val).transform.position.y > -160f) && (!(mainEntrancePosition != Vector3.zero) || !(Vector3.Distance(mainEntrancePosition, ((Component)val).transform.position) < 18f)) && !(random.NextDouble() > (double)ExtraDoorLockChance))
{
float num = Mathf.Clamp(24f + (float)random.NextDouble() * 55f, 10f, 120f);
val.LockDoor(num);
}
}
}
internal static void TuneEnemyInstance(EnemyAI enemy)
{
if ((Object)(object)enemy == (Object)null)
{
return;
}
int instanceID = ((Object)enemy).GetInstanceID();
if (PatchedEnemyInstances.Add(instanceID))
{
float num = EnemyNavSpeedMultiplier;
if (UseNamedEnemyBiases && (Object)(object)enemy.enemyType != (Object)null)
{
num *= GetNamedEnemyNavBias(enemy.enemyType);
}
enemy.openDoorSpeedMultiplier *= EnemyDoorSpeedMultiplier;
if ((Object)(object)enemy.agent != (Object)null)
{
NavMeshAgent agent = enemy.agent;
agent.speed *= num;
NavMeshAgent agent2 = enemy.agent;
agent2.acceleration *= EnemyNavAccelerationMultiplier;
NavMeshAgent agent3 = enemy.agent;
agent3.angularSpeed *= EnemyNavAngularSpeedMultiplier;
}
}
}
private static void TuneEnemyList(List<SpawnableEnemyWithRarity> enemies)
{
if (enemies == null)
{
return;
}
for (int i = 0; i < enemies.Count; i++)
{
SpawnableEnemyWithRarity val = enemies[i];
if (val != null && !((Object)(object)val.enemyType == (Object)null))
{
val.rarity = Mathf.Clamp(Mathf.RoundToInt((float)val.rarity * EnemyRarityMultiplier), 1, 999);
TuneEnemy(val.enemyType);
}
}
}
private static void TuneEnemy(EnemyType enemy)
{
int instanceID = ((Object)enemy).GetInstanceID();
if (PatchedEnemies.Add(instanceID))
{
float maxCountMultiplier = EnemyMaxCountMultiplier;
float powerBudgetMultiplier = EnemyPowerBudgetMultiplier;
float probabilityMultiplier = EnemyProbabilityMultiplier;
float doorSpeedMultiplier = EnemyDoorSpeedMultiplier;
float navSpeedMultiplier = EnemyNavSpeedMultiplier;
int spawnGroupBonus = EnemySpawnGroupBonus;
if (UseNamedEnemyBiases)
{
ApplyNamedEnemyBiases(enemy, ref maxCountMultiplier, ref powerBudgetMultiplier, ref probabilityMultiplier, ref doorSpeedMultiplier, ref navSpeedMultiplier, ref spawnGroupBonus);
}
enemy.MaxCount = Mathf.Clamp(Mathf.RoundToInt((float)enemy.MaxCount * maxCountMultiplier), 1, 64);
enemy.PowerLevel = Mathf.Clamp(enemy.PowerLevel * powerBudgetMultiplier, 0.05f, 100f);
enemy.doorSpeedMultiplier *= doorSpeedMultiplier;
enemy.stunTimeMultiplier = Mathf.Clamp(enemy.stunTimeMultiplier * EnemyStunTimeMultiplier, 0.1f, 10f);
enemy.pushPlayerForce *= EnemyPushForceMultiplier;
enemy.pushPlayerDistance *= Mathf.Lerp(1f, EnemyPushForceMultiplier, 0.5f);
enemy.timeToPlayAudio = Mathf.Clamp(enemy.timeToPlayAudio * EnemyVentDelayMultiplier, 1f, 60f);
enemy.canSeeThroughFog = enemy.canSeeThroughFog || EnemiesIgnoreFog;
enemy.canBeStunned = !DisableEnemyStuns && enemy.canBeStunned;
if (enemy.spawnInGroupsOf > 0)
{
enemy.spawnInGroupsOf = Mathf.Clamp(enemy.spawnInGroupsOf + spawnGroupBonus, 1, 8);
}
if (enemy.probabilityCurve != null)
{
enemy.probabilityCurve = ScaleCurve(enemy.probabilityCurve, probabilityMultiplier, 0f, 0f, 200f);
}
if (enemy.useNumberSpawnedFalloff && enemy.numberSpawnedFalloff != null)
{
enemy.numberSpawnedFalloff = ScaleCurve(enemy.numberSpawnedFalloff, 1.2f, 0f, 0f, 200f);
}
enemy.nestsSpawned = 0;
enemy.numberSpawned = 0;
enemy.hasSpawnedAtLeastOne = false;
}
}
private static float GetNamedEnemyNavBias(EnemyType enemy)
{
string text = ((enemy.enemyName == null) ? string.Empty : enemy.enemyName.ToLowerInvariant());
if (text.Contains("thumper") || text.Contains("crawler") || text.Contains("spider") || text.Contains("centipede"))
{
return 1.15f;
}
if (text.Contains("forest") || text.Contains("keeper") || text.Contains("dog") || text.Contains("baboon") || text.Contains("hawk"))
{
return 1.12f;
}
if (text.Contains("coil") || text.Contains("head") || text.Contains("bracken") || text.Contains("masked"))
{
return 1.08f;
}
return 1f;
}
private static void ApplyNamedEnemyBiases(EnemyType enemy, ref float maxCountMultiplier, ref float powerBudgetMultiplier, ref float probabilityMultiplier, ref float doorSpeedMultiplier, ref float navSpeedMultiplier, ref int spawnGroupBonus)
{
string text = ((enemy.enemyName == null) ? string.Empty : enemy.enemyName.ToLowerInvariant());
if (text.Contains("jester") || text.Contains("girl") || text.Contains("dress") || text.Contains("ghost"))
{
maxCountMultiplier *= 1.25f;
powerBudgetMultiplier *= 0.85f;
probabilityMultiplier *= 1.2f;
}
if (text.Contains("coil") || text.Contains("head") || text.Contains("bracken") || text.Contains("masked"))
{
maxCountMultiplier *= 1.2f;
powerBudgetMultiplier *= 0.82f;
probabilityMultiplier *= 1.15f;
doorSpeedMultiplier *= 1.15f;
navSpeedMultiplier *= 1.08f;
}
if (text.Contains("thumper") || text.Contains("crawler") || text.Contains("spider") || text.Contains("centipede"))
{
maxCountMultiplier *= 1.15f;
powerBudgetMultiplier *= 0.84f;
probabilityMultiplier *= 1.18f;
navSpeedMultiplier *= 1.15f;
}
if (text.Contains("forest") || text.Contains("keeper") || text.Contains("dog") || text.Contains("baboon") || text.Contains("hawk"))
{
maxCountMultiplier *= 1.2f;
powerBudgetMultiplier *= 0.8f;
probabilityMultiplier *= 1.2f;
navSpeedMultiplier *= 1.12f;
spawnGroupBonus++;
}
}
private static void TuneItem(Item item)
{
if ((Object)(object)item == (Object)null)
{
return;
}
int instanceID = ((Object)item).GetInstanceID();
if (PatchedItems.Add(instanceID))
{
if (item.isScrap)
{
float num = 1f;
float num2 = Mathf.Max(0f, item.weight - num);
float num3 = Mathf.Min(num2 * (ScrapWeightMultiplier - 1f), ScrapWeightExtraCap);
item.weight = num + num2 + num3;
}
if (item.requiresBattery)
{
item.batteryUsage = Mathf.Clamp(item.batteryUsage * BatteryLifeMultiplier, 0.1f, 999f);
}
}
}
private static AnimationCurve ScaleCurve(AnimationCurve source, float valueMultiplier, float valueOffset, float minValue, float maxValue)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0088: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Expected O, but got Unknown
if (source == null)
{
return null;
}
Keyframe[] keys = source.keys;
for (int i = 0; i < keys.Length; i++)
{
Keyframe val = keys[i];
((Keyframe)(ref val)).value = Mathf.Clamp(((Keyframe)(ref val)).value * valueMultiplier + valueOffset, minValue, maxValue);
((Keyframe)(ref val)).inTangent = ((Keyframe)(ref val)).inTangent * valueMultiplier;
((Keyframe)(ref val)).outTangent = ((Keyframe)(ref val)).outTangent * valueMultiplier;
keys[i] = val;
}
return new AnimationCurve(keys)
{
preWrapMode = source.preWrapMode,
postWrapMode = source.postWrapMode
};
}
}
[HarmonyPatch]
internal static class SadisticCompanyPatches
{
[HarmonyPatch(typeof(StartOfRound), "Awake")]
[HarmonyPostfix]
private static void StartOfRoundAwakePostfix(StartOfRound __instance)
{
SadisticCompanyPlugin.TuneItems(__instance);
}
[HarmonyPatch(typeof(RoundManager), "LoadNewLevel")]
[HarmonyPostfix]
private static void LoadNewLevelPostfix(RoundManager __instance, SelectableLevel newLevel)
{
SadisticCompanyPlugin.TuneLevel(newLevel ?? __instance.currentLevel);
}
[HarmonyPatch(typeof(RoundManager), "RefreshEnemiesList")]
[HarmonyPostfix]
private static void RefreshEnemiesListPostfix(RoundManager __instance)
{
SadisticCompanyPlugin.ApplyRoundBudgets(__instance);
}
[HarmonyPatch(typeof(RoundManager), "SetLockedDoors")]
[HarmonyPostfix]
private static void SetLockedDoorsPostfix(Vector3 mainEntrancePosition)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
SadisticCompanyPlugin.InflateExtraDoorLocks(mainEntrancePosition);
}
[HarmonyPatch(typeof(DoorLock), "LockDoor")]
[HarmonyPrefix]
private static void LockDoorPrefix(ref float timeToLockPick)
{
timeToLockPick = Mathf.Clamp(timeToLockPick * SadisticCompanyPlugin.DoorLockTimeMultiplier, 2f, 240f);
}
[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
[HarmonyPrefix]
private static void DamagePlayerPrefix(ref int damageNumber)
{
damageNumber = Mathf.Max(1, Mathf.RoundToInt((float)damageNumber * SadisticCompanyPlugin.PlayerDamageMultiplier));
}
[HarmonyPatch(typeof(EnemyAI), "Start")]
[HarmonyPostfix]
private static void EnemyStartPostfix(EnemyAI __instance)
{
SadisticCompanyPlugin.TuneEnemyInstance(__instance);
}
}