Decompiled source of HIFUBanditTweaks v1.2.4

HIFUBanditTweaks.dll

Decompiled 3 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using EntityStates;
using EntityStates.Bandit2;
using EntityStates.Bandit2.Weapon;
using HIFUBanditTweaks.Skills;
using HarmonyLib;
using IL.EntityStates.Bandit2;
using IL.EntityStates.Bandit2.Weapon;
using IL.RoR2;
using KinematicCharacterController;
using Microsoft.CodeAnalysis;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.RuntimeDetour;
using On.EntityStates.Bandit2;
using On.EntityStates.Bandit2.Weapon;
using On.RoR2;
using On.RoR2.Achievements.Bandit2;
using R2API;
using R2API.Networking;
using R2API.Networking.Interfaces;
using RoR2;
using RoR2.Achievements;
using RoR2.Achievements.Bandit2;
using RoR2.Skills;
using UnityEngine;
using UnityEngine.AddressableAssets;
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.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("HIFUBanditTweaks")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("HIFUBanditTweaks")]
[assembly: AssemblyTitle("HIFUBanditTweaks")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 HIFUBanditTweaks
{
	public class ConfigManager
	{
		internal static bool ConfigChanged;

		internal static bool VersionChanged;

		public static T HandleConfig<T>(ConfigEntryBase entry, ConfigFile config, string name)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Expected O, but got Unknown
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			MethodInfo methodInfo = (from x in typeof(ConfigFile).GetMethods()
				where x.Name == "Bind"
				select x).First();
			methodInfo = methodInfo.MakeGenericMethod(typeof(T));
			object[] parameters = new object[3]
			{
				(object)new ConfigDefinition(Regex.Replace(config.ConfigFilePath, "\\W", "") + " : " + entry.Definition.Section, name),
				entry.DefaultValue,
				(object)new ConfigDescription(entry.Description.Description, (AcceptableValueBase)null, Array.Empty<object>())
			};
			ConfigEntryBase val = (ConfigEntryBase)methodInfo.Invoke(config, parameters);
			if (Main._preVersioning)
			{
				entry.BoxedValue = entry.DefaultValue;
			}
			if (!ConfigEqual(val.DefaultValue, val.BoxedValue) && VersionChanged)
			{
				entry.BoxedValue = entry.DefaultValue;
				val.BoxedValue = val.DefaultValue;
			}
			return default(T);
		}

		private static bool ConfigEqual(object a, object b)
		{
			if (a.Equals(b))
			{
				return true;
			}
			if (float.TryParse(a.ToString(), out var result) && float.TryParse(b.ToString(), out var result2) && (double)Mathf.Abs(result - result2) < 0.0001)
			{
				return true;
			}
			return false;
		}
	}
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInPlugin("HIFU.HIFUBanditTweaks", "HIFUBanditTweaks", "1.2.3")]
	public class Main : BaseUnityPlugin
	{
		public const string PluginGUID = "HIFU.HIFUBanditTweaks";

		public const string PluginAuthor = "HIFU";

		public const string PluginName = "HIFUBanditTweaks";

		public const string PluginVersion = "1.2.3";

		public static ConfigFile HBTConfig;

		public static ConfigFile HBTBackupConfig;

		public static ManualLogSource HBTLogger;

		public static bool _preVersioning;

		public static ConfigEntry<bool> enableAutoConfig { get; set; }

		public static ConfigEntry<string> latestVersion { get; set; }

		public void Awake()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			HBTLogger = ((BaseUnityPlugin)this).Logger;
			HBTConfig = ((BaseUnityPlugin)this).Config;
			HBTBackupConfig = new ConfigFile(Paths.ConfigPath + "\\HIFU.HIFUBanditTweaks.Backup.cfg", true);
			HBTBackupConfig.Bind<string>(": DO NOT MODIFY THIS FILES CONTENTS :", ": DO NOT MODIFY THIS FILES CONTENTS :", ": DO NOT MODIFY THIS FILES CONTENTS :", ": DO NOT MODIFY THIS FILES CONTENTS :");
			enableAutoConfig = HBTConfig.Bind<bool>("Config", "Enable Auto Config Sync", true, "Disabling this would stop HIFUBanditTweaks from syncing config whenever a new version is found.");
			_preVersioning = !((Dictionary<ConfigDefinition, string>)AccessTools.DeclaredPropertyGetter(typeof(ConfigFile), "OrphanedEntries").Invoke(HBTConfig, null)).Keys.Any((ConfigDefinition x) => x.Key == "Latest Version");
			latestVersion = HBTConfig.Bind<string>("Config", "Latest Version", "1.2.3", "DO NOT CHANGE THIS");
			if (enableAutoConfig.Value && (_preVersioning || latestVersion.Value != "1.2.3"))
			{
				latestVersion.Value = "1.2.3";
				ConfigManager.VersionChanged = true;
				HBTLogger.LogInfo((object)"Config Autosync Enabled.");
			}
			Specials.Init();
			IEnumerable<Type> enumerable = from type in Assembly.GetExecutingAssembly().GetTypes()
				where !type.IsAbstract && type.IsSubclassOf(typeof(TweakBase))
				select type;
			HBTLogger.LogInfo((object)"==+----------------==TWEAKS==----------------+==");
			foreach (Type item in enumerable)
			{
				TweakBase tweakBase = (TweakBase)Activator.CreateInstance(item);
				if (ValidateTweak(tweakBase))
				{
					tweakBase.Init();
				}
			}
			IEnumerable<Type> enumerable2 = from type in Assembly.GetExecutingAssembly().GetTypes()
				where !type.IsAbstract && type.IsSubclassOf(typeof(MiscBase))
				select type;
			HBTLogger.LogInfo((object)"==+----------------==MISC==----------------+==");
			foreach (Type item2 in enumerable2)
			{
				MiscBase miscBase = (MiscBase)Activator.CreateInstance(item2);
				if (ValidateMisc(miscBase))
				{
					miscBase.Init();
				}
			}
			NetworkingAPI.RegisterMessageType<SyncCooldownReduction>();
		}

		public bool ValidateTweak(TweakBase tb)
		{
			if (tb.isEnabled && ((BaseUnityPlugin)this).Config.Bind<bool>(tb.Name, "Enable?", true, "Vanilla is false").Value)
			{
				return true;
			}
			return false;
		}

		public bool ValidateMisc(MiscBase mb)
		{
			if (mb.isEnabled && ((BaseUnityPlugin)this).Config.Bind<bool>(mb.Name, "Enable?", true, "Vanilla is false").Value)
			{
				return true;
			}
			return false;
		}

		private void PeripheryMyBeloved()
		{
		}
	}
	public abstract class MiscBase
	{
		public abstract string Name { get; }

		public virtual bool isEnabled { get; } = true;


		public T ConfigOption<T>(T value, string name, string description)
		{
			ConfigEntry<T> val = Main.HBTConfig.Bind<T>(Name, name, value, description);
			ConfigManager.HandleConfig<T>((ConfigEntryBase)(object)val, Main.HBTBackupConfig, name);
			return val.Value;
		}

		public abstract void Hooks();

		public string d(float f)
		{
			return f * 100f + "%";
		}

		public virtual void Init()
		{
			Hooks();
			Main.HBTLogger.LogInfo((object)("Added " + Name));
		}
	}
	public abstract class MiscBase<T> : MiscBase where T : MiscBase<T>
	{
		public static T instance { get; set; }

		public MiscBase()
		{
			if (instance != null)
			{
				throw new InvalidOperationException("Singleton class " + typeof(T).Name + " was instantiated twice");
			}
			instance = this as T;
		}
	}
	public abstract class TweakBase
	{
		public abstract string Name { get; }

		public abstract string SkillToken { get; }

		public abstract string DescText { get; }

		public virtual bool isEnabled { get; } = true;


		public T ConfigOption<T>(T value, string name, string description)
		{
			ConfigEntry<T> val = Main.HBTConfig.Bind<T>(Name, name, value, description);
			ConfigManager.HandleConfig<T>((ConfigEntryBase)(object)val, Main.HBTBackupConfig, name);
			return val.Value;
		}

		public abstract void Hooks();

		public string d(float f)
		{
			return f * 100f + "%";
		}

		public virtual void Init()
		{
			Hooks();
			string text = "BANDIT2_" + SkillToken.ToUpper() + "_DESCRIPTION";
			LanguageAPI.Add(text, DescText);
			Main.HBTLogger.LogInfo((object)("Added " + Name));
		}
	}
	public abstract class TweakBase<T> : TweakBase where T : TweakBase<T>
	{
		public static T instance { get; set; }

		public TweakBase()
		{
			if (instance != null)
			{
				throw new InvalidOperationException("Singleton class " + typeof(T).Name + " was instantiated twice");
			}
			instance = this as T;
		}
	}
}
namespace HIFUBanditTweaks.Skills
{
	public class Blast : TweakBase
	{
		public static float Damage;

