Decompiled source of RFFPlus v1.0.0

BepInEx\plugins\RFFPlus\RFFPlus.dll

Decompiled 2 days ago
using System;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using Agents;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Player;
using SNetwork;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("RFFPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("RFFPlus")]
[assembly: AssemblyTitle("RFFPlus")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace RFFPlus;

[HarmonyPatch(typeof(Dam_PlayerDamageLimb), "BulletDamage")]
internal static class Patch_LimbBulletDamage
{
	public static bool Prefix(Agent sourceAgent)
	{
		if (!Plugin.Cfg_IgnoreFriendlyBullets.Value)
		{
			return true;
		}
		if ((Object)(object)sourceAgent == (Object)null || (Object)(object)((Il2CppObjectBase)sourceAgent).TryCast<PlayerAgent>() == (Object)null)
		{
			return true;
		}
		return false;
	}
}
[HarmonyPatch(typeof(Dam_PlayerDamageBase), "ReceiveBulletDamage")]
internal static class Patch_BaseReceiveBulletDamage
{
	public static void Prefix(ref pBulletDamageData data)
	{
		ReflectPatches.HandleIncomingBulletDamage(ref data);
	}
}
[HarmonyPatch(typeof(Dam_PlayerDamageLocal), "ReceiveBulletDamage")]
internal static class Patch_LocalReceiveBulletDamage
{
	public static void Prefix(ref pBulletDamageData data)
	{
		ReflectPatches.HandleIncomingBulletDamage(ref data);
	}
}
internal static class ReflectPatches
{
	internal static bool IsSentryFire;

	internal static PlayerAgent SentryOwner;

	public static void HandleIncomingBulletDamage(ref pBulletDamageData data)
	{
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		//IL_005b: Expected O, but got Unknown
		if (!Plugin.Cfg_ReflectEnabled.Value || !SNet.IsMaster)
		{
			return;
		}
		PlayerAgent val;
		if (IsSentryFire)
		{
			val = SentryOwner;
		}
		else
		{
			Agent val2 = default(Agent);
			if (!((pAgent)(ref data.source)).TryGet(ref val2) || (Object)(object)val2 == (Object)null)
			{
				return;
			}
			val = ((Il2CppObjectBase)val2).TryCast<PlayerAgent>();
		}
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Dam_SyncedDamageBase val3 = (Dam_SyncedDamageBase)val.Damage;
		if ((Object)(object)val3 == (Object)null)
		{
			return;
		}
		float healthMax = val3.HealthMax;
		float num = ((UFloat16)(ref data.damage)).Get(healthMax);
		if (!(num <= 0f))
		{
			((UFloat16)(ref data.damage)).Set(num * Plugin.Cfg_FFMulti.Value, healthMax);
			float num2 = Math.Clamp(num * Plugin.Cfg_ReflectMulti.Value, 0f, healthMax);
			float num3 = Math.Clamp(val3.Health - num2, Plugin.Cfg_ReflectToDeath.Value ? 0f : 0.001f, healthMax);
			val3.SendSetHealth(num3);
			if (num3 == 0f && Plugin.Cfg_ReflectToDeath.Value)
			{
				val3.SendSetDead(true);
			}
		}
	}
}
[HarmonyPatch(typeof(SentryGunInstance_Firing_Bullets), "FireBullet")]
internal static class Patch_SentryFireBullet
{
	public static void Prefix(SentryGunInstance_Firing_Bullets __instance)
	{
		if (SNet.IsMaster)
		{
			ReflectPatches.IsSentryFire = true;
			iSentrygunInstanceCore core = __instance.m_core;
			ReflectPatches.SentryOwner = ((core != null) ? core.Owner : null);
		}
	}

	public static void Postfix()
	{
		if (SNet.IsMaster)
		{
			ReflectPatches.IsSentryFire = false;
			ReflectPatches.SentryOwner = null;
		}
	}
}
[HarmonyPatch(typeof(SentryGunInstance_Firing_Bullets), "UpdateFireShotgunSemi")]
internal static class Patch_SentryUpdateFireShotgunSemi
{
	public static void Prefix(SentryGunInstance_Firing_Bullets __instance)
	{
		if (SNet.IsMaster)
		{
			ReflectPatches.IsSentryFire = true;
			iSentrygunInstanceCore core = __instance.m_core;
			ReflectPatches.SentryOwner = ((core != null) ? core.Owner : null);
		}
	}

	public static void Postfix()
	{
		if (SNet.IsMaster)
		{
			ReflectPatches.IsSentryFire = false;
			ReflectPatches.SentryOwner = null;
		}
	}
}
[BepInPlugin("RFFPlus", "ReverseFriendlyFire Plus (Standalone)", "1.0.0")]
public class Plugin : BasePlugin
{
	internal static ConfigEntry<bool> Cfg_IgnoreFriendlyBullets;

	internal static ConfigEntry<bool> Cfg_ReflectEnabled;

	internal static ConfigEntry<float> Cfg_FFMulti;

	internal static ConfigEntry<float> Cfg_ReflectMulti;

	internal static ConfigEntry<bool> Cfg_ReflectToDeath;

	private Harmony _harmony;

	private static FileSystemWatcher _cfgWatcher;

	private static DateTime _lastReloadAt = DateTime.MinValue;

	private static readonly object _reloadLock = new object();

	public override void Load()
	{
		//IL_006e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0078: Expected O, but got Unknown
		//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: 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
		Cfg_IgnoreFriendlyBullets = ((BasePlugin)this).Config.Bind<bool>("免伤模式 (任何端生效)", "启用玩家子弹免伤", true, "玩家(含哨戒炮)的子弹不再对玩家造成伤害。任何端装了本插件都对自己的开火生效,主机安装则对全队生效。");
		Cfg_ReflectEnabled = ((BasePlugin)this).Config.Bind<bool>("反伤模式 (主机生效)", "启用友伤反伤", true, "主机权威:友方子弹伤害先按友伤倍率缩放,再按反伤倍率反噬开枪者。");
		Cfg_FFMulti = ((BasePlugin)this).Config.Bind<float>("反伤模式 (主机生效)", "友伤倍率", 0f, new ConfigDescription("被队友打到的实际承伤倍率,0 = 队友不掉血", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
		Cfg_ReflectMulti = ((BasePlugin)this).Config.Bind<float>("反伤模式 (主机生效)", "反伤倍率", 1f, new ConfigDescription("按原始伤害值反噬开枪者的倍率", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>()));
		Cfg_ReflectToDeath = ((BasePlugin)this).Config.Bind<bool>("反伤模式 (主机生效)", "反伤致死", true, "反伤足以耗尽开枪者血量时,直接将其击杀");
		StartConfigWatcher();
		_harmony = new Harmony("RFFPlus");
		_harmony.PatchAll(typeof(Plugin).Assembly);
		((BasePlugin)this).Log.LogInfo((object)("[RFFPlus] 加载完成:免伤=" + Cfg_IgnoreFriendlyBullets.Value + " 反伤=" + Cfg_ReflectEnabled.Value + " (友伤倍率=" + Cfg_FFMulti.Value + " 反伤倍率=" + Cfg_ReflectMulti.Value + " 反伤致死=" + Cfg_ReflectToDeath.Value + ")"));
	}

	private void StartConfigWatcher()
	{
		try
		{
			string configFilePath = ((BasePlugin)this).Config.ConfigFilePath;
			string? directoryName = Path.GetDirectoryName(configFilePath);
			string fileName = Path.GetFileName(configFilePath);
			_cfgWatcher = new FileSystemWatcher(directoryName, fileName)
			{
				NotifyFilter = (NotifyFilters.Size | NotifyFilters.LastWrite)
			};
			_cfgWatcher.Changed += OnConfigFileChanged;
			_cfgWatcher.EnableRaisingEvents = true;
			((BasePlugin)this).Log.LogInfo((object)("[RFFPlus] 配置热重载监视已启动: " + configFilePath));
		}
		catch (Exception ex)
		{
			((BasePlugin)this).Log.LogWarning((object)("[RFFPlus] 配置监视启动失败(热重载不可用,但不影响功能): " + ex.Message));
		}
	}

	private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
	{
		lock (_reloadLock)
		{
			if ((DateTime.Now - _lastReloadAt).TotalMilliseconds < 300.0)
			{
				return;
			}
			_lastReloadAt = DateTime.Now;
		}
		try
		{
			((BasePlugin)this).Config.Reload();
			((BasePlugin)this).Log.LogInfo((object)("[RFFPlus] 配置已热重载: 免伤=" + Cfg_IgnoreFriendlyBullets.Value + " 反伤=" + Cfg_ReflectEnabled.Value + " (友伤倍率=" + Cfg_FFMulti.Value + " 反伤倍率=" + Cfg_ReflectMulti.Value + " 反伤致死=" + Cfg_ReflectToDeath.Value + ")"));
		}
		catch (Exception ex)
		{
			((BasePlugin)this).Log.LogWarning((object)("[RFFPlus] 配置热重载失败: " + ex.Message));
		}
	}

	public override bool Unload()
	{
		_cfgWatcher?.Dispose();
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		return true;
	}
}