Decompiled source of PoisonGuns v1.1.2

PoisonGuns.dll

Decompiled 17 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using LevelEditor;
using TMPro;
using UnityEngine;
using WeaponFramework;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("PoisonGuns")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.2.0")]
[assembly: AssemblyInformationalVersion("1.1.2")]
[assembly: AssemblyProduct("PoisonGuns")]
[assembly: AssemblyTitle("PoisonGuns")]
[assembly: AssemblyVersion("1.1.2.0")]
namespace PoisonGuns;

internal static class FrameworkBridge
{
	private static readonly string[,] names = new string[6, 3]
	{
		{ "vanilla.snakegun", "SNAKE GUN", "POISON GUN" },
		{ "vanilla.snakeshotgun", "SNAKE SHOTGUN", "POISON SHOTGUN" },
		{ "vanilla.snakegrenade", "SNAKE GRENADE", "POISON GRENADE" },
		{ "vanilla.snakelauncher", "SNAKE LAUNCHER", "POISON LAUNCHER" },
		{ "vanilla.snakeminigun", "SNAKE MINIGUN", "POISON MINIGUN" },
		{ "vanilla.flyingsnake", "FLYING SNAKE", "FLYING POISON" }
	};

	private static readonly Dictionary<string, int> gameTickets = new Dictionary<string, int>();

	public static void Start()
	{
		WeaponRegistry.Ready += Apply;
		EventHandler eventHandler = delegate
		{
			Apply();
		};
		Plugin.ReplaceSnakeGuns.SettingChanged += eventHandler;
		Plugin.RenameSnakeToPoison.SettingChanged += eventHandler;
		Plugin.LauncherMatchesRpgRarity.SettingChanged += eventHandler;
		Plugin.SeekerMatchesRpgRarity.SettingChanged += eventHandler;
	}

	private static void Apply()
	{
		try
		{
			bool value = Plugin.ReplaceSnakeGuns.Value;
			bool flag = value && Plugin.RenameSnakeToPoison.Value;
			for (int i = 0; i < names.GetLength(0); i++)
			{
				WeaponRegistry.SetName(names[i, 0], flag ? names[i, 2] : names[i, 1]);
			}
			WeaponRegistry.SetCategoryName("snake", flag ? "POISON" : "SNAKE");
			WeaponInfo val = WeaponRegistry.Get("vanilla.rpg");
			int rpgTickets = ((val != null) ? val.DefaultTickets : 2);
			Tickets("vanilla.snakelauncher", value && Plugin.LauncherMatchesRpgRarity.Value, rpgTickets);
			Tickets("vanilla.flyingsnake", value && Plugin.SeekerMatchesRpgRarity.Value, rpgTickets);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Couldn't update Weapon Framework's weapon list: " + ex));
		}
	}

	private static void Tickets(string id, bool rpgRare, int rpgTickets)
	{
		WeaponInfo val = WeaponRegistry.Get(id);
		if (val != null)
		{
			if (!gameTickets.TryGetValue(id, out var value))
			{
				value = val.DefaultTickets;
				gameTickets[id] = value;
			}
			WeaponRegistry.SetDefaultTickets(id, rpgRare ? rpgTickets : value);
		}
	}
}
internal static class MenuRename
{
	[HarmonyPatch(typeof(WeaponSelectionHandler), "Start")]
	private static class WeaponMenuStart
	{
		[HarmonyPostfix]
		private static void Postfix(WeaponSelectionHandler __instance)
		{
			if (Plugin.WithFramework)
			{
				return;
			}
			s_Handler = __instance;
			if (!Wanted)
			{
				return;
			}
			try
			{
				Apply(__instance, rename: true);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to rename weapon menu: " + ex));
			}
		}
	}

	[HarmonyPatch(typeof(WeaponSelectionHandler), "ToggleWeaponActive")]
	private static class ToggleWeaponFix
	{
		[HarmonyPrefix]
		private static void Prefix(ref string weaponName, List<SingleWeaponUI> ___m_Weapons)
		{
			if (___m_Weapons != null)
			{
				foreach (SingleWeaponUI ___m_Weapon in ___m_Weapons)
				{
					if (string.Equals(___m_Weapon.WeaponName, weaponName, StringComparison.OrdinalIgnoreCase))
					{
						return;
					}
				}
			}
			weaponName = Original(weaponName);
		}
	}

	[HarmonyPatch(typeof(WeaponSelectionHandler), "ToggleCategoryActive")]
	private static class ToggleCategoryFix
	{
		[HarmonyPrefix]
		private static void Prefix(ref string categoryName)
		{
			categoryName = Original(categoryName);
		}
	}

