Decompiled source of OneShotOneKill v1.0.0

OneShotOneKill.dll

Decompiled 12 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using On.RoR2;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("OneShotOneKill")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("OneShotOneKill")]
[assembly: AssemblyTitle("OneShotOneKill")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace OneShotOneKill
{
	[BepInPlugin("com.yourname.oneshotonekill", "One Shot, One Kill", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class OneShotOneKillPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.yourname.oneshotonekill";

		public const string PluginName = "One Shot, One Kill";

		public const string PluginVersion = "1.0.0";

		public static ConfigEntry<bool> ModEnabled;

		public static ConfigEntry<float> GracePeriodSeconds;

		public static ConfigEntry<float> NoKillCooldownSeconds;

		public static ConfigEntry<float> AttributionWindowSeconds;

		private static readonly Dictionary<GenericSkill, float> lockStartTime = new Dictionary<GenericSkill, float>();

		private static readonly List<GenericSkill> scratchKeys = new List<GenericSkill>();

		private void Awake()
		{
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Expected O, but got Unknown
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master on/off switch for One Shot, One Kill.");
			GracePeriodSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Initial Grace Period (seconds)", 300f, "How many seconds after the run/stage timer starts before the kill-to-reset rule kicks in. Default 300 = 5 minutes.");
			NoKillCooldownSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "No-Kill Cooldown (seconds)", 99f, "If a locked skill does NOT get a kill, this is how long it takes to come back on its own.");
			AttributionWindowSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Kill Attribution Window (seconds)", 3f, "How many seconds after firing a skill a kill can still be credited to it. Increase this for slow projectiles/DoTs, decrease it if kills feel like they're crediting the wrong skill.");
			if (Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"))
			{
				SetupRiskOfOptions();
			}
			GenericSkill.CanExecute += new hook_CanExecute(GenericSkill_CanExecute);
			GenericSkill.OnExecute += new hook_OnExecute(GenericSkill_OnExecute);
			GlobalEventManager.OnCharacterDeath += new hook_OnCharacterDeath(GlobalEventManager_OnCharacterDeath);
			Run.OnDestroy += new hook_OnDestroy(Run_OnDestroy);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"One Shot, One Kill loaded.");
		}

		private void OnDestroy()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Expected O, but got Unknown
			GenericSkill.CanExecute -= new hook_CanExecute(GenericSkill_CanExecute);
			GenericSkill.OnExecute -= new hook_OnExecute(GenericSkill_OnExecute);
			GlobalEventManager.OnCharacterDeath -= new hook_OnCharacterDeath(GlobalEventManager_OnCharacterDeath);
			Run.OnDestroy -= new hook_OnDestroy(Run_OnDestroy);
			lockStartTime.Clear();
		}

		private void SetupRiskOfOptions()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected O, but got Unknown
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Expected O, but got Unknown
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(GracePeriodSeconds, new StepSliderConfig
			{
				min = 0f,
				max = 900f,
				increment = 15f
			}));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(NoKillCooldownSeconds, new StepSliderConfig
			{
				min = 5f,
				max = 300f,
				increment = 1f
			}));
			ModSettingsManager.AddOption((BaseOption)new StepSliderOption(AttributionWindowSeconds, new StepSliderConfig
			{
				min = 0.5f,
				max = 10f,
				increment = 0.5f
			}));
		}

		private bool GenericSkill_CanExecute(orig_CanExecute orig, GenericSkill self)
		{
			if (!orig.Invoke(self))
			{
				return false;
			}
			if (!ModEnabled.Value || (Object)(object)self == (Object)null)
			{
				return true;
			}
			if (lockStartTime.TryGetValue(self, out var value) && Time.time - value < NoKillCooldownSeconds.Value)
			{
				return false;
			}
			return true;
		}

		private void GenericSkill_OnExecute(orig_OnExecute orig, GenericSkill self)
		{
			orig.Invoke(self);
			if (!NetworkServer.active || !ModEnabled.Value || (Object)(object)self == (Object)null)
			{
				return;
			}
			CharacterBody characterBody = self.characterBody;
			if (!((Object)(object)characterBody == (Object)null) && characterBody.isPlayerControlled && !((Object)(object)Run.instance == (Object)null) && !(Run.instance.GetRunStopwatch() < GracePeriodSeconds.Value))
			{
				SkillLocator skillLocator = characterBody.skillLocator;
				if (!((Object)(object)skillLocator == (Object)null) && !((Object)(object)self == (Object)(object)skillLocator.utility) && ((Object)(object)self == (Object)(object)skillLocator.primary || (Object)(object)self == (Object)(object)skillLocator.secondary || (Object)(object)self == (Object)(object)skillLocator.special))
				{
					lockStartTime[self] = Time.time;
				}
			}
		}

		private void GlobalEventManager_OnCharacterDeath(orig_OnCharacterDeath orig, GlobalEventManager self, DamageReport damageReport)
		{
			orig.Invoke(self, damageReport);
			if (!NetworkServer.active || !ModEnabled.Value)
			{
				return;
			}
			CharacterBody attackerBody = damageReport.attackerBody;
			if ((Object)(object)attackerBody == (Object)null || !attackerBody.isPlayerControlled)
			{
				return;
			}
			SkillLocator skillLocator = attackerBody.skillLocator;
			if (!((Object)(object)skillLocator == (Object)null))
			{
				GenericSkill best = null;
				float bestTime = float.NegativeInfinity;
				TryConsiderForCredit(skillLocator.primary, ref best, ref bestTime);
				TryConsiderForCredit(skillLocator.secondary, ref best, ref bestTime);
				TryConsiderForCredit(skillLocator.special, ref best, ref bestTime);
				if ((Object)(object)best != (Object)null)
				{
					UnlockAndRestock(best);
				}
			}
		}

		private static void TryConsiderForCredit(GenericSkill skill, ref GenericSkill best, ref float bestTime)
		{
			if (!((Object)(object)skill == (Object)null) && lockStartTime.TryGetValue(skill, out var value) && Time.time - value <= AttributionWindowSeconds.Value && value > bestTime)
			{
				best = skill;
				bestTime = value;
			}
		}

		private static void UnlockAndRestock(GenericSkill skill)
		{
			lockStartTime.Remove(skill);
			skill.stock = skill.maxStock;
			skill.rechargeStopwatch = 0f;
		}

		private void Run_OnDestroy(orig_OnDestroy orig, Run self)
		{
			orig.Invoke(self);
			lockStartTime.Clear();
		}

		private void FixedUpdate()
		{
			if (!NetworkServer.active || !ModEnabled.Value || lockStartTime.Count == 0)
			{
				return;
			}
			scratchKeys.Clear();
			scratchKeys.AddRange(lockStartTime.Keys);
			for (int i = 0; i < scratchKeys.Count; i++)
			{
				GenericSkill val = scratchKeys[i];
				if ((Object)(object)val == (Object)null)
				{
					lockStartTime.Remove(val);
					continue;
				}
				float num = lockStartTime[val];
				float num2 = Time.time - num;
				if (num2 >= NoKillCooldownSeconds.Value)
				{
					UnlockAndRestock(val);
					continue;
				}
				val.stock = 0;
				val.rechargeStopwatch = 0f;
			}
		}
	}
}