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;
}
}