	[HarmonyPatch(typeof(GunButtonUI), "Init")]
	private static class GunButtonFix
	{
		[HarmonyPostfix]
		private static void Postfix(GunButtonUI __instance)
		{
			if (Plugin.RenameSnakeToPoison.Value && Plugin.ReplaceSnakeGuns.Value)
			{
				TextMeshProUGUI componentInChildren = ((Component)__instance).GetComponentInChildren<TextMeshProUGUI>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((TMP_Text)componentInChildren).text = Rename(((TMP_Text)componentInChildren).text);
				}
			}
		}
	}

	private static readonly Dictionary<string, string> s_Originals = new Dictionary<string, string>();

	private static readonly string[,] s_Pairs = new string[6, 2]
	{
		{ "SNAKES", "POISON" },
		{ "Snakes", "Poison" },
		{ "snakes", "poison" },
		{ "SNAKE", "POISON" },
		{ "Snake", "Poison" },
		{ "snake", "poison" }
	};

	private static readonly FieldRef<WeaponSelectionHandler, List<SingleWeaponUI>> s_MenuWeapons = AccessTools.FieldRefAccess<WeaponSelectionHandler, List<SingleWeaponUI>>("m_Weapons");

	private static WeaponSelectionHandler s_Handler;

	private static bool Wanted
	{
		get
		{
			if (Plugin.RenameSnakeToPoison.Value)
			{
				return Plugin.ReplaceSnakeGuns.Value;
			}
			return false;
		}
	}

	internal static string Rename(string text)
	{
		if (string.IsNullOrEmpty(text) || text.IndexOf("snake", StringComparison.OrdinalIgnoreCase) < 0)
		{
			return text;
		}
		string text2 = text;
		for (int i = 0; i < s_Pairs.GetLength(0); i++)
		{
			text2 = text2.Replace(s_Pairs[i, 0], s_Pairs[i, 1]);
		}
		if (text2 != text)
		{
			s_Originals[text2] = text;
		}
		return text2;
	}

	internal static string Original(string text)
	{
		if (text == null || !s_Originals.TryGetValue(text, out var value))
		{
			return text;
		}
		return value;
	}

	private static void Apply(WeaponSelectionHandler handler, bool rename)
	{
		TextMeshProUGUI[] componentsInChildren = ((Component)handler).GetComponentsInChildren<TextMeshProUGUI>(true);
		foreach (TextMeshProUGUI val in componentsInChildren)
		{
			string text = Shown(((TMP_Text)val).text, rename);
			if (text != ((TMP_Text)val).text)
			{
				((TMP_Text)val).text = text;
			}
		}
		List<SingleWeaponUI> list = s_MenuWeapons.Invoke(handler);
		if (list == null)
		{
			return;
		}
		foreach (SingleWeaponUI item in list)
		{
			item.WeaponName = Shown(item.WeaponName, rename);
		}
	}

	private static string Shown(string text, bool rename)
	{
		string text2 = Original(text);
		if (!rename)
		{
			return text2;
		}
		return Rename(text2);
	}

	internal static void Relabel()
	{
		if (Plugin.WithFramework || (Object)(object)s_Handler == (Object)null)
		{
			return;
		}
		try
		{
			Apply(s_Handler, Wanted);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Failed to rename weapon menu: " + ex));
		}
	}
}
[BepInPlugin("stickfight.poisonguns", "PoisonGuns", "1.1.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
	public const string Guid = "stickfight.poisonguns";

	public const string Name = "PoisonGuns";

	public const string Version = "1.1.2";

	private const string FrameworkGuid = "stickfight.weaponframework";

	internal static bool WithFramework;

	internal static ManualLogSource Log;

	internal static ConfigEntry<bool> ReplaceSnakeGuns;

	internal static ConfigEntry<bool> RenameSnakeToPoison;

	internal static ConfigEntry<string> TemplateWeapon;

	internal static ConfigEntry<bool> LogWeaponList;

	internal static ConfigEntry<string> BulletColor;

	internal static ConfigEntry<float> BulletSpeed;

	internal static ConfigEntry<float> BulletOrbSize;

	internal static ConfigEntry<float> BulletLifetime;

	internal static ConfigEntry<float> ImpactDamageMultiplier;

	internal static ConfigEntry<float> PoisonDamageMultiplier;

	internal static ConfigEntry<float> MinigunRecoilMultiplier;

	internal static ConfigEntry<float> ShotgunPelletSpread;

	internal static ConfigEntry<float> RocketModelScale;

	internal static ConfigEntry<float> RocketSpinSpeed;

	internal static ConfigEntry<bool> LauncherMatchesRpgRarity;

	internal static ConfigEntry<bool> SeekerMatchesRpgRarity;

	internal static ConfigEntry<float> RocketSpeed;

	internal static ConfigEntry<float> RocketOrbSize;

	internal static ConfigEntry<float> RocketImpactDamage;

	internal static ConfigEntry<float> RocketBlastPoison;

	internal static ConfigEntry<float> RocketBlastRadius;

	internal static ConfigEntry<float> SeekerSpeed;

	internal static ConfigEntry<float> SeekerOrbSize;

	internal static ConfigEntry<float> SeekerImpactDamage;

	internal static ConfigEntry<float> SeekerBlastPoison;

	internal static ConfigEntry<float> SeekerBlastRadius;

	internal static ConfigEntry<float> SeekerTurnRate;

	internal static ConfigEntry<float> SeekerRange;

	internal static ConfigEntry<float> GrenadeBlastPoison;

	internal static ConfigEntry<float> GrenadeBlastRadius;

	internal static ConfigEntry<bool> BlastHitsShooter;

	internal static ConfigEntry<float> PoisonDuration;

	internal static ConfigEntry<float> PoisonTickInterval;

	internal static ConfigEntry<int> MaxStackedDoses;

	internal static ConfigEntry<bool> PoisonParticles;

	internal static Color ParsedColor = new Color(0.33f, 1f, 0.2f, 1f);

	private void Awake()
	{
		//IL_04a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
		//IL_054f: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		ReplaceSnakeGuns = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "ReplaceSnakeGuns", true, "Replace the snakes fired by snake weapons with poison projectiles. Snakes spawned by maps are never touched.");
		RenameSnakeToPoison = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "RenameSnakeToPoison", true, "Show 'Poison' instead of 'Snake' in the weapon menus (only while ReplaceSnakeGuns is on).");
		TemplateWeapon = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TemplateWeapon", "Pistol", "Name (or part of the name) of the gun whose bullet is copied to make poison bullets.");
		LogWeaponList = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "LogWeaponList", true, "Write every weapon and what it fires to the BepInEx log once per launch.");
		BulletColor = ((BaseUnityPlugin)this).Config.Bind<string>("General", "Color", "#55FF33", "Colour of all poison projectiles and effects, as an HTML hex colour.");
		BulletSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonBullet", "Speed", 14f, "Used by the Poison Gun, Poison Minigun and each Poison Shotgun pellet. A normal pistol bullet is 120.");
		BulletOrbSize = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonBullet", "OrbSize", 0.35f, "Diameter of the glowing ball at the front of the bullet.");
		BulletLifetime = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonBullet", "Lifetime", 10f, "Seconds before a poison projectile that hit nothing disappears.");
		ImpactDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonBullet", "ImpactDamage", 0.5f, "Damage dealt instantly on hit. Damage values are multiples of one normal pistol bullet.");
		PoisonDamageMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonBullet", "PoisonDamage", 1f, "Damage dealt over time after a hit. Damage values are multiples of one normal pistol bullet.");
		MinigunRecoilMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonBullet", "MinigunRecoilMultiplier", 1.6f, "Recoil of the Poison Minigun compared to the original Snake Minigun.");
		ShotgunPelletSpread = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonBullet", "ShotgunPelletSpread", 7f, "Random spread, in degrees, added to each Poison Shotgun pellet. The game's normal shotguns use 7.");
		RocketSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonRocket", "Speed", 7f, "Poison Launcher projectile speed.");
		RocketModelScale = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonRocket", "SizeVsRPG", 1f, "Size of the poison rocket compared to the RPG's rocket. 1 = identical.");
		LauncherMatchesRpgRarity = ((BaseUnityPlugin)this).Config.Bind<bool>("PoisonRocket", "SameRarityAsRPG", true, "Make the Poison Launcher spawn as rarely as the RPG (the Snake Launcher is normally as common as the pistol). Local play only.");
		RocketSpinSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonRocket", "SpinSpeed", 401f, "How fast the rocket rolls, in degrees per second. 401 matches the RPG rocket.");
		RocketOrbSize = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonRocket", "OrbSize", 1f, "Diameter of the fallback ball, only used if the RPG rocket model can't be found.");
		RocketImpactDamage = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonRocket", "ImpactDamage", 1f, "Instant damage to a player hit directly. Damage values are multiples of one normal pistol bullet.");
		RocketBlastPoison = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonRocket", "BlastPoison", 2f, "Poison given to everyone in the blast (half at the edge). Damage values are multiples of one normal pistol bullet.");
		RocketBlastRadius = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonRocket", "BlastRadius", 4f, "Blast radius.");
		SeekerSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonSeeker", "Speed", 8f, "Flying Poison projectile speed.");
		SeekerOrbSize = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonSeeker", "OrbSize", 0.8f, "Diameter of the seeker's ball.");
		SeekerImpactDamage = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonSeeker", "ImpactDamage", 0.75f, "Instant damage to a player hit directly. Damage values are multiples of one normal pistol bullet.");
		SeekerBlastPoison = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonSeeker", "BlastPoison", 1.5f, "Poison given to everyone in the blast (half at the edge). Damage values are multiples of one normal pistol bullet.");
		SeekerBlastRadius = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonSeeker", "BlastRadius", 3f, "Blast radius.");
		SeekerMatchesRpgRarity = ((BaseUnityPlugin)this).Config.Bind<bool>("PoisonSeeker", "SameRarityAsRPG", true, "Make the Flying Poison spawn as rarely as the RPG (the Flying Snake is normally as common as the pistol). Local play only.");
		SeekerTurnRate = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonSeeker", "TurnRate", 45f, "How hard it homes, in degrees per second. Higher = sharper turns.");
		SeekerRange = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonSeeker", "HomingRange", 40f, "Only players closer than this are chased.");
		GrenadePoisonDefaults();
		BlastHitsShooter = ((BaseUnityPlugin)this).Config.Bind<bool>("PoisonEffect", "SelfDamage", true, "Whether your own poison blasts (launcher, seeker, grenade) poison you too, like normal explosions do.");
		PoisonDuration = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonEffect", "Duration", 3f, "Seconds the poison takes to deal its damage. Another hit adds more poison and restarts the timer.");
		PoisonTickInterval = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonEffect", "TickInterval", 0.5f, "Seconds between poison damage ticks.");
		MaxStackedDoses = ((BaseUnityPlugin)this).Config.Bind<int>("PoisonEffect", "MaxStackedDoses", 3, "Most hits' worth of poison a player can have stored at once.");
		PoisonParticles = ((BaseUnityPlugin)this).Config.Bind<bool>("PoisonEffect", "Particles", true, "Puff green particles from a poisoned player on every tick.");
		Color parsedColor = default(Color);
		if (ColorUtility.TryParseHtmlString(BulletColor.Value, ref parsedColor))
		{
			ParsedColor = parsedColor;
		}
		else
		{
			Log.LogWarning((object)("Could not read Color '" + BulletColor.Value + "', using default green."));
		}
		EventHandler eventHandler = delegate
		{
			RarityFix.Rebuild();
		};
		ReplaceSnakeGuns.SettingChanged += eventHandler;
		LauncherMatchesRpgRarity.SettingChanged += eventHandler;
		SeekerMatchesRpgRarity.SettingChanged += eventHandler;
		EventHandler eventHandler2 = delegate
		{
			MenuRename.Relabel();
		};
		ReplaceSnakeGuns.SettingChanged += eventHandler2;
		RenameSnakeToPoison.SettingChanged += eventHandler2;
		new Harmony("stickfight.poisonguns").PatchAll(typeof(Plugin).Assembly);
		WithFramework = Chainloader.PluginInfos.ContainsKey("stickfight.weaponframework");
		if (WithFramework)
		{
			FrameworkBridge.Start();
		}
		Log.LogInfo((object)("PoisonGuns 1.1.2 loaded" + (WithFramework ? " (with Weapon Framework)." : ".")));
	}

	private void GrenadePoisonDefaults()
	{
		GrenadeBlastPoison = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonGrenade", "BlastPoison", 2f, "Poison given to everyone in the blast (half at the edge). Damage values are multiples of one normal pistol bullet.");
		GrenadeBlastRadius = ((BaseUnityPlugin)this).Config.Bind<float>("PoisonGrenade", "BlastRadius", 4.5f, "Blast radius.");
	}
}
public class PoisonBullet : MonoBehaviour
{
	public const string HitMessage = "PoisonGunsHit";

