Decompiled source of CrewShield v1.0.0

BepInEx/plugins/CrewShield/CrewShield.dll

Decompiled a day ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using GameNetcodeStuff;
using HarmonyLib;
using UnityEngine;

[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace CrewShield;

[BepInPlugin("local.crewshield", "Crew Shield", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string Guid = "local.crewshield";

	internal static ConfigEntry<bool> DisableFriendlyFire;

	private Harmony harmony;

	internal static bool Disabled
	{
		get
		{
			if (DisableFriendlyFire != null)
			{
				return DisableFriendlyFire.Value;
			}
			return false;
		}
	}

	private void Awake()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		DisableFriendlyFire = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "DisableFriendlyFire", true, "Block direct damage from teammates. Monsters and hazards remain lethal. Set the same value on every player's installation.");
		harmony = new Harmony("local.crewshield");
		try
		{
			harmony.PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)("Crew Shield 1.0.0 loaded. DisableFriendlyFire=" + DisableFriendlyFire.Value));
		}
		catch (Exception ex)
		{
			harmony.UnpatchSelf();
			((BaseUnityPlugin)this).Logger.LogError((object)("Crew Shield could not patch this game version; patches removed. " + ex));
		}
	}

	private void OnDestroy()
	{
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	internal static bool IsTeammateHit(PlayerControllerB victim, int attackerIndex, int damage)
	{
		StartOfRound instance = StartOfRound.Instance;
		if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null || attackerIndex < 0 || attackerIndex >= instance.allPlayerScripts.Length)
		{
			return false;
		}
		PlayerControllerB val = instance.allPlayerScripts[attackerIndex];
		return DamagePolicy.BlockPlayerHit(Disabled, damage, (Object)(object)val != (Object)null, ((Object)(object)val != (Object)null) ? val.playerClientId : 0, victim.playerClientId);
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayerFromOtherClientServerRpc")]
internal static class PlayerHitServerPatch
{
	private static void Prefix(PlayerControllerB __instance, ref int damageAmount, ref Vector3 hitDirection, int playerWhoHit)
	{
		//IL_0010: 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)
		if (Plugin.IsTeammateHit(__instance, playerWhoHit, damageAmount))
		{
			damageAmount = 0;
			hitDirection = Vector3.zero;
		}
	}
}
internal static class DamageContext
{
	[ThreadStatic]
	internal static bool TeammateRpc;

	[ThreadStatic]
	internal static ShotgunItem Shotgun;
}
[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayerFromOtherClientClientRpc")]
internal static class PlayerHitClientPatch
{
	private static void Prefix(PlayerControllerB __instance, ref int damageAmount, ref Vector3 hitDirection, int playerWhoHit, ref int newHealthAmount, out bool __state)
	{
		//IL_0020: 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)
		__state = DamageContext.TeammateRpc;
		if (DamageContext.TeammateRpc = Plugin.IsTeammateHit(__instance, playerWhoHit, damageAmount))
		{
			damageAmount = 0;
			hitDirection = Vector3.zero;
			newHealthAmount = __instance.health;
		}
	}

	private static void Finalizer(bool __state)
	{
		DamageContext.TeammateRpc = __state;
	}
}
[HarmonyPatch(typeof(ShotgunItem), "ShootGun")]
internal static class ShotgunContextPatch
{
	private static void Prefix(ShotgunItem __instance, out ShotgunItem __state)
	{
		__state = DamageContext.Shotgun;
		DamageContext.Shotgun = __instance;
	}

	private static void Finalizer(ShotgunItem __state)
	{
		DamageContext.Shotgun = __state;
	}
}
[HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")]
internal static class ScopedDamagePatch
{
	private static bool Prefix(PlayerControllerB __instance, int damageNumber)
	{
		if (!Plugin.Disabled || damageNumber < 0)
		{
			return true;
		}
		if (DamageContext.TeammateRpc)
		{
			return false;
		}
		ShotgunItem shotgun = DamageContext.Shotgun;
		if ((Object)(object)shotgun == (Object)null)
		{
			return true;
		}
		PlayerControllerB playerHeldBy = ((GrabbableObject)shotgun).playerHeldBy;
		bool flag = DamagePolicy.BlockShotgun(Plugin.Disabled, damageNumber, ((GrabbableObject)shotgun).isHeld, ((GrabbableObject)shotgun).isHeldByEnemy, (Object)(object)playerHeldBy != (Object)null, ((Object)(object)playerHeldBy != (Object)null) ? playerHeldBy.playerClientId : 0, __instance.playerClientId);
		return !flag;
	}
}
internal static class DamagePolicy
{
	internal static bool BlockPlayerHit(bool disabled, int damage, bool attackerKnown, ulong attacker, ulong victim)
	{
		if (disabled && damage >= 0 && attackerKnown)
		{
			return attacker != victim;
		}
		return false;
	}

	internal static bool BlockShotgun(bool disabled, int damage, bool playerHeld, bool enemyHeld, bool attackerKnown, ulong attacker, ulong victim)
	{
		if (playerHeld && !enemyHeld)
		{
			return BlockPlayerHit(disabled, damage, attackerKnown, attacker, victim);
		}
		return false;
	}
}