		public static int AmmoCount;

		public static float AutofireDur;

		public override string Name => ": Primary :: Blast";

		public override string SkillToken => "primary_alt";

		public override string DescText => "Fire an automatic rifle blast for <style=cIsDamage>" + d(Damage) + " damage</style>. Can hold up to " + AmmoCount + " bullets.";

		public override void Init()
		{
			Damage = ConfigOption(2.2f, "Damage", "Decimal. Vanilla is 3.3");
			AmmoCount = ConfigOption(6, "Charges", "Vanilla is 4");
			AutofireDur = ConfigOption(0.12f, "Autofire Duration per Bullet", "");
			base.Init();
		}

		public override void Hooks()
		{
			//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
			Bandit2FirePrimaryBase.OnEnter += new hook_OnEnter(Bandit2FirePrimaryBase_OnEnter);
			Bandit2FirePrimaryBase.GetMinimumInterruptPriority += new hook_GetMinimumInterruptPriority(Bandit2FirePrimaryBase_GetMinimumInterruptPriority);
			Changes();
		}

		private InterruptPriority Bandit2FirePrimaryBase_GetMinimumInterruptPriority(orig_GetMinimumInterruptPriority orig, Bandit2FirePrimaryBase self)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if (((EntityState)self).fixedAge <= self.minimumDuration && ((EntityState)self).inputBank.skill1.wasDown)
			{
				return (InterruptPriority)2;
			}
			return (InterruptPriority)0;
		}