	public float poisonDamage;

	private void PoisonGunsHit(Rigidbody rig)
	{
		if (!((Object)(object)rig == (Object)null) && !(poisonDamage <= 0f))
		{
			BodyPart component = ((Component)rig).GetComponent<BodyPart>();
			if (!((Object)(object)component == (Object)null) && !component.isGun && !((Object)(object)component.health == (Object)null))
			{
				ProjectileCollision component2 = ((Component)this).GetComponent<ProjectileCollision>();
				PoisonEffect.Apply(component.health, ((Object)(object)component2 != (Object)null) ? component2.damager : null, poisonDamage);
			}
		}
	}
}
public class PoisonProjectile : MonoBehaviour
{
	public GameObject orb;

	public float blastRadius;

	public float blastPoison;

	public GameObject blastVisual;

	private RayCastForward m_Mover;

	private ProjectileCollision m_Collision;

	private bool m_Finished;

	private void Start()
	{
		m_Mover = ((Component)this).GetComponent<RayCastForward>();
		m_Collision = ((Component)this).GetComponent<ProjectileCollision>();
	}

	private void LateUpdate()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		if (!m_Finished && !((Object)(object)m_Mover == (Object)null) && !((Behaviour)m_Mover).enabled)
		{
			m_Finished = true;
			if ((Object)(object)orb != (Object)null)
			{
				orb.SetActive(false);
			}
			if (blastRadius > 0f)
			{
				PoisonBlast.Trigger(((Component)this).transform.position, ((Object)(object)m_Collision != (Object)null) ? m_Collision.damager : null, blastRadius, blastPoison, blastVisual);
			}
		}
	}
}
public class PoisonSpin : MonoBehaviour
{
	public float degreesPerSecond = 401f;

	private void Update()
	{
		((Component)this).transform.Rotate(0f, 0f, degreesPerSecond * Time.deltaTime, (Space)1);
	}
}
public class PoisonHoming : MonoBehaviour
{
	public float turnRate = 45f;

	public float range = 40f;

	private RayCastForward m_Mover;

	private ProjectileCollision m_Collision;

	private Transform m_Target;

	private float m_Retarget;

	private static readonly Dictionary<Controller, Transform> s_Torsos = new Dictionary<Controller, Transform>();

	private void Start()
	{
		m_Mover = ((Component)this).GetComponent<RayCastForward>();
		m_Collision = ((Component)this).GetComponent<ProjectileCollision>();
	}

	private void FixedUpdate()
	{
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//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_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_009e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_Mover == (Object)null || !((Behaviour)m_Mover).enabled)
		{
			return;
		}
		m_Retarget -= Time.fixedDeltaTime;
		if (m_Retarget <= 0f)
		{
			m_Retarget = 0.2f;
			m_Target = FindTarget();
		}
		if (!((Object)(object)m_Target == (Object)null))
		{
			Vector3 val = m_Target.position - ((Component)this).transform.position;
			val.x = 0f;
			if (!(((Vector3)(ref val)).sqrMagnitude < 0.001f))
			{
				Vector3 forward = ((Component)this).transform.forward;
				forward.x = 0f;
				Vector3 val2 = Vector3.RotateTowards(((Vector3)(ref forward)).normalized, ((Vector3)(ref val)).normalized, turnRate * ((float)Math.PI / 180f) * Time.fixedDeltaTime, 0f);
				((Component)this).transform.rotation = Quaternion.LookRotation(val2);
			}
		}
	}

	private Transform FindTarget()
	{
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: 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_00bb: Unknown result type (might be due to invalid IL or missing references)
		GameManager instance = GameManager.Instance;
		if ((Object)(object)instance == (Object)null || instance.playersAlive == null)
		{
			return null;
		}
		Controller val = (((Object)(object)m_Collision != (Object)null) ? m_Collision.damager : null);
		Transform result = null;
		float num = range * range;
		foreach (Controller item in instance.playersAlive)
		{
			if ((Object)(object)item == (Object)null || (Object)(object)item == (Object)(object)val)
			{
				continue;
			}
			CharacterInformation component = ((Component)item).GetComponent<CharacterInformation>();
			if ((Object)(object)component != (Object)null && component.isDead)
			{
				continue;
			}
			Transform val2 = TorsoOf(item);
			if (!((Object)(object)val2 == (Object)null))
			{
				Vector3 val3 = val2.position - ((Component)this).transform.position;
				val3.x = 0f;
				if (((Vector3)(ref val3)).sqrMagnitude < num)
				{
					num = ((Vector3)(ref val3)).sqrMagnitude;
					result = val2;
				}
			}
		}
		return result;
	}

	private static Transform TorsoOf(Controller c)
	{
		if (s_Torsos.TryGetValue(c, out var value) && (Object)(object)value != (Object)null)
		{
			return value;
		}
		if (s_Torsos.Count >= 16)
		{
			PruneTorsos();
		}
		Torso componentInChildren = ((Component)c).GetComponentInChildren<Torso>();
		value = (((Object)(object)componentInChildren != (Object)null) ? ((Component)componentInChildren).transform : ((Component)c).transform);
		s_Torsos[c] = value;
		return value;
	}

	private static void PruneTorsos()
	{
		List<Controller> list = new List<Controller>();
		foreach (KeyValuePair<Controller, Transform> s_Torso in s_Torsos)
		{
			if ((Object)(object)s_Torso.Key == (Object)null || (Object)(object)s_Torso.Value == (Object)null)
			{
				list.Add(s_Torso.Key);
			}
		}
		foreach (Controller item in list)
		{
			s_Torsos.Remove(item);
		}
	}
}
public class PoisonGrenade : MonoBehaviour
{
	public float fuse = 2f;

	public float blastRadius;

	public float blastPoison;

	public GameObject blastVisual;

	private Controller m_Damager;

	private bool m_Done;

	private void Start()
	{
		SpawnObjectAfterDelay component = ((Component)this).GetComponent<SpawnObjectAfterDelay>();
		if ((Object)(object)component != (Object)null)
		{
			m_Damager = component.damager;
			((Behaviour)component).enabled = false;
		}
		RandomValue component2 = ((Component)this).GetComponent<RandomValue>();
		if ((Object)(object)component2 != (Object)null && component2.value > 0f)
		{
			fuse *= component2.value;
		}
	}

