Decompiled source of QuotaDifficulty v1.0.0

QuotaDifficulty.dll

Decompiled 5 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Mirror;
using YAPYAP;

[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("QuotaDifficulty")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+cd7c6cb439467ad6465739ddd2d2e163716004eb")]
[assembly: AssemblyProduct("QuotaDifficulty")]
[assembly: AssemblyTitle("QuotaDifficulty")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace QuotaDifficulty
{
	public enum DifficultyPreset
	{
		Easiest,
		Easier,
		Easy,
		Original,
		Hard,
		Harder,
		Hardest,
		Custom
	}
	public static class DifficultyState
	{
		private static bool _frozen;

		private static float _frozenMultiplier = 1f;

		public static bool IsFrozen => _frozen;

		public static void Freeze(float multiplier)
		{
			_frozen = true;
			_frozenMultiplier = multiplier;
		}

		public static void Clear()
		{
			_frozen = false;
			_frozenMultiplier = 1f;
		}

		public static float Resolve(float liveMultiplier)
		{
			if (!_frozen)
			{
				return liveMultiplier;
			}
			return _frozenMultiplier;
		}
	}
	internal sealed class ModConfig
	{
		private readonly ConfigEntry<DifficultyPreset> _preset;

		private readonly ConfigEntry<float> _customMultiplier;

		private readonly ConfigEntry<bool> _verboseLogging;

		public DifficultyPreset Preset => _preset.Value;

		public float CustomMultiplier => _customMultiplier.Value;

		public bool VerboseLogging => _verboseLogging.Value;

		public float Multiplier => QuotaMath.MultiplierFor(Preset, CustomMultiplier);

		public ModConfig(ConfigFile file)
		{
			_preset = file.Bind<DifficultyPreset>("Difficulty", "Preset", DifficultyPreset.Original, "Quota goal difficulty. Easiest 50%, Easier 65%, Easy 80%, Original 100%, Hard 125%, Harder 150%, Hardest 200%. Choose Custom to use CustomMultiplier instead.");
			_customMultiplier = file.Bind<float>("Difficulty", "CustomMultiplier", 1f, "Multiplier used when Preset is Custom. Clamped to the range 0.05 - 10.0.");
			_verboseLogging = file.Bind<bool>("Diagnostics", "VerboseLogging", false, "Log every quota goal calculation. Use this when reporting a problem.");
		}
	}
	[BepInPlugin("psh_games.quotadifficulty", "QuotaDifficulty", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "psh_games.quotadifficulty";

		public const string PluginName = "QuotaDifficulty";

		public const string PluginVersion = "1.0.0";

		internal static ManualLogSource Log { get; private set; }

		internal static ModConfig Settings { get; private set; }

		internal static float ActiveMultiplier => DifficultyState.Resolve((Settings == null) ? 1f : Settings.Multiplier);

		private void Awake()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			Settings = new ModConfig(((BaseUnityPlugin)this).Config);
			try
			{
				new Harmony("psh_games.quotadifficulty").PatchAll(typeof(Plugin).Assembly);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to apply patches; the game runs unmodified. " + ex));
				return;
			}
			Log.LogInfo((object)string.Format("{0} {1} loaded. preset={2} multiplier={3:0.###}", "QuotaDifficulty", "1.0.0", Settings.Preset, Settings.Multiplier));
		}
	}
	public static class QuotaMath
	{
		public const float MinMultiplier = 0.05f;

		public const float MaxMultiplier = 10f;

		public const int MinGoal = 1;

		public static float MultiplierFor(DifficultyPreset preset, float customMultiplier)
		{
			return preset switch
			{
				DifficultyPreset.Easiest => 0.5f, 
				DifficultyPreset.Easier => 0.65f, 
				DifficultyPreset.Easy => 0.8f, 
				DifficultyPreset.Original => 1f, 
				DifficultyPreset.Hard => 1.25f, 
				DifficultyPreset.Harder => 1.5f, 
				DifficultyPreset.Hardest => 2f, 
				DifficultyPreset.Custom => Clamp(customMultiplier), 
				_ => 1f, 
			};
		}

		public static float Clamp(float multiplier)
		{
			if (float.IsNaN(multiplier))
			{
				return 1f;
			}
			if (multiplier < 0.05f)
			{
				return 0.05f;
			}
			if (multiplier > 10f)
			{
				return 10f;
			}
			return multiplier;
		}

		public static bool IsNeutral(float multiplier)
		{
			return multiplier == 1f;
		}

		public static int Scale(int baseGoal, float multiplier)
		{
			if (IsNeutral(multiplier))
			{
				return baseGoal;
			}
			double num = Math.Round((double)baseGoal * (double)multiplier, MidpointRounding.AwayFromZero);
			if (num < 1.0)
			{
				return 1;
			}
			if (num > 2147483647.0)
			{
				return int.MaxValue;
			}
			return (int)num;
		}
	}
}
namespace QuotaDifficulty.Patches
{
	[HarmonyPatch(typeof(GameManager))]
	internal static class GameEntryPatches
	{
		[HarmonyPrefix]
		[HarmonyPatch("OnStartServer")]
		private static void FreezeMultiplier(GameManager __instance)
		{
			float multiplier = Plugin.Settings.Multiplier;
			DifficultyState.Freeze(multiplier);
			Plugin.Log.LogInfo((object)$"Game entered. multiplier frozen at {multiplier:0.###} (preset {Plugin.Settings.Preset}).");
			LogBaseValues(__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnDestroy")]
		private static void ClearMultiplier()
		{
			if (DifficultyState.IsFrozen)
			{
				DifficultyState.Clear();
				Plugin.Log.LogInfo((object)"Game left. multiplier unfrozen.");
			}
		}

		private static void LogBaseValues(GameManager instance)
		{
			if (Plugin.Settings.VerboseLogging)
			{
				int[] array = ReadField<int[]>(instance, "manualQuotaGoals");
				string text = ((array != null) ? string.Join(", ", array) : "unavailable");
				Plugin.Log.LogInfo((object)string.Format("Game base values: manualQuotaGoals=[{0}] sessionQuotaMultiplier={1} quotaScoreGoal={2} roundsToQuota={3}", text, ReadField<float>(instance, "sessionQuotaMultiplier"), ReadField<int>(instance, "quotaScoreGoal"), ReadField<int>(instance, "roundsToQuota")));
			}
		}

		private static T ReadField<T>(GameManager instance, string name)
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(GameManager), name);
			if (fieldInfo == null)
			{
				return default(T);
			}
			object value = fieldInfo.GetValue(instance);
			if (value is T)
			{
				return (T)value;
			}
			return default(T);
		}
	}
	[HarmonyPatch(typeof(GameManager))]
	internal static class QuotaScalingPatches
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetQuotaForSession")]
		private static void ScaleSessionGoal(ref int __result)
		{
			int num = QuotaMath.Scale(__result, Plugin.ActiveMultiplier);
			if (num != __result && Plugin.Settings.VerboseLogging)
			{
				Plugin.Log.LogInfo((object)$"GetQuotaForSession {__result} -> {num}");
			}
			__result = num;
		}

		[HarmonyPostfix]
		[HarmonyPatch("SvResetGameState")]
		private static void RewriteGoalAfterReset(GameManager __instance)
		{
			ApplyGoal(__instance, "SvResetGameState");
		}

		[HarmonyPostfix]
		[HarmonyPatch("RestoreGameData")]
		private static void RewriteGoalAfterRestore(GameManager __instance)
		{
			ApplyGoal(__instance, "RestoreGameData");
		}

		[HarmonyPostfix]
		[HarmonyPatch("GetNextQuotaScoreGoal")]
		private static void RewriteNextGoal(GameManager __instance, ref int __result)
		{
			if (!QuotaMath.IsNeutral(Plugin.ActiveMultiplier))
			{
				__result = __instance.GetQuotaForSession(__instance.QuotaSessionsCompleted + 1);
			}
		}

		private static void ApplyGoal(GameManager instance, string source)
		{
			if (!QuotaMath.IsNeutral(Plugin.ActiveMultiplier) && NetworkServer.active)
			{
				int num = (instance.NetworkcurrentQuotaScoreGoal = instance.GetQuotaForSession(instance.QuotaSessionsCompleted));
				if (Plugin.Settings.VerboseLogging)
				{
					Plugin.Log.LogInfo((object)$"{source}: sessionsCompleted={instance.QuotaSessionsCompleted} goal={num}");
				}
			}
		}
	}
}