		private void Bandit2FirePrimaryBase_OnEnter(orig_OnEnter orig, Bandit2FirePrimaryBase self)
		{
			if (self is Bandit2FireRifle)
			{
				((GenericBulletBaseState)self).damageCoefficient = Damage;
				((GenericBulletBaseState)self).recoilAmplitudeX = 0.15f;
				((GenericBulletBaseState)self).recoilAmplitudeY = 0.7f;
				((GenericBulletBaseState)self).spreadYawScale = 0f;
				((GenericBulletBaseState)self).spreadPitchScale = 0f;
				((GenericBulletBaseState)self).bulletRadius = 0.4f;
				self.minimumBaseDuration = AutofireDur;
			}
			orig.Invoke(self);
		}

		private void Changes()
		{
			//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_0028: Unknown result type (might be due to invalid IL or missing references)
			SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Bandit2/Bandit2Blast.asset").WaitForCompletion();
			val.baseMaxStock = AmmoCount;
			val.mustKeyPress = false;
			val.interruptPriority = (InterruptPriority)1;
		}

		private void HaveAblastPeriphery()
		{
		}
	}
	public class Burst : TweakBase
	{
		public static int PelletCount;

		public static float Damage;

		public static float ProcCoefficient;

		public static int AmmoCount;

		public static float AutofireDur;

		public override string Name => ": Primary : Burst";

		public override string SkillToken => "primary";

		public override string DescText => "Fire an automatic shotgun burst for <style=cIsDamage>" + PelletCount + "x" + d(Damage) + " damage</style>. Can hold up to " + AmmoCount + " shells.";

		public override void Init()
		{
			PelletCount = ConfigOption(5, "Pellet Count", "Vanilla is 5");
			Damage = ConfigOption(0.75f, "Damage", "Decimal. Vanilla is 1");
			ProcCoefficient = ConfigOption(0.7f, "Proc Coefficient", "Vanilla is 0.5");
			AmmoCount = ConfigOption(4, "Charges", "Vanilla is 4");
			AutofireDur = ConfigOption(0.12f, "Autofire Duration per Bullet", "");
			base.Init();
		}

		public override void Hooks()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Bandit2FirePrimaryBase.OnEnter += new hook_OnEnter(Bandit2FirePrimaryBase_OnEnter);
			Changes();
		}

		private void Bandit2FirePrimaryBase_OnEnter(orig_OnEnter orig, Bandit2FirePrimaryBase self)
		{
			if (self is FireShotgun2)
			{
				((GenericBulletBaseState)self).bulletCount = PelletCount;
				((GenericBulletBaseState)self).damageCoefficient = Damage;
				((GenericBulletBaseState)self).procCoefficient = ProcCoefficient;
				((GenericBulletBaseState)self).bulletRadius = 0.3f;
				self.minimumBaseDuration = AutofireDur;
			}
			orig.Invoke(self);
		}

		private void Changes()
		{
			//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_0028: Unknown result type (might be due to invalid IL or missing references)
			SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Bandit2/FireShotgun2.asset").WaitForCompletion();
			val.baseMaxStock = AmmoCount;
			val.mustKeyPress = false;
			val.interruptPriority = (InterruptPriority)1;
		}
	}
	public class Desperado : TweakBase
	{
		public static float Damage;

		public static float StackDamage;

		public static float Cooldown;

		public override string Name => ": Special :: Desperado";

		public override string SkillToken => "special_alt";

		public override string DescText => "<style=cIsDamage>Slayer</style>. Fire a revolver shot for <style=cIsDamage>" + d(Damage) + " damage</style>. Kills grant <style=cIsDamage>stacking tokens</style> for <style=cIsDamage>" + d(StackDamage * Damage) + "</style> more Desperado skill damage.";

		public override void Init()
		{
			Cooldown = ConfigOption(6f, "Cooldown", "Vanilla is 4");
			Damage = ConfigOption(8f, "Damage", "Decimal. Vanilla is 6");
			StackDamage = ConfigOption(0.05f, "Desperado Total Damage Percent per Token", "Vanilla is 0.1");
			base.Init();
		}

		public override void Hooks()
		{
			//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
			BaseFireSidearmRevolverState.OnEnter += new hook_OnEnter(BaseFireSidearmRevolverState_OnEnter);
			FireSidearmSkullRevolver.ModifyBullet += new Manipulator(FireSidearmSkullRevolver_ModifyBullet);
			Changes();
		}

		private void FireSidearmSkullRevolver_ModifyBullet(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 0.1f)
			}))
			{
				val.Next.Operand = StackDamage;
			}
			else
			{
				Main.HBTLogger.LogError((object)"Failed to apply Desperado Stacking Damage hook");
			}
		}

		private void BaseFireSidearmRevolverState_OnEnter(orig_OnEnter orig, BaseFireSidearmRevolverState self)
		{
			if (self is FireSidearmSkullRevolver)
			{
				self.damageCoefficient = Damage;
			}
			orig.Invoke(self);
		}

		private void Changes()
		{
			//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)
			SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Bandit2/SkullRevolver.asset").WaitForCompletion();
			val.baseRechargeInterval = Cooldown;
			val.canceledFromSprinting = false;
		}
	}
	public static class Specials
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_FixedUpdate <0>__BaseSidearmState_FixedUpdate;

			public static hook_FixedUpdate <1>__BasePrepSidearmRevolverState_FixedUpdate;
		}

		public static void Init()
		{
			//IL_0011: 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_001c: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			object obj = <>O.<0>__BaseSidearmState_FixedUpdate;
			if (obj == null)
			{
				hook_FixedUpdate val = BaseSidearmState_FixedUpdate;
				<>O.<0>__BaseSidearmState_FixedUpdate = val;
				obj = (object)val;
			}
			BaseSidearmState.FixedUpdate += (hook_FixedUpdate)obj;
			object obj2 = <>O.<1>__BasePrepSidearmRevolverState_FixedUpdate;
			if (obj2 == null)
			{
				hook_FixedUpdate val2 = BasePrepSidearmRevolverState_FixedUpdate;
				<>O.<1>__BasePrepSidearmRevolverState_FixedUpdate = val2;
				obj2 = (object)val2;
			}
			BasePrepSidearmRevolverState.FixedUpdate += (hook_FixedUpdate)obj2;
		}

		private static void BasePrepSidearmRevolverState_FixedUpdate(orig_FixedUpdate orig, BasePrepSidearmRevolverState self)
		{
			((EntityState)self).fixedAge = ((EntityState)self).fixedAge + Time.fixedDeltaTime;
			if (((EntityState)self).fixedAge >= ((BaseSidearmState)self).duration && !((EntityState)self).inputBank.skill4.down)
			{
				((EntityState)self).outer.SetNextState(self.GetNextState());
			}
		}

		public static void BaseSidearmState_FixedUpdate(orig_FixedUpdate orig, BaseSidearmState self)
		{
			((EntityState)self).fixedAge = ((EntityState)self).fixedAge + Time.fixedDeltaTime;
		}
	}
	public class LightsOut : TweakBase<LightsOut>
	{
		public static float Damage;

		public static float Cooldown;

		public static ModdedDamageType cooldownReset = DamageAPI.ReserveDamageType();

		public static float CooldownReduction;

		public override string Name => ": Special : Lights Out";

		public override string SkillToken => "special";

		public override string DescText => "<style=cIsDamage>Slayer</style>. Fire a revolver shot for <style=cIsDamage>" + d(Damage) + " damage</style>. Kills <style=cIsUtility>reset Lights Out's cooldown</style> and <style=cIsUtility>reduce other cooldowns</style> by <style=cIsUtility>" + d(CooldownReduction) + "</style>.";

		public override void Init()
		{
			Cooldown = ConfigOption(6f, "Cooldown", "Vanilla is 4");
			Damage = ConfigOption(8f, "Damage", "Decimal. Vanilla is 6");
			CooldownReduction = ConfigOption(0.33f, "Non-Special Cooldown Reduction on Kill", "Decimal. Vanilla is 1");
			base.Init();
		}

		public override void Hooks()
		{
			//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
			BaseFireSidearmRevolverState.OnEnter += new hook_OnEnter(BaseFireSidearmRevolverState_OnEnter);
			FireSidearmResetRevolver.ModifyBullet += new hook_ModifyBullet(FireSidearmResetRevolver_ModifyBullet);
			GlobalEventManager.onCharacterDeathGlobal += GlobalEventManager_onCharacterDeathGlobal;
			Changes();
		}

		private void GlobalEventManager_onCharacterDeathGlobal(DamageReport damageReport)
		{
			//IL_0009: 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_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_003d: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			DamageInfo damageInfo = damageReport.damageInfo;
			if (!DamageAPI.HasModdedDamageType(damageInfo, cooldownReset))
			{
				return;
			}
			EffectManager.SpawnEffect(LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/ImpactEffects/Bandit2ResetEffect"), new EffectData
			{
				origin = damageInfo.position
			}, true);
			GameObject attacker = damageReport.attacker;
			if (!Object.op_Implicit((Object)(object)attacker))
			{
				return;
			}
			NetMessageExtensions.Send((INetMessage)(object)new SyncCooldownReduction(attacker.GetComponent<NetworkIdentity>().netId, CooldownReduction), (NetworkDestination)1);
			SkillLocator component = attacker.GetComponent<SkillLocator>();
			if (Object.op_Implicit((Object)(object)component))
			{
				GenericSkill primary = component.primary;
				GenericSkill secondary = component.secondary;
				GenericSkill utility = component.utility;
				GenericSkill special = component.special;
				if (Object.op_Implicit((Object)(object)primary) && primary.stock < primary.maxStock)
				{
					primary.rechargeStopwatch += primary.finalRechargeInterval * CooldownReduction;
				}
				if (Object.op_Implicit((Object)(object)secondary) && secondary.stock < secondary.maxStock)
				{
					secondary.rechargeStopwatch += secondary.finalRechargeInterval * CooldownReduction;
				}
				if (Object.op_Implicit((Object)(object)utility) && utility.stock < utility.maxStock)
				{
					utility.rechargeStopwatch += utility.finalRechargeInterval * CooldownReduction;
				}
				if (Object.op_Implicit((Object)(object)special) && special.stock < special.maxStock)
				{
					special.rechargeStopwatch += special.finalRechargeInterval * 1f;
				}
			}
		}

		private void FireSidearmResetRevolver_ModifyBullet(orig_ModifyBullet orig, FireSidearmResetRevolver self, BulletAttack bulletAttack)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			orig.Invoke(self, bulletAttack);
			DamageAPI.AddModdedDamageType(bulletAttack, cooldownReset);
			bulletAttack.damageType = (DamageType)(bulletAttack.damageType & -5);
		}

		private void BaseFireSidearmRevolverState_OnEnter(orig_OnEnter orig, BaseFireSidearmRevolverState self)
		{
			if (self is FireSidearmResetRevolver)
			{
				self.damageCoefficient = Damage;
			}
			orig.Invoke(self);
		}

		private void Changes()
		{
			//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)
			SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Bandit2/ResetRevolver.asset").WaitForCompletion();
			val.baseRechargeInterval = Cooldown;
			val.canceledFromSprinting = false;
		}
	}
	public class SyncCooldownReduction : INetMessage, ISerializableObject
	{
		private NetworkInstanceId objID;

		private float cooldownReduction;

		public SyncCooldownReduction()
		{
		}

		public SyncCooldownReduction(NetworkInstanceId objID, float cooldownReduction)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			this.objID = objID;
			this.cooldownReduction = cooldownReduction;
		}

		public void Deserialize(NetworkReader reader)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			objID = reader.ReadNetworkId();
			cooldownReduction = reader.ReadSingle();
		}

		public void OnReceived()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (NetworkServer.active)
			{
				return;
			}
			GameObject val = Util.FindNetworkObject(objID);
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			SkillLocator component = val.GetComponent<SkillLocator>();
			if (Object.op_Implicit((Object)(object)component))
			{
				GenericSkill primary = component.primary;
				GenericSkill secondary = component.secondary;
				GenericSkill utility = component.utility;
				GenericSkill special = component.special;
				if (Object.op_Implicit((Object)(object)primary) && primary.stock < primary.maxStock)
				{
					primary.rechargeStopwatch += primary.finalRechargeInterval * cooldownReduction;
				}
				if (Object.op_Implicit((Object)(object)secondary) && secondary.stock < secondary.maxStock)
				{
					secondary.rechargeStopwatch += secondary.finalRechargeInterval * cooldownReduction;
				}
				if (Object.op_Implicit((Object)(object)utility) && utility.stock < utility.maxStock)
				{
					utility.rechargeStopwatch += utility.finalRechargeInterval * cooldownReduction;
				}
				if (Object.op_Implicit((Object)(object)special) && special.stock < special.maxStock)
				{
					special.rechargeStopwatch += special.finalRechargeInterval * 1f;
				}
			}
		}

		public void Serialize(NetworkWriter writer)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			writer.Write(objID);
			writer.Write(cooldownReduction);
		}
	}
	public class SerratedDagger : TweakBase
	{
		public static float Damage;

		public static float Cooldown;

		public static float ProcCoefficient;

		public static bool Lunge;

		public override string Name => ": Secondary : Serrated Dagger";

		public override string SkillToken => "secondary";

		public override string DescText => "<style=cIsUtility>Lunge</style> and slash for <style=cIsDamage>" + d(Damage) + " damage</style>. Critical Strikes also cause <style=cIsHealth>hemorrhaging</style>.";

		public override void Init()
		{
			Damage = ConfigOption(6f, "Damage", "Decimal. Vanilla is 3.6");
			Cooldown = ConfigOption(7f, "Cooldown", "Vanilla is 4");
			ProcCoefficient = ConfigOption(0f, "Proc Coefficient", "Vanilla is 1");
			Lunge = ConfigOption(value: true, "Enable lunge?", "Vanilla is false");
			base.Init();
		}

		public override void Hooks()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			SlashBlade.OnEnter += new hook_OnEnter(SlashBlade_OnEnter);
			Changes();
		}

		private void SlashBlade_OnEnter(orig_OnEnter orig, SlashBlade self)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0064: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			((BasicMeleeAttack)self).damageCoefficient = Damage;
			((BasicMeleeAttack)self).procCoefficient = ProcCoefficient;
			orig.Invoke(self);
			if (Lunge && ((EntityState)self).isAuthority)
			{
				Ray aimRay = ((BaseState)self).GetAimRay();
				Vector3 direction = ((Ray)(ref aimRay)).direction;
				Vector3 val = ((Vector3)(ref direction)).normalized * 2.6f * ((BaseState)self).moveSpeedStat;
				Vector3 val2 = Vector3.up * 2f;
				Vector3 val3 = new Vector3(direction.x, 0f, direction.z);
				Vector3 val4 = ((Vector3)(ref val3)).normalized * 2.6f;
				((BaseCharacterController)((EntityState)self).characterMotor).Motor.ForceUnground();
				((EntityState)self).characterMotor.velocity = val + val2 + val4;
			}
		}

		private void Changes()
		{
			//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)
			SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Bandit2/SlashBlade.asset").WaitForCompletion();
			val.baseRechargeInterval = Cooldown;
		}
	}
	public class SerratedShiv : TweakBase
	{
		public static float Damage;

		public static float Cooldown;

		public static int Charges;

		public static int ChargesToRecharge;

		public static bool Sidestep;

		public override string Name => ": Secondary :: Serrated Shiv";

		public override string SkillToken => "secondary_alt";

		public override string DescText => (Sidestep ? "<style=cIsUtility>Sidestep</style> and throw" : "Throw") + " a hidden blade for <style=cIsDamage>" + d(Damage) + " damage</style>. Critical Strikes also cause <style=cIsHealth>hemorrhaging</style>." + ((Charges > 1) ? (" <style=cIsUtility>Can hold up to " + Charges + " shivs</style>.") : "");

		public override void Init()
		{
			Damage = ConfigOption(2f, "Damage", "Decimal. Vanilla is 3.6");
			Cooldown = ConfigOption(10f, "Cooldown", "Vanilla is 4");
			Charges = ConfigOption(2, "Charges", "Vanilla is 1");
			ChargesToRecharge = ConfigOption(2, "Charges to Recharge", "Vanilla is 1");
			Sidestep = ConfigOption(value: true, "Enable sidestep?", "Vanilla is false");
			base.Init();
		}

		public override void Hooks()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			Bandit2FireShiv.OnEnter += new hook_OnEnter(Bandit2FireShiv_OnEnter);
			Changes();
		}

		private void Bandit2FireShiv_OnEnter(orig_OnEnter orig, Bandit2FireShiv self)
		{
			//IL_002f: 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_0052: 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)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: 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)
			self.damageCoefficient = Damage;
			orig.Invoke(self);
			if (Sidestep && ((EntityState)self).isAuthority)
			{
				Vector3 val = ((((EntityState)self).inputBank.moveVector == Vector3.zero) ? Vector3.zero : ((Vector3)(ref ((EntityState)self).inputBank.moveVector)).normalized);
				Vector3 velocity = ((Vector3)(ref val)).normalized * 2.5f * ((BaseState)self).moveSpeedStat;
				((BaseCharacterController)((EntityState)self).characterMotor).Motor.ForceUnground();
				((EntityState)self).characterMotor.velocity = velocity;
			}
		}

		private void Changes()
		{
			//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)
			SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Bandit2/Bandit2SerratedShivs.asset").WaitForCompletion();
			val.baseRechargeInterval = Cooldown;
			val.baseMaxStock = Charges;
			val.rechargeStock = ChargesToRecharge;
		}
	}
	public class SmokeBomb : TweakBase
	{
		public static float Cooldown;

		public static float CloakDur;

		public static float Damage;

		public static bool Ignite;

		public override string Name => ": Utility : Smoke Bomb";

		public override string SkillToken => "utility";

		public override string DescText => "<style=cIsDamage>Stunning</style>." + (Ignite ? " <style=cIsDamage>Ignite</style>." : "") + " Deal <style=cIsDamage>" + d(Damage) + " damage</style>, become <style=cIsUtility>invisible</style> for <style=cIsUtility>" + CloakDur + "</style> seconds, then deal <style=cIsDamage>" + d(Damage) + " damage</style> again.";

		public override void Init()
		{
			Cooldown = ConfigOption(8f, "Cooldown", "Vanilla is 6");
			CloakDur = ConfigOption(3f, "Cloak Duration", "Vanilla is 3");
			Damage = ConfigOption(2f, "Damage", "Decimal. Vanilla is 2");
			Ignite = ConfigOption(value: true, "Ignite?", "Vanilla is false");
			base.Init();
		}

		public override void Hooks()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected O, but got Unknown
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Expected O, but got Unknown
			StealthMode.OnEnter += new hook_OnEnter(StealthMode_OnEnter);
			if (Ignite)
			{
				StealthMode.FireSmokebomb += new Manipulator(StealthMode_FireSmokebomb);
			}
			Changes();
		}

		private void StealthMode_FireSmokebomb(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 32)
			}))
			{
				int index = val.Index;
				val.Index = index + 1;
				val.EmitDelegate<Func<int, int>>((Func<int, int>)((int useless) => 160));
			}
			else
			{
				Main.HBTLogger.LogError((object)"Failed to apply Smoke Bomb Ignite hook");
			}
		}

		private void StealthMode_OnEnter(orig_OnEnter orig, StealthMode self)
		{
			StealthMode.duration = CloakDur;
			StealthMode.blastAttackDamageCoefficient = Damage;
			orig.Invoke(self);
		}

		private void Changes()
		{
			//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)
			SkillDef val = Addressables.LoadAssetAsync<SkillDef>((object)"RoR2/Base/Bandit2/ThrowSmokebomb.asset").WaitForCompletion();
			val.baseRechargeInterval = Cooldown;
			if (Ignite)
			{
				val.keywordTokens = new string[2] { "KEYWORD_STUNNING", "KEYWORD_IGNITE" };
			}
		}
	}
}
namespace HIFUBanditTweaks.Misc
{
	public class Achievements : MiscBase
	{
		public static Hook hook;