	private void Update()
	{
		//IL_0036: Unknown result type (might be due to invalid IL or missing references)
		if (!m_Done)
		{
			fuse -= Time.deltaTime;
			if (!(fuse > 0f))
			{
				m_Done = true;
				PoisonBlast.Trigger(((Component)this).transform.position, m_Damager, blastRadius, blastPoison, blastVisual);
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}
	}
}
internal static class PoisonBlast
{
	public static void Trigger(Vector3 pos, Controller damager, float radius, float poison, GameObject visual)
	{
		//IL_0018: Unknown result type (might be due to invalid IL or missing references)
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		pos.x = 0f;
		if ((Object)(object)visual != (Object)null)
		{
			ScaleParticles(Object.Instantiate<GameObject>(visual, pos, Quaternion.identity), Mathf.Max(0.3f, radius / 4f));
		}
		if (poison <= 0f || radius <= 0f)
		{
			return;
		}
		Dictionary<HealthHandler, float> dictionary = new Dictionary<HealthHandler, float>();
		Collider[] array = Physics.OverlapSphere(pos, radius);
		foreach (Collider val in array)
		{
			if ((Object)(object)val == (Object)null)
			{
				continue;
			}
			BodyPart componentInParent = ((Component)val).GetComponentInParent<BodyPart>();
			if (!((Object)(object)componentInParent == (Object)null) && !componentInParent.isGun && !((Object)(object)componentInParent.health == (Object)null) && (Plugin.BlastHitsShooter.Value || !((Object)(object)damager != (Object)null) || !((Object)(object)((Component)componentInParent.health).transform.root == (Object)(object)((Component)damager).transform.root)))
			{
				Vector3 val2 = ((Component)val).transform.position - pos;
				val2.x = 0f;
				float magnitude = ((Vector3)(ref val2)).magnitude;
				if (!dictionary.TryGetValue(componentInParent.health, out var value) || magnitude < value)
				{
					dictionary[componentInParent.health] = magnitude;
				}
			}
		}
		foreach (KeyValuePair<HealthHandler, float> item in dictionary)
		{
			float num = Mathf.Lerp(1f, 0.5f, Mathf.Clamp01(item.Value / radius));
			PoisonEffect.Apply(item.Key, damager, poison * num);
		}
	}

	private static void ScaleParticles(GameObject root, float scale)
	{
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_007a: 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)
		if (Mathf.Approximately(scale, 1f))
		{
			return;
		}
		ParticleSystem[] componentsInChildren = root.GetComponentsInChildren<ParticleSystem>(true);
		foreach (ParticleSystem obj in componentsInChildren)
		{
			MainModule main = obj.main;
			if (((MainModule)(ref main)).startSize3D)
			{
				((MainModule)(ref main)).startSizeXMultiplier = ((MainModule)(ref main)).startSizeXMultiplier * scale;
				((MainModule)(ref main)).startSizeYMultiplier = ((MainModule)(ref main)).startSizeYMultiplier * scale;
				((MainModule)(ref main)).startSizeZMultiplier = ((MainModule)(ref main)).startSizeZMultiplier * scale;
			}
			else
			{
				((MainModule)(ref main)).startSizeMultiplier = ((MainModule)(ref main)).startSizeMultiplier * scale;
			}
			((MainModule)(ref main)).startSpeedMultiplier = ((MainModule)(ref main)).startSpeedMultiplier * scale;
			ShapeModule shape = obj.shape;
			((ShapeModule)(ref shape)).radius = ((ShapeModule)(ref shape)).radius * scale;
		}
	}
}
public class PoisonEffect : MonoBehaviour
{
	private HealthHandler m_Health;

	private Controller m_Damager;

	private ParticleSystem m_Particles;

	private Transform m_Torso;

	private float m_Remaining;

	private float m_TimeLeft;

	private float m_TickTimer;

	private float m_LastSinceSpawn;

	public static void Apply(HealthHandler health, Controller damager, float amount)
	{
		if (!((Object)(object)health == (Object)null) && !(amount <= 0f))
		{
			PoisonEffect poisonEffect = ((Component)health).GetComponent<PoisonEffect>();
			if ((Object)(object)poisonEffect == (Object)null)
			{
				poisonEffect = ((Component)health).gameObject.AddComponent<PoisonEffect>();
			}
			poisonEffect.Add(health, damager, amount);
		}
	}

	private void Add(HealthHandler health, Controller damager, float amount)
	{
		if ((Object)(object)m_Health == (Object)null)
		{
			m_Health = health;
			DamageParticle componentInChildren = ((Component)health).GetComponentInChildren<DamageParticle>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				m_Particles = ((Component)componentInChildren).GetComponent<ParticleSystem>();
			}
			Torso componentInChildren2 = ((Component)health).GetComponentInChildren<Torso>();
			m_Torso = (((Object)(object)componentInChildren2 != (Object)null) ? ((Component)componentInChildren2).transform : ((Component)health).transform);
		}
		if ((Object)(object)damager != (Object)null)
		{
			m_Damager = damager;
		}
		float num = Mathf.Max(amount * (float)Mathf.Max(1, Plugin.MaxStackedDoses.Value), m_Remaining);
		m_Remaining = Mathf.Min(m_Remaining + amount, num);
		m_TimeLeft = Mathf.Max(0.05f, Plugin.PoisonDuration.Value);
		m_LastSinceSpawn = health.sinceSpawn;
	}

	private void Clear()
	{
		m_Remaining = 0f;
		m_TimeLeft = 0f;
		m_TickTimer = 0f;
	}

	private void Update()
	{
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_0116: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)m_Health == (Object)null || m_Remaining <= 0f)
		{
			return;
		}
		if (m_Health.sinceSpawn < m_LastSinceSpawn || m_Health.health <= 0f)
		{
			Clear();
			return;
		}
		m_LastSinceSpawn = m_Health.sinceSpawn;
		float num = Mathf.Max(0.05f, Plugin.PoisonTickInterval.Value);
		m_TickTimer += Time.deltaTime;
		if (!(m_TickTimer < num))
		{
			m_TickTimer -= num;
			int num2 = Mathf.Max(1, Mathf.CeilToInt(m_TimeLeft / num));
			float num3 = m_Remaining / (float)num2;
			m_Remaining -= num3;
			m_TimeLeft -= num;
			if (m_TimeLeft <= 0f)
			{
				m_Remaining = 0f;
			}
			Controller val = m_Damager;
			if ((Object)(object)val != (Object)null && !val.HasControl)
			{
				val = null;
			}
			if (m_Health.TakeDamage(num3, val, (DamageType)2, false, default(Vector3), default(Vector3)) && Plugin.PoisonParticles.Value)
			{
				Puff();
			}
		}
	}

	private void Puff()
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0022: 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_003a: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: 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_004e: 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_0082: 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_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)m_Particles == (Object)null) && !((Object)(object)m_Torso == (Object)null))
		{
			Color parsedColor = Plugin.ParsedColor;
			for (int i = 0; i < 6; i++)
			{
				EmitParams val = default(EmitParams);
				((EmitParams)(ref val)).position = m_Torso.position + Vector2.op_Implicit(Random.insideUnitCircle * 0.4f);
				((EmitParams)(ref val)).velocity = new Vector3(0f, Random.Range(1f, 4f), Random.Range(-2f, 2f));
				((EmitParams)(ref val)).startColor = Color32.op_Implicit(parsedColor);
				((EmitParams)(ref val)).applyShapeToPosition = false;
				m_Particles.Emit(val, 1);
			}
		}
	}
}
internal static class RarityFix
{
	[HarmonyPatch(typeof(WeaponSelectionHandler), "GenerateWeaponRarityArray")]
	private static class AfterBagBuilt
	{
		[HarmonyPostfix]
		private static void Postfix(WeaponSelectionHandler __instance)
		{
			s_Handler = __instance;
			s_LastBuiltOnline = MatchmakingHandler.IsNetworkMatch;
			if (Plugin.WithFramework || s_LastBuiltOnline || !Plugin.ReplaceSnakeGuns.Value)
			{
				return;
			}
			try
			{
				FindWeapons();
				List<byte> list = s_Bag.Invoke(__instance);
				if (list != null && s_RpgRarity >= 0)
				{
					if (Plugin.LauncherMatchesRpgRarity.Value)
					{
						SetWeight(list, s_LauncherIndex, s_RpgRarity);
					}
					if (Plugin.SeekerMatchesRpgRarity.Value)
					{
						SetWeight(list, s_SeekerIndex, s_RpgRarity);
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to adjust launcher rarity: " + ex));
			}
		}
	}

	[HarmonyPatch(typeof(WeaponSelectionHandler), "GetRandomWeaponIndex")]
	private static class BeforeDraw
	{
		[HarmonyPrefix]
		private static void Prefix(WeaponSelectionHandler __instance)
		{
			if (s_LastBuiltOnline != MatchmakingHandler.IsNetworkMatch && (object)s_Generate != null)
			{
				s_Generate.Invoke(__instance, null);
			}
		}
	}

	private static readonly FieldRef<WeaponSelectionHandler, List<byte>> s_Bag = AccessTools.FieldRefAccess<WeaponSelectionHandler, List<byte>>("m_WeaponRaritiesArray");

	private static readonly MethodInfo s_Generate = AccessTools.Method(typeof(WeaponSelectionHandler), "GenerateWeaponRarityArray", (Type[])null, (Type[])null);

	private static WeaponSelectionHandler s_Handler;

	private static bool s_LastBuiltOnline;

	private static int s_LauncherIndex = -2;

	private static int s_SeekerIndex = -1;

	private static int s_RpgRarity = -1;

	private static void FindWeapons()
	{
		if (s_LauncherIndex != -2)
		{
			return;
		}
		s_LauncherIndex = -1;
		ResourcesManager instance = ResourcesManager.Instance;
		if ((Object)(object)instance == (Object)null || (Object)(object)instance.CharacterObject == (Object)null)
		{
			s_LauncherIndex = -2;
			return;
		}
		Transform val = instance.CharacterObject.transform.Find("Weapons");
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		for (int i = 0; i < val.childCount; i++)
		{
			Transform child = val.GetChild(i);
			Weapon component = ((Component)child).GetComponent<Weapon>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.projectile == (Object)null)
			{
				continue;
			}
			string[] array = ((Object)child).name.Split(new char[1] { ' ' });
			if (array.Length != 0 && byte.TryParse(array[0], out var result))
			{
				if (((Object)component.projectile).name == "SnakeBulletBig")
				{
					s_LauncherIndex = result;
				}
				else if (((Object)component.projectile).name == "SnakeBulletBigFly")
				{
					s_SeekerIndex = result;
				}
				else if (((Object)component.projectile).name == "Rocket" && component.isGun)
				{
					s_RpgRarity = component.Rarity;
				}
			}
		}
		if (s_RpgRarity < 0)
		{
			Plugin.Log.LogWarning((object)"Could not find the RPG; launcher and seeker rarity left unchanged.");
			s_LauncherIndex = -1;
			s_SeekerIndex = -1;
		}
		else
		{
			Plugin.Log.LogInfo((object)("Poison Launcher / Flying Poison spawn weight set to the RPG's (" + s_RpgRarity + ") in local play."));
		}
	}

