Decompiled source of ComfyFishing v0.1.0

ComfyFishing.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("ComfyFishing")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+f629447c8b83df14d9ff3212dfefc8d95674f636")]
[assembly: AssemblyProduct("ComfyFishing")]
[assembly: AssemblyTitle("ComfyFishing")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 ComfyFishing
{
	[BepInPlugin("games.loxley.comfyfishing", "ComfyFishing", "0.1.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class ComfyFishingPlugin : BaseUnityPlugin
	{
		public const string PluginGUID = "games.loxley.comfyfishing";

		public const string PluginName = "ComfyFishing";

		public const string PluginVersion = "0.1.0";

		public static ConfigEntry<bool> VanillaRodVanillaReel;

		public static ConfigEntry<bool> AutoHook;

		public static ConfigEntry<float> HookWindow;

		public static ConfigEntry<float> ReelSpeed;

		public static ConfigEntry<float> ReelSpeedMaxSkill;

		public static ConfigEntry<bool> GateBySkill;

		public static ConfigEntry<string> BaitTiers;

		private void Awake()
		{
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			VanillaRodVanillaReel = ((BaseUnityPlugin)this).Config.Bind<bool>("Reel", "VanillaRodVanillaReel", true, "Haldor's fishing rod keeps the vanilla tug-of-war; only crafted rods get the comfy reel.");
			AutoHook = ((BaseUnityPlugin)this).Config.Bind<bool>("Reel", "AutoHook", false, "Hook the fish the moment it bites, no click needed.");
			HookWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Reel", "HookWindow", 1.5f, "Seconds after a bite in which a click hooks the fish (vanilla: 0.5).");
			ReelSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Reel", "ReelSpeed", 3f, "Metres of line per second once hooked, at fishing skill 0.");
			ReelSpeedMaxSkill = ((BaseUnityPlugin)this).Config.Bind<float>("Reel", "ReelSpeedMaxSkill", 6f, "Metres of line per second once hooked, at fishing skill 100.");
			GateBySkill = ((BaseUnityPlugin)this).Config.Bind<bool>("Tiers", "Enabled", true, "Baits need a fishing skill level and rod tier before fish will take them.");
			BaitTiers = ((BaseUnityPlugin)this).Config.Bind<string>("Tiers", "BaitTiers", "FishingBait:0:1, FishingBaitForest:10:1, FishingBaitCave:20:2, FishingBaitSwamp:25:2, FishingBaitOcean:30:2, FishingBaitPlains:40:3, FishingBaitMistlands:55:3, FishingBaitDeepNorth:70:4, FishingBaitAshlands:70:4", "bait prefab : fishing skill needed : rod tier needed. Rod tiers: 1 Fishing rod, 2 Bone rod, 3 Silver rod, 4 Black metal rod.");
			PrefabManager.OnVanillaPrefabsAvailable += AddRods;
			new Harmony("games.loxley.comfyfishing").PatchAll();
		}

		private void AddRods()
		{
			//IL_0020: 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_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Expected O, but got Unknown
			//IL_021e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Expected O, but got Unknown
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Expected O, but got Unknown
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0309: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			AddRod("RodWood", 1, "Wooden fishing rod", "A bent branch and a length of line. Reels itself in once something bites, but only meadows and forest fish will take the bait. Wears quickly.", new Color(0.75f, 0.6f, 0.4f), CraftingStations.Workbench, 1, 60f, ("Wood", 10, 5), ("Resin", 4, 2), ("LeatherScraps", 2, 1));
			AddRod("RodBone", 2, "Bone fishing rod", "Fine wood spliced with bone. Reels itself in, and swamp, cave and ocean fish will take the bait.", new Color(0.95f, 0.9f, 0.78f), CraftingStations.Workbench, 2, 100f, ("FineWood", 10, 5), ("BoneFragments", 4, 2), ("Resin", 5, 2));
			AddRod("RodSilver", 3, "Silver fishing rod", "Light and true. Plains and mistlands fish will take the bait. Reels faster than bone.", new Color(0.8f, 0.88f, 1f), CraftingStations.Forge, 2, 150f, ("FineWood", 10, 5), ("Silver", 4, 2), ("Guck", 2, 1));
			AddRod("RodBlackMetal", 4, "Black metal fishing rod", "Nothing in the sea is too strong for it. Every bait, fastest reel.", new Color(0.45f, 0.45f, 0.5f), CraftingStations.Forge, 3, 200f, ("FineWood", 10, 5), ("BlackMetal", 5, 3), ("LinenThread", 5, 2));
			ItemManager instance = ItemManager.Instance;
			RecipeConfig val = new RecipeConfig();
			val.Item = "FishingBait";
			val.Amount = 10;
			val.CraftingStation = CraftingStations.Cauldron;
			val.Requirements = (RequirementConfig[])(object)new RequirementConfig[2]
			{
				new RequirementConfig("NeckTail", 2, 0, true),
				new RequirementConfig("Mushroom", 1, 0, true)
			};
			instance.AddRecipe(new CustomRecipe(val));
			foreach (KeyValuePair<string, Color> item in new Dictionary<string, Color>
			{
				{
					"FishingBaitForest",
					new Color(0.55f, 0.85f, 0.45f)
				},
				{
					"FishingBaitCave",
					new Color(0.75f, 0.6f, 0.95f)
				},
				{
					"FishingBaitSwamp",
					new Color(0.55f, 0.65f, 0.35f)
				},
				{
					"FishingBaitOcean",
					new Color(0.45f, 0.7f, 1f)
				},
				{
					"FishingBaitPlains",
					new Color(1f, 0.85f, 0.4f)
				},
				{
					"FishingBaitMistlands",
					new Color(0.6f, 0.9f, 0.9f)
				},
				{
					"FishingBaitDeepNorth",
					new Color(0.8f, 0.9f, 1f)
				},
				{
					"FishingBaitAshlands",
					new Color(1f, 0.5f, 0.35f)
				}
			})
			{
				GameObject prefab = PrefabManager.Instance.GetPrefab(item.Key);
				SharedData val2 = ((!Object.op_Implicit((Object)(object)prefab)) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared);
				if (val2?.m_icons != null && val2.m_icons.Length != 0 && Object.op_Implicit((Object)(object)val2.m_icons[0]))
				{
					val2.m_icons = (Sprite[])(object)new Sprite[1] { Tint.Sprite(val2.m_icons[0], item.Value) };
				}
			}
			PrefabManager.OnVanillaPrefabsAvailable -= AddRods;
		}

		private void AddRod(string name, int tier, string display, string desc, Color tint, string station, int level, float durability, params (string item, int amount, int perLevel)[] cost)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_0052: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			List<RequirementConfig> list = new List<RequirementConfig>();
			for (int i = 0; i < cost.Length; i++)
			{
				var (text, num, num2) = cost[i];
				list.Add(new RequirementConfig(text, num, num2, true));
			}
			CustomItem val = new CustomItem(name, "FishingRod", new ItemConfig
			{
				Name = display,
				Description = desc,
				CraftingStation = station,
				MinStationLevel = level,
				Requirements = list.ToArray()
			});
			SharedData shared = val.ItemDrop.m_itemData.m_shared;
			shared.m_useDurability = true;
			shared.m_maxDurability = durability;
			shared.m_durabilityPerLevel = durability * 0.5f;
			shared.m_useDurabilityDrain = 1f;
			shared.m_maxQuality = 4;
			Tint.Apply(val.ItemPrefab, tint);
			if (shared.m_icons != null && shared.m_icons.Length != 0 && Object.op_Implicit((Object)(object)shared.m_icons[0]))
			{
				shared.m_icons = (Sprite[])(object)new Sprite[1] { Tint.Sprite(shared.m_icons[0], tint) };
			}
			ItemManager.Instance.AddItem(val);
			Rods.Tiers[shared.m_name] = tier;
		}
	}
	public static class Tint
	{
		public static void Apply(GameObject prefab, Color c)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			Renderer[] componentsInChildren = prefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val in componentsInChildren)
			{
				Material[] sharedMaterials = val.sharedMaterials;
				for (int j = 0; j < sharedMaterials.Length; j++)
				{
					if (Object.op_Implicit((Object)(object)sharedMaterials[j]))
					{
						Material val2 = new Material(sharedMaterials[j]);
						if (val2.HasProperty("_Color"))
						{
							val2.color = c;
						}
						sharedMaterials[j] = val2;
					}
				}
				val.sharedMaterials = sharedMaterials;
			}
		}

		public static Sprite Sprite(Sprite src, Color c)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: 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_0059: Expected O, but got Unknown
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				Rect textureRect = src.textureRect;
				RenderTexture temporary = RenderTexture.GetTemporary(((Texture)src.texture).width, ((Texture)src.texture).height, 0, (RenderTextureFormat)0);
				RenderTexture active = RenderTexture.active;
				Graphics.Blit((Texture)(object)src.texture, temporary);
				RenderTexture.active = temporary;
				int num = (int)((Rect)(ref textureRect)).width;
				int num2 = (int)((Rect)(ref textureRect)).height;
				Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
				val.ReadPixels(new Rect(((Rect)(ref textureRect)).x, ((Rect)(ref textureRect)).y, (float)num, (float)num2), 0, 0);
				Texture2D val2 = new Texture2D(num, num2, (TextureFormat)4, false);
				val2.ReadPixels(new Rect(((Rect)(ref textureRect)).x, (float)((Texture)src.texture).height - ((Rect)(ref textureRect)).y - (float)num2, (float)num, (float)num2), 0, 0);
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
				float num3 = Alpha(val);
				float num4 = Alpha(val2);
				if (num3 <= 0f && num4 <= 0f)
				{
					return src;
				}
				Texture2D val3 = ((num3 >= num4) ? val : val2);
				Color[] pixels = val3.GetPixels();
				for (int i = 0; i < pixels.Length; i++)
				{
					pixels[i] = new Color(pixels[i].r * c.r, pixels[i].g * c.g, pixels[i].b * c.b, pixels[i].a);
				}
				val3.SetPixels(pixels);
				val3.Apply();
				return Sprite.Create(val3, new Rect(0f, 0f, (float)num, (float)num2), new Vector2(0.5f, 0.5f), src.pixelsPerUnit);
			}
			catch
			{
				return src;
			}
			static float Alpha(Texture2D t)
			{
				//IL_0013: 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_001a: Unknown result type (might be due to invalid IL or missing references)
				float num5 = 0f;
				Color[] pixels2 = t.GetPixels();
				foreach (Color val4 in pixels2)
				{
					num5 += val4.a;
				}
				return num5;
			}
		}
	}
	public static class Rods
	{
		public static readonly Dictionary<string, int> Tiers = new Dictionary<string, int>();

		public static int TierOf(Character owner)
		{
			Character obj = ((owner is Humanoid) ? owner : null);
			string text = ((obj != null) ? ((Humanoid)obj).GetCurrentWeapon() : null)?.m_shared?.m_name;
			if (text == null || !Tiers.TryGetValue(text, out var value))
			{
				return 1;
			}
			return value;
		}
	}
	public static class Baits
	{
		private static Dictionary<string, (int skill, int rod)> s_table;

		public static (int skill, int rod) Requirement(string bait)
		{
			if (s_table == null)
			{
				s_table = new Dictionary<string, (int, int)>();
				string[] array = ComfyFishingPlugin.BaitTiers.Value.Split(new char[1] { ',' });
				for (int i = 0; i < array.Length; i++)
				{
					string[] array2 = array[i].Trim().Split(new char[1] { ':' });
					if (array2.Length == 3 && int.TryParse(array2[1], out var result) && int.TryParse(array2[2], out var result2))
					{
						s_table[array2[0]] = (result, result2);
					}
				}
			}
			if (!s_table.TryGetValue(bait, out (int, int) value))
			{
				return (skill: 0, rod: 1);
			}
			return value;
		}
	}
	public static class Reel
	{
		[HarmonyPatch(typeof(FishingFloat), "FixedUpdate")]
		private static class ComfyReel
		{
			private static bool Prefix(FishingFloat __instance)
			{
				//IL_022b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0254: Unknown result type (might be due to invalid IL or missing references)
				//IL_0284: Unknown result type (might be due to invalid IL or missing references)
				//IL_028f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0294: Unknown result type (might be due to invalid IL or missing references)
				//IL_0299: Unknown result type (might be due to invalid IL or missing references)
				ZNetView val = View.Invoke(__instance);
				if (!val.IsOwner())
				{
					return true;
				}
				Character val2 = Owner(__instance);
				if (!Object.op_Implicit((Object)(object)val2))
				{
					return true;
				}
				if (ComfyFishingPlugin.VanillaRodVanillaReel.Value && Rods.TierOf(val2) <= 1)
				{
					return true;
				}
				Fish val3 = __instance.GetCatch();
				if (!Object.op_Implicit((Object)(object)val3))
				{
					TryHook(__instance, val2);
					return true;
				}
				Transform val4 = RodTop(__instance, val2);
				if (!Object.op_Implicit((Object)(object)val4))
				{
					return true;
				}
				if (val2.InAttack() || val2.IsDrawingBow())
				{
					val3.OnHooked((FishingFloat)null);
					val.Destroy();
					return false;
				}
				float fixedDeltaTime = Time.fixedDeltaTime;
				float skillFactor = val2.GetSkillFactor((SkillType)104);
				float num = Mathf.Lerp(ComfyFishingPlugin.ReelSpeed.Value, ComfyFishingPlugin.ReelSpeedMaxSkill.Value, skillFactor);
				num *= 1f + 0.2f * (float)(Rods.TierOf(val2) - 1);
				Character obj = ((val2 is Humanoid) ? val2 : null);
				ItemData val5 = ((obj != null) ? ((Humanoid)obj).GetCurrentWeapon() : null);
				if (val5 != null)
				{
					num *= 1f + 0.1f * (float)(val5.m_quality - 1);
				}
				ItemDrop component = ((Component)val3).GetComponent<ItemDrop>();
				int num2 = ((!Object.op_Implicit((Object)(object)component)) ? 1 : component.m_itemData.m_quality);
				num /= 1f + 0.15f * (float)(num2 - 1);
				float num3 = LineLength.Invoke(__instance);
				LineLength.Invoke(__instance) = Mathf.Max(0f, num3 - num * fixedDeltaTime);
				if ((int)LineLength.Invoke(__instance) != (int)num3)
				{
					Say(__instance, LineLength.Invoke(__instance).ToString("0m"), prio: false);
				}
				SkillTimer.Invoke(__instance) += fixedDeltaTime * 2f;
				if (SkillTimer.Invoke(__instance) > 1f)
				{
					SkillTimer.Invoke(__instance) = 0f;
					val2.RaiseSkill((SkillType)104, 1f);
				}
				if (LineLength.Invoke(__instance) <= 0.5f)
				{
					Say(__instance, FishingFloat.Catch(val3, val2), prio: true);
					SetCatch(__instance, null);
					val3.OnHooked((FishingFloat)null);
					val.Destroy();
					return false;
				}
				Rigidbody obj2 = Body.Invoke(__instance);
				Utils.Pull(obj2, ((Component)val3).transform.position, 0.5f, __instance.m_moveForce, 0.5f, 0.3f, false, false, 1f);
				Utils.Pull(obj2, val4.position, LineLength.Invoke(__instance), __instance.m_moveForce, 1f, 0.3f, false, false, 1f);
				Vector3 val6 = val4.position - ((Component)__instance).transform.position;
				float magnitude = ((Vector3)(ref val6)).magnitude;
				__instance.m_rodLine.SetSlack((1f - Utils.LerpStep(LineLength.Invoke(__instance) / 2f, LineLength.Invoke(__instance), magnitude)) * __instance.m_maxLineSlack);
				return false;
			}
		}

		[HarmonyPatch(typeof(FishingFloat), "RPC_Nibble")]
		private static class GateBite
		{
			private static bool Prefix(FishingFloat __instance, bool correctBait)
			{
				if (!correctBait || !ComfyFishingPlugin.GateBySkill.Value)
				{
					return true;
				}
				Character val = Owner(__instance);
				if (!Object.op_Implicit((Object)(object)val))
				{
					return true;
				}
				var (num, num2) = Baits.Requirement(__instance.GetBait());
				if (Mathf.FloorToInt(val.GetSkillLevel((SkillType)104)) < num)
				{
					Say(__instance, $"Something bites, but it's too strong for you (fishing {num})", prio: true);
					return false;
				}
				if (Rods.TierOf(val) < num2)
				{
					Say(__instance, "Something bites, but your rod isn't up to it", prio: true);
					return false;
				}
				return true;
			}
		}

		private static readonly FieldRef<FishingFloat, float> LineLength = AccessTools.FieldRefAccess<FishingFloat, float>("m_lineLength");

		private static readonly FieldRef<FishingFloat, Rigidbody> Body = AccessTools.FieldRefAccess<FishingFloat, Rigidbody>("m_body");

		private static readonly FieldRef<FishingFloat, ZNetView> View = AccessTools.FieldRefAccess<FishingFloat, ZNetView>("m_nview");

		private static readonly FieldRef<FishingFloat, Fish> Nibbler = AccessTools.FieldRefAccess<FishingFloat, Fish>("m_nibbler");

		private static readonly FieldRef<FishingFloat, float> NibbleTime = AccessTools.FieldRefAccess<FishingFloat, float>("m_nibbleTime");

		private static readonly FieldRef<FishingFloat, float> SkillTimer = AccessTools.FieldRefAccess<FishingFloat, float>("m_fishingSkillImproveTimer");

		private static Character Owner(FishingFloat f)
		{
			return Traverse.Create((object)f).Method("GetOwner", Array.Empty<object>()).GetValue<Character>();
		}

		private static Transform RodTop(FishingFloat f, Character o)
		{
			return Traverse.Create((object)f).Method("GetRodTop", new object[1] { o }).GetValue<Transform>();
		}

		private static void SetCatch(FishingFloat f, Fish fish)
		{
			Traverse.Create((object)f).Method("SetCatch", new object[1] { fish }).GetValue();
		}

		private static void Say(FishingFloat f, string msg, bool prio)
		{
			Traverse.Create((object)f).Method("Message", new object[2] { msg, prio }).GetValue();
		}

		private static void TryHook(FishingFloat f, Character owner)
		{
			Fish val = Nibbler.Invoke(f);
			if (!((Object)(object)val == (Object)null) && !((Object)(object)f.GetCatch() != (Object)null))
			{
				if (Time.time - NibbleTime.Invoke(f) > ComfyFishingPlugin.HookWindow.Value)
				{
					Nibbler.Invoke(f) = null;
				}
				else if (ComfyFishingPlugin.AutoHook.Value || owner.IsBlocking())
				{
					Say(f, "$msg_fishing_hooked", prio: true);
					SetCatch(f, val);
					Nibbler.Invoke(f) = null;
					Game.instance.IncrementPlayerStat((PlayerStatType)158, 1f, false);
				}
			}
		}
	}
}