		public static int hemoRequirement;

		public override string Name => ": Misc : Achievements";

		public override void Init()
		{
			hemoRequirement = ConfigOption(4, "Hemorrhage Required", "Vanilla is 20");
			base.Init();
		}

		public override void Hooks()
		{
			//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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Expected O, but got Unknown
			Bandit2StackSuperBleedAchievement.LookUpRequiredBodyIndex += new hook_LookUpRequiredBodyIndex(Bandit2StackSuperBleedAchievement_LookUpRequiredBodyIndex);
			Bandit2RevolverFinaleServerAchievement.DoesDamageQualify += new hook_DoesDamageQualify(Bandit2RevolverFinaleServerAchievement_DoesDamageQualify);
			hook = new Hook((MethodBase)typeof(Bandit2ConsecutiveResetServerAchievement).GetMethod("OnCharacterDeathGlobal", BindingFlags.Instance | BindingFlags.NonPublic), typeof(Achievements).GetMethod("OnKillDamageTypeHook", BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic));
			Changes();
		}

		private static void OnKillDamageTypeHook(Bandit2ConsecutiveResetServerAchievement orig, DamageReport damageReport)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Invalid comparison between Unknown and I4
			if (((Object)(object)damageReport.attackerBody == (Object)(object)orig.trackedBody && Object.op_Implicit((Object)(object)damageReport.attackerBody) && (damageReport.damageInfo.damageType & 4) == 4) || DamageAPI.HasModdedDamageType(damageReport.damageInfo, LightsOut.cooldownReset))
			{
				orig.waitingForKill = false;
				orig.progress++;
				if (orig.progress >= Bandit2ConsecutiveResetAchievement.requirement)
				{
					((BaseServerAchievement)orig).Grant();
				}
			}
		}