	private static void SetWeight(List<byte> bag, int index, int weight)
	{
		if (index >= 0 && bag.RemoveAll((byte b) => b == index) != 0)
		{
			for (int num = 0; num < weight; num++)
			{
				bag.Add((byte)index);
			}
		}
	}

	internal static void Rebuild()
	{
		if ((Object)(object)s_Handler == (Object)null || (object)s_Generate == null)
		{
			return;
		}
		try
		{
			s_Generate.Invoke(s_Handler, null);
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Failed to rebuild the spawn bag: " + ex));
		}
	}
}
[HarmonyPatch(typeof(Fighting), "Start")]
internal static class SnakeGunSwapper
{
	private enum Kind
	{
		None,
		Bullet,
		Shotgun,
		Rocket,
		Seeker,
		Grenade
	}

	private class WeaponState
	{
		public GameObject snakeProjectile;

		public GameObject poisonProjectile;

		public float snakeRecoil;

		public float snakeTorsoRecoil;

		public float poisonRecoil;

		public float poisonTorsoRecoil;
	}

	[HarmonyPatch(typeof(Weapon), "ActuallyShoot")]
	private static class BeforeShot
	{
		[HarmonyPrefix]
		private static void Prefix(Weapon __instance)
		{
			if (s_States.TryGetValue(__instance, out var value))
			{
				ApplyMode(__instance, value);
			}
		}
	}

	private static GameObject s_Holder;

	private static bool s_Built;

	private static bool s_Logged;

	private static GameObject s_PlainBullet;

	private static GameObject s_OrbSource;

	private static GameObject s_BlastVisual;

	private static GameObject s_RocketSource;

	private static float s_BaseDamage = 32f;

	private static readonly Dictionary<GameObject, GameObject> s_Replacements = new Dictionary<GameObject, GameObject>();

	private static readonly HashSet<GameObject> s_PoisonProjectiles = new HashSet<GameObject>();

	private static readonly Dictionary<GameObject, bool> s_SnakeCache = new Dictionary<GameObject, bool>();

	private static readonly Dictionary<Weapon, WeaponState> s_States = new Dictionary<Weapon, WeaponState>();

	private static int s_GameWeaponCount = -1;

	private static readonly Dictionary<Material, Material> s_Tinted = new Dictionary<Material, Material>();

	private static void ApplyMode(Weapon w, WeaponState st)
	{
		bool flag = Plugin.ReplaceSnakeGuns.Value && !MatchmakingHandler.IsNetworkMatch;
		w.projectile = (flag ? st.poisonProjectile : st.snakeProjectile);
		w.recoil = (flag ? st.poisonRecoil : st.snakeRecoil);
		w.torsoRecoil = (flag ? st.poisonTorsoRecoil : st.snakeTorsoRecoil);
	}

	private static void PruneStates()
	{
		if (s_States.Count < 400)
		{
			return;
		}
		List<Weapon> list = new List<Weapon>();
		foreach (Weapon key in s_States.Keys)
		{
			if ((Object)(object)key == (Object)null)
			{
				list.Add(key);
			}
		}
		foreach (Weapon item in list)
		{
			s_States.Remove(item);
		}
	}

	[HarmonyPostfix]
	private static void Postfix(Fighting __instance)
	{
		try
		{
			Weapon[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<Weapon>(true);
			if (componentsInChildren.Length == 0)
			{
				return;
			}
			if (!s_Built)
			{
				s_Built = true;
				BuildSharedParts(componentsInChildren);
			}
			Weapon[] array = componentsInChildren;
			foreach (Weapon val in array)
			{
				if ((Object)(object)val.projectile == (Object)null || s_States.ContainsKey(val) || s_PoisonProjectiles.Contains(val.projectile) || !IsGameWeapon(val))
				{
					continue;
				}
				Kind kind = KindOf(val.projectile);
				GameObject replacement = GetReplacement(val.projectile);
				if (!((Object)(object)replacement == (Object)null))
				{
					WeaponState weaponState = new WeaponState
					{
						snakeProjectile = val.projectile,
						poisonProjectile = replacement,
						snakeRecoil = val.recoil,
						snakeTorsoRecoil = val.torsoRecoil,
						poisonRecoil = val.recoil,
						poisonTorsoRecoil = val.torsoRecoil
					};
					if (kind == Kind.Bullet && val.fullAuto && ((Object)val).name.ToLowerInvariant().Contains("minigun"))
					{
						float num = Mathf.Max(0f, Plugin.MinigunRecoilMultiplier.Value);
						weaponState.poisonRecoil *= num;
						weaponState.poisonTorsoRecoil *= num;
					}
					s_States[val] = weaponState;
					ApplyMode(val, weaponState);
				}
			}
			PruneStates();
			if (Plugin.LogWeaponList.Value && !s_Logged)
			{
				s_Logged = true;
				LogWeapons(componentsInChildren);
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Failed to swap snake weapons: " + ex));
		}
	}

	private static bool IsGameWeapon(Weapon w)
	{
		if (s_GameWeaponCount < 0)
		{
			ResourcesManager instance = ResourcesManager.Instance;
			Transform val = (((Object)(object)instance != (Object)null && (Object)(object)instance.CharacterObject != (Object)null) ? instance.CharacterObject.transform.Find("Weapons") : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			s_GameWeaponCount = val.childCount;
		}
		Transform parent = ((Component)w).transform.parent;
		if ((Object)(object)parent == (Object)null || ((Object)parent).name != "Weapons")
		{
			return true;
		}
		return ((Component)w).transform.GetSiblingIndex() < s_GameWeaponCount;
	}

	private static Kind KindOf(GameObject projectile)
	{
		if ((Object)(object)projectile == (Object)null || !SpawnsSnakes(projectile))
		{
			return Kind.None;
		}
		return ((Object)projectile).name switch
		{
			"BulletShotgunSnake" => Kind.Shotgun, 
			"SnakeBulletBig" => Kind.Rocket, 
			"SnakeBulletBigFly" => Kind.Seeker, 
			"SnakeGrenade" => Kind.Grenade, 
			_ => Kind.Bullet, 
		};
	}

	private static bool SpawnsSnakes(GameObject go)
	{
		if ((Object)(object)go == (Object)null)
		{
			return false;
		}
		if (s_SnakeCache.TryGetValue(go, out var value))
		{
			return value;
		}
		bool flag = SpawnsSnakes(go, 0, new HashSet<GameObject>());
		s_SnakeCache[go] = flag;
		return flag;
	}

	private static bool SpawnsSnakes(GameObject go, int depth, HashSet<GameObject> seen)
	{
		if ((Object)(object)go == (Object)null || depth > 5 || !seen.Add(go))
		{
			return false;
		}
		if ((Object)(object)go.GetComponentInChildren<SnakeAI>(true) != (Object)null)
		{
			return true;
		}
		if ((Object)(object)go.GetComponentInChildren<SnakeSpawner>(true) != (Object)null)
		{
			return true;
		}
		ProjectileCollision[] componentsInChildren = go.GetComponentsInChildren<ProjectileCollision>(true);
		for (int i = 0; i < componentsInChildren.Length; i++)
		{
			if (SpawnsSnakes(componentsInChildren[i].spawnObject, depth + 1, seen))
			{
				return true;
			}
		}
		SpawnObject[] componentsInChildren2 = go.GetComponentsInChildren<SpawnObject>(true);
		for (int i = 0; i < componentsInChildren2.Length; i++)
		{
			if (SpawnsSnakes(componentsInChildren2[i].obj, depth + 1, seen))
			{
				return true;
			}
		}
		SpawnObjectAfterDelay[] componentsInChildren3 = go.GetComponentsInChildren<SpawnObjectAfterDelay>(true);
		for (int i = 0; i < componentsInChildren3.Length; i++)
		{
			if (SpawnsSnakes(componentsInChildren3[i].objectToSpawn, depth + 1, seen))
			{
				return true;
			}
		}
		SpawnObjectInRandomRange[] componentsInChildren4 = go.GetComponentsInChildren<SpawnObjectInRandomRange>(true);
		for (int i = 0; i < componentsInChildren4.Length; i++)
		{
			if (SpawnsSnakes(componentsInChildren4[i].obj, depth + 1, seen))
			{
				return true;
			}
		}
		SpawnStickyObject[] componentsInChildren5 = go.GetComponentsInChildren<SpawnStickyObject>(true);
		for (int i = 0; i < componentsInChildren5.Length; i++)
		{
			if (SpawnsSnakes(componentsInChildren5[i].stickyObject, depth + 1, seen))
			{
				return true;
			}
		}
		return false;
	}

	private static bool IsPlainBullet(GameObject p)
	{
		if ((Object)(object)p == (Object)null || (Object)(object)p.GetComponent<RayCastForward>() == (Object)null)
		{
			return false;
		}
		ProjectileCollision component = p.GetComponent<ProjectileCollision>();
		if ((Object)(object)component == (Object)null || component.damage <= 0f || (Object)(object)component.spawnObject != (Object)null)
		{
			return false;
		}
		if ((Object)(object)p.GetComponent<ProjectileBounce>() != (Object)null || (Object)(object)p.GetComponent<Gravity>() != (Object)null)
		{
			return false;
		}
		if ((Object)(object)p.GetComponent<SpawnStickyObject>() != (Object)null || (Object)(object)p.GetComponent<StickyObject>() != (Object)null)
		{
			return false;
		}
		return !SpawnsSnakes(p);
	}

	private static void BuildSharedParts(Weapon[] weapons)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000f: Expected O, but got Unknown
		//IL_025d: Unknown result type (might be due to invalid IL or missing references)
		s_Holder = new GameObject("PoisonGuns_Templates");
		s_Holder.SetActive(false);
		Object.DontDestroyOnLoad((Object)(object)s_Holder);
		string text = (Plugin.TemplateWeapon.Value ?? string.Empty).Trim().ToLowerInvariant();
		Weapon val = null;
		GameObject val2 = null;
		foreach (Weapon val3 in weapons)
		{
			if ((Object)(object)val3.projectile != (Object)null && ((Object)val3.projectile).name == "SnakeGrenade")
			{
				val2 = val3.projectile;
			}
			if ((Object)(object)val3.projectile != (Object)null && ((Object)val3.projectile).name == "Rocket")
			{
				s_RocketSource = val3.projectile;
			}
			if (val3.isGun && IsPlainBullet(val3.projectile))
			{
				if (text.Length > 0 && ((Object)val3).name.ToLowerInvariant().Contains(text) && ((Object)(object)val == (Object)null || !((Object)val).name.ToLowerInvariant().Contains(text)))
				{
					val = val3;
				}
				if ((Object)(object)val == (Object)null)
				{
					val = val3;
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			Plugin.Log.LogError((object)"Could not find a normal gun to copy a bullet from. Snake weapons were left unchanged.");
			return;
		}
		s_PlainBullet = val.projectile;
		s_BaseDamage = s_PlainBullet.GetComponent<ProjectileCollision>().damage;
		Plugin.Log.LogInfo((object)("Poison bullets are built from '" + ((Object)val).name + "' (" + ((Object)s_PlainBullet).name + ", " + s_BaseDamage + " damage)."));
		if ((Object)(object)val2 != (Object)null)
		{
			Transform val4 = val2.transform.Find("Sphere");
			if ((Object)(object)val4 != (Object)null)
			{
				s_OrbSource = ((Component)val4).gameObject;
			}
			SpawnObjectAfterDelay component = val2.GetComponent<SpawnObjectAfterDelay>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.objectToSpawn != (Object)null)
			{
				Transform val5 = component.objectToSpawn.transform.Find("ExplosionSmaller");
				if ((Object)(object)val5 != (Object)null)
				{
					s_BlastVisual = Object.Instantiate<GameObject>(((Component)val5).gameObject, s_Holder.transform);
					((Object)s_BlastVisual).name = "PoisonBlast";
					Tint(s_BlastVisual, Plugin.ParsedColor);
				}
			}
		}
		if ((Object)(object)s_OrbSource == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Snake grenade ball not found; poison projectiles will have no orb.");
		}
		if ((Object)(object)s_BlastVisual == (Object)null)
		{
			Plugin.Log.LogWarning((object)"Snake bomb explosion not found; poison blasts will be invisible.");
		}
	}

	private static GameObject GetReplacement(GameObject original)
	{
		if (s_Replacements.TryGetValue(original, out var value))
		{
			return value;
		}
		GameObject val = null;
		Kind kind = KindOf(original);
		if (kind != Kind.None && (Object)(object)s_PlainBullet != (Object)null)
		{
			switch (kind)
			{
			case Kind.Bullet:
				val = MakeBullet("PoisonBullet", s_Holder.transform);
				break;
			case Kind.Shotgun:
				val = MakeShotgun(original);
				break;
			case Kind.Rocket:
				val = MakeRocket(seeker: false);
				break;
			case Kind.Seeker:
				val = MakeRocket(seeker: true);
				break;
			case Kind.Grenade:
				val = MakeGrenade(original);
				break;
			}
			if ((Object)(object)val != (Object)null)
			{
				s_PoisonProjectiles.Add(val);
				Plugin.Log.LogInfo((object)("Built " + ((Object)val).name + " to replace " + ((Object)original).name + "."));
			}
		}
		s_Replacements[original] = val;
		return val;
	}

	private static GameObject BuildFlyingProjectile(string name, Transform parent, float speed, float orbSize, float impact, float poisonOnHit, float trailWidth)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0171: Unknown result type (might be due to invalid IL or missing references)
		//IL_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0193: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_0215: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = Object.Instantiate<GameObject>(s_PlainBullet, parent);
		((Object)val).name = name;
		val.transform.localPosition = Vector3.zero;
		val.transform.localRotation = Quaternion.identity;
		RayCastForward[] componentsInChildren = val.GetComponentsInChildren<RayCastForward>(true);
		foreach (RayCastForward obj in componentsInChildren)
		{
			obj.speed = Mathf.Max(0.5f, speed);
			obj.friction = 0f;
		}
		RemoveAfterSeconds[] componentsInChildren2 = val.GetComponentsInChildren<RemoveAfterSeconds>(true);
		foreach (RemoveAfterSeconds obj2 in componentsInChildren2)
		{
			obj2.time = Mathf.Max(obj2.time, Plugin.BulletLifetime.Value);
		}
		ProjectileCollision component = val.GetComponent<ProjectileCollision>();
		component.damage = s_BaseDamage * Mathf.Max(0f, impact);
		component.SpecialEffect = "PoisonGunsHit";
		component.secondsToDestroyAfterCollision = Mathf.Min(component.secondsToDestroyAfterCollision, 3f);
		val.AddComponent<PoisonBullet>().poisonDamage = s_BaseDamage * Mathf.Max(0f, poisonOnHit);
		Tint(val, Plugin.ParsedColor);
		TrailRenderer[] componentsInChildren3 = val.GetComponentsInChildren<TrailRenderer>(true);
		foreach (TrailRenderer obj3 in componentsInChildren3)
		{
			obj3.widthMultiplier *= trailWidth;
		}
		PoisonProjectile poisonProjectile = val.AddComponent<PoisonProjectile>();
		if ((Object)(object)s_OrbSource != (Object)null)
		{
			GameObject val2 = Object.Instantiate<GameObject>(s_OrbSource, val.transform);
			((Object)val2).name = "PoisonOrb";
			val2.SetActive(true);
			val2.transform.localPosition = Vector3.zero;
			val2.transform.localRotation = Quaternion.identity;
			val2.transform.localScale = Vector3.one * Mathf.Max(0.05f, orbSize);
			Collider[] componentsInChildren4 = val2.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			Rigidbody[] componentsInChildren5 = val2.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren5.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren5[i]);
			}
			MonoBehaviour[] componentsInChildren6 = val2.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren6.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren6[i]);
			}
			Tint(val2, Plugin.ParsedColor);
			poisonProjectile.orb = val2;
		}
		return val;
	}

	private static GameObject MakeBullet(string name, Transform parent)
	{
		return BuildFlyingProjectile(name, parent, Plugin.BulletSpeed.Value, Plugin.BulletOrbSize.Value, Plugin.ImpactDamageMultiplier.Value, Plugin.PoisonDamageMultiplier.Value, 1.5f);
	}

	private static GameObject MakeShotgun(GameObject original)
	{
		//IL_0005: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
		//IL_011d: Unknown result type (might be due to invalid IL or missing references)
		//IL_015f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: Unknown result type (might be due to invalid IL or missing references)
		//IL_0186: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0090: Unknown result type (might be due to invalid IL or missing references)
		//IL_0093: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
		GameObject val = new GameObject("PoisonShotgunShell");
		val.transform.SetParent(s_Holder.transform, false);
		val.AddComponent<RemoveAfterSeconds>().time = Plugin.BulletLifetime.Value + 4f;
		List<Vector3> list = new List<Vector3>();
		List<float> list2 = new List<float>();
		SnakeSpawner componentInChildren = original.GetComponentInChildren<SnakeSpawner>(true);
		if ((Object)(object)componentInChildren != (Object)null && AccessTools.Field(typeof(SnakeSpawner), "Spawns").GetValue(componentInChildren) is List<Spawn> list3)
		{
			foreach (Spawn item in list3)
			{
				list.Add(item.Rot);
				list2.Add(item.Pos.y);
			}
		}
		if (list.Count == 0)
		{
			list.Add(Vector3.zero);
			list2.Add(0f);
			list.Add(new Vector3(-20f, 0f, 0f));
			list2.Add(0.4f);
			list.Add(new Vector3(20f, 0f, 0f));
			list2.Add(-0.4f);
		}
		for (int i = 0; i < list.Count; i++)
		{
			GameObject obj = MakeBullet("PoisonPellet" + i, val.transform);
			obj.transform.localRotation = Quaternion.Euler(list[i]);
			obj.transform.localPosition = new Vector3(0f, list2[i], 0f);
			RayCastForward[] componentsInChildren = obj.GetComponentsInChildren<RayCastForward>(true);
			for (int j = 0; j < componentsInChildren.Length; j++)
			{
				componentsInChildren[j].spread = Mathf.Max(0f, Plugin.ShotgunPelletSpread.Value);
			}
		}
		return val;
	}

	private static GameObject MakeRocket(bool seeker)
	{
		//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
		GameObject val;
		PoisonProjectile component;
		if (!seeker)
		{
			val = BuildFlyingProjectile("PoisonRocket", s_Holder.transform, Plugin.RocketSpeed.Value, Plugin.RocketOrbSize.Value, Plugin.RocketImpactDamage.Value, 0f, 2f);
			component = val.GetComponent<PoisonProjectile>();
			component.blastRadius = Plugin.RocketBlastRadius.Value;
			component.blastPoison = s_BaseDamage * Plugin.RocketBlastPoison.Value;
			GameObject val2 = BuildRocketModel(val.transform);
			if ((Object)(object)val2 != (Object)null)
			{
				if ((Object)(object)component.orb != (Object)null)
				{
					Object.DestroyImmediate((Object)(object)component.orb);
				}
				component.orb = val2;
				TrailRenderer[] componentsInChildren = val.GetComponentsInChildren<TrailRenderer>(true);
				for (int i = 0; i < componentsInChildren.Length; i++)
				{
					((Renderer)componentsInChildren[i]).enabled = false;
				}
				val2.AddComponent<PoisonSpin>().degreesPerSecond = Plugin.RocketSpinSpeed.Value;
			}
		}
		else
		{
			val = BuildFlyingProjectile("PoisonSeeker", s_Holder.transform, Plugin.SeekerSpeed.Value, Plugin.SeekerOrbSize.Value, Plugin.SeekerImpactDamage.Value, 0f, 3f);
			component = val.GetComponent<PoisonProjectile>();
			component.blastRadius = Plugin.SeekerBlastRadius.Value;
			component.blastPoison = s_BaseDamage * Plugin.SeekerBlastPoison.Value;
			TrailRenderer[] componentsInChildren = val.GetComponentsInChildren<TrailRenderer>(true);
			foreach (TrailRenderer val3 in componentsInChildren)
			{
				val3.time = 0.7f;
				val3.minVertexDistance = 0.05f;
				val3.widthCurve = AnimationCurve.Linear(0f, 1f, 1f, 0f);
				val3.widthMultiplier = Mathf.Max(0.05f, Plugin.SeekerOrbSize.Value);
				val3.endColor = new Color(val3.endColor.r, val3.endColor.g, val3.endColor.b, 0f);
			}
			PoisonHoming poisonHoming = val.AddComponent<PoisonHoming>();
			poisonHoming.turnRate = Plugin.SeekerTurnRate.Value;
			poisonHoming.range = Plugin.SeekerRange.Value;
		}
		component.blastVisual = s_BlastVisual;
		Object.DestroyImmediate((Object)(object)val.GetComponent<PoisonBullet>());
		val.GetComponent<ProjectileCollision>().SpecialEffect = string.Empty;
		return val;
	}

	private static GameObject BuildRocketModel(Transform parent)
	{
		//IL_0023: Unknown result type (might be due to invalid IL or missing references)
		//IL_0029: Expected O, but got Unknown
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_005f: 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_0094: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Expected O, but got Unknown
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_01be: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)s_RocketSource == (Object)null)
		{
			Plugin.Log.LogWarning((object)"RPG rocket not found; the poison rocket keeps the plain orb.");
			return null;
		}
		GameObject val = new GameObject("PoisonRocketModel");
		val.transform.SetParent(parent, false);
		val.transform.localScale = s_RocketSource.transform.localScale * Mathf.Max(0.1f, Plugin.RocketModelScale.Value);
		val.transform.localRotation = Quaternion.identity;
		foreach (Transform item in s_RocketSource.transform)
		{
			Transform val2 = item;
			if (!((Component)val2).gameObject.activeSelf)
			{
				continue;
			}
			GameObject val3 = Object.Instantiate<GameObject>(((Component)val2).gameObject, val.transform);
			((Object)val3).name = ((Object)val2).name;
			val3.transform.localPosition = val2.localPosition;
			val3.transform.localRotation = val2.localRotation;
			val3.transform.localScale = val2.localScale;
			Joint[] componentsInChildren = val3.GetComponentsInChildren<Joint>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren[i]);
			}
			Collider[] componentsInChildren2 = val3.GetComponentsInChildren<Collider>(true);
			for (int i = 0; i < componentsInChildren2.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren2[i]);
			}
			Rigidbody[] componentsInChildren3 = val3.GetComponentsInChildren<Rigidbody>(true);
			for (int i = 0; i < componentsInChildren3.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren3[i]);
			}
			MonoBehaviour[] componentsInChildren4 = val3.GetComponentsInChildren<MonoBehaviour>(true);
			for (int i = 0; i < componentsInChildren4.Length; i++)
			{
				Object.DestroyImmediate((Object)(object)componentsInChildren4[i]);
			}
			ParticleSystem component = val3.GetComponent<ParticleSystem>();
			if (!((Object)(object)component != (Object)null) || !((Object)(object)val3.GetComponent<MeshRenderer>() == (Object)null))
			{
				continue;
			}
			MainModule main = component.main;
			((MainModule)(ref main)).startColor = new MinMaxGradient(Plugin.ParsedColor);
			ParticleSystemRenderer component2 = val3.GetComponent<ParticleSystemRenderer>();
			if ((Object)(object)component2 != (Object)null)
			{
				Material[] sharedMaterials = ((Renderer)component2).sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					sharedMaterials[j] = TintedMaterial(sharedMaterials[j], Plugin.ParsedColor);
				}
				((Renderer)component2).sharedMaterials = sharedMaterials;
			}
		}
		return val;
	}

	private static GameObject MakeGrenade(GameObject original)
	{
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		GameObject obj = Object.Instantiate<GameObject>(original, s_Holder.transform);
		((Object)obj).name = "PoisonGrenade";
		Tint(obj, Plugin.ParsedColor);
		PoisonGrenade poisonGrenade = obj.AddComponent<PoisonGrenade>();
		SpawnObjectAfterDelay component = obj.GetComponent<SpawnObjectAfterDelay>();
		if ((Object)(object)component != (Object)null)
		{
			poisonGrenade.fuse = component.secondsBeforeSpawn;
			((Behaviour)component).enabled = false;
		}
		poisonGrenade.blastRadius = Plugin.GrenadeBlastRadius.Value;
		poisonGrenade.blastPoison = s_BaseDamage * Plugin.GrenadeBlastPoison.Value;
		poisonGrenade.blastVisual = s_BlastVisual;
		return obj;
	}

	private static void Tint(GameObject root, Color color)
	{
		//IL_0011: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_002e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		//IL_003f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: 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_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_0067: Unknown result type (might be due to invalid IL or missing references)
		//IL_008f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: 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_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: Unknown result type (might be due to invalid IL or missing references)
		//IL_0128: Unknown result type (might be due to invalid IL or missing references)
		//IL_0132: Unknown result type (might be due to invalid IL or missing references)
		//IL_015e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0185: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		TrailRenderer[] componentsInChildren = root.GetComponentsInChildren<TrailRenderer>(true);
		foreach (TrailRenderer val in componentsInChildren)
		{
			val.startColor = new Color(color.r, color.g, color.b, val.startColor.a);
			val.endColor = new Color(color.r, color.g, color.b, val.endColor.a);
			((Renderer)val).sharedMaterial = TintedMaterial(((Renderer)val).sharedMaterial, color);
		}
		LineRenderer[] componentsInChildren2 = root.GetComponentsInChildren<LineRenderer>(true);
		foreach (LineRenderer val2 in componentsInChildren2)
		{
			val2.startColor = new Color(color.r, color.g, color.b, val2.startColor.a);
			val2.endColor = new Color(color.r, color.g, color.b, val2.endColor.a);
			((Renderer)val2).sharedMaterial = TintedMaterial(((Renderer)val2).sharedMaterial, color);
		}
		SpriteRenderer[] componentsInChildren3 = root.GetComponentsInChildren<SpriteRenderer>(true);
		foreach (SpriteRenderer val3 in componentsInChildren3)
		{
			val3.color = new Color(color.r, color.g, color.b, val3.color.a);
		}
		MeshRenderer[] componentsInChildren4 = root.GetComponentsInChildren<MeshRenderer>(true);
		foreach (MeshRenderer obj in componentsInChildren4)
		{
			((Renderer)obj).sharedMaterial = TintedMaterial(((Renderer)obj).sharedMaterial, color);
		}
		ParticleSystem[] componentsInChildren5 = root.GetComponentsInChildren<ParticleSystem>(true);
		for (int i = 0; i < componentsInChildren5.Length; i++)
		{
			MainModule main = componentsInChildren5[i].main;
			((MainModule)(ref main)).startColor = new MinMaxGradient(color);
		}
	}

	private static Material TintedMaterial(Material original, Color color)
	{
		//IL_001d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0023: Expected O, but got Unknown
		//IL_004c: 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_0058: 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_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0097: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)original == (Object)null)
		{
			return null;
		}
		if (s_Tinted.TryGetValue(original, out var value))
		{
			return value;
		}
		value = new Material(original);
		((Object)value).name = ((Object)original).name + " (Poison)";
		if (value.HasProperty("_Color"))
		{
			value.SetColor("_Color", new Color(color.r, color.g, color.b, value.GetColor("_Color").a));
		}
		if (value.HasProperty("_TintColor"))
		{
			value.SetColor("_TintColor", new Color(color.r, color.g, color.b, value.GetColor("_TintColor").a));
		}
		if (value.HasProperty("_EmissionColor"))
		{
			value.SetColor("_EmissionColor", color);
		}
		s_Tinted[original] = value;
		s_Tinted[value] = value;
		return value;
	}

	private static void LogWeapons(Weapon[] weapons)
	{
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine("Snake weapons swapped (weapon | now fires):");
		foreach (Weapon val in weapons)
		{
			if (s_States.TryGetValue(val, out var value))
			{
				stringBuilder.Append("  ").Append(((Object)val).name).Append(" | ")
					.Append(((Object)value.poisonProjectile).name)
					.AppendLine();
			}
		}
		stringBuilder.Append("(Online matches use the original snakes.)");
		Plugin.Log.LogInfo((object)stringBuilder.ToString());
	}
}