		private bool Bandit2RevolverFinaleServerAchievement_DoesDamageQualify(orig_DoesDamageQualify orig, BaseServerAchievement self, DamageReport damageReport)
		{
			//IL_0007: 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: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			return (damageReport.damageInfo.damageType & 4) == 4 || DamageAPI.HasModdedDamageType(damageReport.damageInfo, LightsOut.cooldownReset);
		}

		private BodyIndex Bandit2StackSuperBleedAchievement_LookUpRequiredBodyIndex(orig_LookUpRequiredBodyIndex orig, Bandit2StackSuperBleedAchievement self)
		{
			//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_0015: Unknown result type (might be due to invalid IL or missing references)
			Bandit2StackSuperBleedAchievement.requirement = hemoRequirement;
			return orig.Invoke(self);
		}

		private void Changes()
		{
			LanguageAPI.Add("ACHIEVEMENT_BANDIT2STACKSUPERBLEED_DESCRIPTION", "As Bandit, kill a monster with " + hemoRequirement + " stacks of Hemorrhage.");
		}
	}
	public class Hemorrhage : MiscBase
	{
		public static float Interval;

		public static float DamagePerTick;

		public static float TotalDuration;

		public override string Name => ": Secondary ::: Hemorrhage";

		public override void Init()
		{
			Interval = ConfigOption(0.25f, "Tick Interval", "Decimal. Vanilla is 0.25");
			DamagePerTick = ConfigOption(0.75f, "Tick Damage", "Vanilla is 0.333");
			TotalDuration = ConfigOption(4f, "Total Duration", "Vanilla is 15");
			base.Init();
		}

		public override void Hooks()
		{
			//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
			DotController.InitDotCatalog += new hook_InitDotCatalog(DotController_InitDotCatalog1);
			GlobalEventManager.OnHitEnemy += new Manipulator(GlobalEventManager_OnHitEnemy);
			GlobalEventManager.onServerDamageDealt += GlobalEventManager_onServerDamageDealt;
			Changes();
		}

		private void GlobalEventManager_OnHitEnemy(ILContext il)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			ILCursor val = new ILCursor(il);
			if (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
			{
				(Instruction x) => ILPatternMatchingExt.MatchLdcI4(x, 6),
				(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 15f)
			}))
			{
				val.Index += 1;
				val.Next.Operand = TotalDuration;
			}
			else
			{
				Main.HBTLogger.LogError((object)"Failed to apply Hemorrhage Total Duration hook");
			}
		}

		private void GlobalEventManager_onServerDamageDealt(DamageReport dr)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Invalid comparison between Unknown and I4
			DamageInfo damageInfo = dr.damageInfo;
			if (damageInfo == null)
			{
				return;
			}
			GameObject attacker = damageInfo.attacker;
			if (!((Object)(object)attacker == (Object)null))
			{
				CharacterBody component = attacker.GetComponent<CharacterBody>();
				if ((Object)(object)component != (Object)null && damageInfo.crit && damageInfo.procCoefficient == 0f && (damageInfo.damageType & 0x8000000) > 0)
				{
					DotController.InflictDot(((Component)dr.victim).gameObject, damageInfo.attacker, (DotIndex)6, TotalDuration, 1f, (uint?)uint.MaxValue);
				}
			}
		}

		private void DotController_InitDotCatalog1(orig_InitDotCatalog orig)
		{
			orig.Invoke();
			DotController.dotDefs[6].interval = Interval;
			DotController.dotDefs[6].damageCoefficient = DamagePerTick;
		}

		private void Changes()
		{
			LanguageAPI.Add("KEYWORD_SUPERBLEED", "<style=cKeywordName>Hemorrhage</style><style=cSub>Deal <style=cIsDamage>" + d(DamagePerTick / Interval * TotalDuration + TotalDuration * DamagePerTick) + "</style> base damage over " + TotalDuration + "s. <i>Hemorrhage can stack.</i></style>");
		}
	}
	public class Reload : MiscBase
	{
		public static float ReloadDur;

		public override string Name => ": Primary ::: Reload";

		public override void Init()
		{
			ReloadDur = ConfigOption(0.3f, "Reload Duration", "Vanilla is ??");
			base.Init();
		}

		public override void Hooks()
		{
			//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
			EnterReload.OnEnter += new hook_OnEnter(EnterReload_OnEnter);
			Reload.OnEnter += new hook_OnEnter(Reload_OnEnter);
		}

		private void Reload_OnEnter(orig_OnEnter orig, Reload self)
		{
			Reload.baseDuration = ReloadDur;
			orig.Invoke(self);
		}

		private void EnterReload_OnEnter(orig_OnEnter orig, EnterReload self)
		{
			EnterReload.baseDuration = ReloadDur;
			orig.Invoke(self);
		}
	}
}