Decompiled source of FeedFish v1.3.4

FeedFish.dll

Decompiled 6 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CustomStoryLogs;
using GameNetcodeStuff;
using HarmonyLib;
using LethalLib.Modules;
using LethalNetworkAPI;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.InputSystem;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("FeedFish")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyCopyright("Copyright © 2024 Yorimor")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a300e77a5342931db301d2892220b7745939f38e")]
[assembly: AssemblyProduct("FeedFish")]
[assembly: AssemblyTitle("FeedFish")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 FeedFish
{
	public class FishingSpot : MonoBehaviour
	{
		public bool triggered = false;

		public void DoSacrificePlayer()
		{
			triggered = true;
			FeedFish.clientFishingSpotEvent.InvokeServer();
		}
	}
	public class FeedFishInteraction : MonoBehaviour
	{
		private delegate void RewardHandler();

		[SerializeField]
		public InteractTrigger triggerScript;

		[SerializeField]
		public GameObject spawnLocation;

		[SerializeField]
		public GameObject presentPrefab;

		private Random _rand = new Random();

		private Dictionary<ConfigEntry<int>, RewardHandler> rewards = new Dictionary<ConfigEntry<int>, RewardHandler>();

		public void Awake()
		{
			InteractTrigger component = ((Component)this).GetComponent<InteractTrigger>();
			component.hoverTip = "Feed " + FeedFish.FishName.Value + " : [LMB]";
			triggerScript.interactable = false;
		}

		public void Update()
		{
			PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController;
			if (Object.op_Implicit((Object)(object)localPlayerController) && localPlayerController.isHoldingObject)
			{
				bool interactable = localPlayerController.isHoldingObject;
				GrabbableObject val = GameNetworkManager.Instance.localPlayerController?.currentlyHeldObjectServer;
				if (Object.op_Implicit((Object)(object)val))
				{
					interactable = ((Object)val).name.Contains("Ragdoll");
				}
				triggerScript.interactable = interactable;
			}
		}

		public void DoFeedFish(PlayerControllerB player)
		{
			GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer;
			if (!((Object)(object)currentlyHeldObjectServer == (Object)null) && ((Object)currentlyHeldObjectServer).name.Contains("Ragdoll"))
			{
				FeedFish.Log.LogInfo((object)("Feeding body to " + FeedFish.FishName.Value));
				player.DespawnHeldObject();
				FeedFish.clientBodyFedEvent.InvokeServer();
			}
		}

		public void SpawnPresent()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (Object.op_Implicit((Object)(object)presentPrefab))
			{
				GameObject val = Object.Instantiate<GameObject>(presentPrefab);
				presentPrefab.GetComponent<NetworkObject>().Spawn(false);
				val.transform.position = spawnLocation.transform.position;
			}
		}
	}
	[BepInPlugin("Yorimor.FeedFish", "FeedFish", "1.3.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class FeedFish : BaseUnityPlugin
	{
		private delegate void RewardHandler();

		private const string modGUID = "Yorimor.FeedFish";

		private const string modName = "FeedFish";

		private const string modVersion = "1.3.0";

		private readonly Harmony harmony = new Harmony("Yorimor.FeedFish");

		internal static ManualLogSource Log;

		[PublicNetworkVariable]
		public static LethalNetworkVariable<int> bodiesFed = new LethalNetworkVariable<int>("bodiesFed");

		[PublicNetworkVariable]
		public static LethalNetworkVariable<int> totalBodiesFed = new LethalNetworkVariable<int>("totalBodiesFed");

		public static AssetBundle MyCustomAssets;

		public static ConfigEntry<string> FishName;

		public static ConfigEntry<bool> EnableRewards;

		private Random _rand = new Random();

		private Dictionary<ConfigEntry<int>, RewardHandler> rewards = new Dictionary<ConfigEntry<int>, RewardHandler>();

		public static int ChanceTotal = 0;

		public static ConfigEntry<int> RewardsChanceNone;

		public static ConfigEntry<int> RewardsCreditsSmall;

		public static ConfigEntry<int> RewardsCreditsMedium;

		public static ConfigEntry<int> RewardsQuotaSmall;

		public static ConfigEntry<int> RewardsQuotaMedium;

		public static ConfigEntry<int> RewardsGiftBox;

		public static ConfigEntry<bool> RecoverFedBodies;

		public static ConfigEntry<bool> RecoverDrownedBodies;

		public static GameObject newFish;

		public static GameObject companyFishingSpot;

		public static LethalClientMessage<string> clientFeedFishMsg = new LethalClientMessage<string>("feedFishMessage", (Action<string>)null, (Action<string, ulong>)null);

		public static LethalServerMessage<string> serverFeedFishMsg = new LethalServerMessage<string>("feedFishMessage", (Action<string, ulong>)null);

		public static LethalClientEvent clientBodyFedEvent = new LethalClientEvent("bodyFedEvent", (Action)null, (Action<ulong>)null);

		public static LethalServerEvent serverBodyFedEvent = new LethalServerEvent("bodyFedEvent", (Action<ulong>)null);

		public static LethalClientEvent clientFishingSpotEvent = new LethalClientEvent("fishingSpotEvent", (Action)null, (Action<ulong>)null);

		public static LethalServerEvent serverFishingSpotEvent = new LethalServerEvent("fishingSpotEvent", (Action<ulong>)null);

		public static LethalClientEvent clientCompanyDrownEvent = new LethalClientEvent("companyDrownEvent", (Action)null, (Action<ulong>)null);

		public static LethalServerEvent serverCompanyDrownEvent = new LethalServerEvent("companyDrownEvent", (Action<ulong>)null);

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			FishName = ((BaseUnityPlugin)this).Config.Bind<string>("Fish", "GoldfishName", "Daryl", "Name of the crews goldfish");
			EnableRewards = ((BaseUnityPlugin)this).Config.Bind<bool>("Fish", "EnableRewards", true, "Enable rewards when feeding");
			RecoverFedBodies = ((BaseUnityPlugin)this).Config.Bind<bool>("Fish", "RecoverFedBodies", false, "If true, fed bodies will count as recovered at the end of round");
			RecoverDrownedBodies = ((BaseUnityPlugin)this).Config.Bind<bool>("Fish", "RecoverCompanyDrowned", false, "If true, players who jump into the company building water will count as recovered");
			RewardsChanceNone = ((BaseUnityPlugin)this).Config.Bind<int>("Rewards", "ChanceNone", 60, "Chance for no reward");
			RewardsCreditsSmall = ((BaseUnityPlugin)this).Config.Bind<int>("Rewards", "CreditsSmall", 10, "Chance for small credit reward");
			RewardsCreditsMedium = ((BaseUnityPlugin)this).Config.Bind<int>("Rewards", "CreditsMedium", 5, "Chance for medium credit reward");
			RewardsQuotaSmall = ((BaseUnityPlugin)this).Config.Bind<int>("Rewards", "QuotaSmall", 10, "Chance for small quota reward");
			RewardsQuotaMedium = ((BaseUnityPlugin)this).Config.Bind<int>("Rewards", "QuotaMedium", 5, "Chance for medium quota reward");
			ChanceTotal = RewardsChanceNone.Value + RewardsCreditsSmall.Value + RewardsCreditsMedium.Value + RewardsQuotaSmall.Value + RewardsQuotaMedium.Value;
			rewards[RewardsChanceNone] = NoReward;
			rewards[RewardsCreditsSmall] = RewardCreditSmall;
			rewards[RewardsCreditsMedium] = RewardCreditMed;
			rewards[RewardsQuotaSmall] = RewardQuotaSmall;
			rewards[RewardsQuotaMedium] = RewardQuotaMed;
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			MyCustomAssets = AssetBundle.LoadFromFile(Path.Combine(directoryName, "yorimor.feedfish"));
			if ((Object)(object)MyCustomAssets == (Object)null)
			{
				Log.LogError((object)"Failed to load custom assets.");
				return;
			}
			newFish = MyCustomAssets.LoadAsset<GameObject>("assets/yorimor/feedfish/fishbowl.prefab");
			NetworkPrefabs.RegisterNetworkPrefab(newFish);
			companyFishingSpot = MyCustomAssets.LoadAsset<GameObject>("assets/yorimor/feedfish/feedfishspot.prefab");
			NetworkPrefabs.RegisterNetworkPrefab(companyFishingSpot);
			clientFeedFishMsg.OnReceived += FeedFishMsgFromServer;
			serverBodyFedEvent.OnReceived += BodyFedReceiveFromClient;
			serverFishingSpotEvent.OnReceived += FishingSpotEventFromClient;
			serverCompanyDrownEvent.OnReceived += CompanyDrownedEventFromClient;
			harmony.PatchAll(typeof(FeedFish));
			AddLore();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin FeedFish v1.3.0 loaded!");
		}

		private static void AddLore()
		{
			//IL_008e: 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)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			int num = CustomStoryLogs.RegisterCustomLog("Yorimor.FeedFish", FishName.Value + " - 2345 days ago", "Date: 2345 days ago\nThe Worship of " + FishName.Value + " dates back to the early days of the planet Offense. Nowadays it exists as a dusty husk of its former glory.\n\nThe planet was entirely covered in deep oceans in the old days and in those great depths the early settlers discovered a being of unfathomable existence. This glorious existence was later given the name " + FishName.Value + ".\n\nIn the modern era his likeness takes the form of a Goldfish, this is merely an avatar as his true form cannot be understood.\n\nModern day worshipers partake in the acquisition and usage of ladders, each rung  a step closer to the divine. The Ladder was also used as a form of punishment...those against the will of the church were squished under the weight of the ladders.\n\nRecently the high priest took his most loyal worshippers to perform an ancient ceremony known only as the fabled 8 stack. Multiple horizontal ladders extended out towards the ocean so members of the church can re-join the divine lord.\n\nThe high priest holds a sign aloft before the ceremony bearing the utterings of the first settlers as the human body cannot produce the sounds required to recite it in earnest.\n\nIt reads as follows; \"Ph'nglui mglw'nafh " + FishName.Value + " R'lyeh wgah'nagl fhtagn.\"\n\nIts true meaning lost to all but the High Priest who passes it on to his predecessor.\n\n", false, false);
			CustomStoryLogs.RegisterCustomLogCollectable("Yorimor.FeedFish", num, "220 Assurance", new Vector3(76f, 15.7f, -49f), new Vector3(0f, 46f, 90f), 0);
			int num2 = CustomStoryLogs.RegisterCustomLog("Yorimor.FeedFish", "Water - [DATE CORRUPTED]", "Date: [Corrupted]\nI keep dreaming of water, of the ocean.\n\nI don't understand...nobody does.\n\nWe have no water here.\n\nWhy does it call to me.\n\n", false, false);
			CustomStoryLogs.RegisterCustomLogCollectable("Yorimor.FeedFish", num2, "21 Offense", new Vector3(1.8f, 7.5f, -71f), new Vector3(330f, 0f, 275f), 0);
		}

		private void FeedFishMsgFromServer(string data)
		{
			Log.LogInfo((object)data);
		}

		public static void IncrementBodiesFed()
		{
			bodiesFed.Value += 1;
			totalBodiesFed.Value += 1;
		}

		private void BodyFedReceiveFromClient(ulong clientID)
		{
			IncrementBodiesFed();
			RandomReward();
		}

		private void FishingSpotEventFromClient(ulong clientID)
		{
			PlayerControllerB playerController = LethalNetworkExtensions.GetPlayerController(clientID);
			serverFeedFishMsg.SendAllClients(playerController?.playerUsername + " gave themselves to " + FishName.Value, true);
			IncrementBodiesFed();
			GiftReward();
		}

		private void CompanyDrownedEventFromClient(ulong clientID)
		{
			IncrementBodiesFed();
		}

		public void RandomReward(int baseChance = 0)
		{
			int num = _rand.Next(baseChance, ChanceTotal) + bodiesFed.Value;
			if (!EnableRewards.Value)
			{
				return;
			}
			foreach (KeyValuePair<ConfigEntry<int>, RewardHandler> reward in rewards)
			{
				if (num < reward.Key.Value)
				{
					serverFeedFishMsg.SendAllClients($"Rewarding: {((ConfigEntryBase)reward.Key).Definition}!", true);
					reward.Value();
					break;
				}
				num -= reward.Key.Value;
			}
			TimeOfDay.Instance.UpdateProfitQuotaCurrentTime();
		}

		public void GiftReward()
		{
			RandomReward(RewardsChanceNone.Value);
		}

		public void NoReward()
		{
		}

		public void RewardCreditSmall()
		{
			Terminal val = Object.FindObjectOfType<Terminal>();
			val.groupCredits += _rand.Next(10, 5 + 10 * bodiesFed.Value);
			HUDManager.Instance.AddTextToChatOnServer(FishName.Value + " loves you.", -1);
		}

		public void RewardCreditMed()
		{
			Terminal val = Object.FindObjectOfType<Terminal>();
			val.groupCredits += _rand.Next(10, 50 + 25 * bodiesFed.Value);
			HUDManager.Instance.AddTextToChatOnServer(FishName.Value + " loves you.", -1);
		}

		public void RewardQuotaSmall()
		{
			TimeOfDay instance = TimeOfDay.Instance;
			instance.quotaFulfilled += _rand.Next(5, 5 + 10 * bodiesFed.Value);
			HUDManager.Instance.AddTextToChatOnServer(FishName.Value + " loves you.", -1);
		}

		public void RewardQuotaMed()
		{
			TimeOfDay instance = TimeOfDay.Instance;
			instance.quotaFulfilled += _rand.Next(5, 50 + 25 * bodiesFed.Value);
			HUDManager.Instance.AddTextToChatOnServer(FishName.Value + " loves you.", -1);
		}

		public void RewardPresent()
		{
			Object.FindObjectOfType<FeedFishInteraction>()?.SpawnPresent();
			HUDManager.Instance.AddTextToChatOnServer(FishName.Value + " loves you.", -1);
		}

		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		private static void DoPatchStartOfRound(StartOfRound __instance)
		{
			foreach (UnlockableItem unlockable in __instance.unlockablesList.unlockables)
			{
				if (unlockable.unlockableName == "Goldfish")
				{
					Log.LogInfo((object)$"Changing FishBowl Prefab to {newFish}");
					unlockable.prefabObject = newFish;
				}
			}
		}

		[HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")]
		[HarmonyPostfix]
		private static void PatchPlayer(PlayerControllerB __instance, ref CallbackContext context)
		{
			InteractTrigger hoveringOverTrigger = __instance.hoveringOverTrigger;
			if (!((Object)(object)hoveringOverTrigger == (Object)null) && ((Object)hoveringOverTrigger).name.StartsWith("FeedTrigger"))
			{
				FeedFishInteraction component = ((Component)hoveringOverTrigger).GetComponent<FeedFishInteraction>();
				component.DoFeedFish(__instance);
			}
		}

		[HarmonyPatch(typeof(StartOfRound), "GetBodiesInShip")]
		[HarmonyPostfix]
		private static void PatchBodyCount(ref int __result)
		{
			if (RecoverFedBodies.Value)
			{
				__result += bodiesFed.Value;
			}
			bodiesFed.Value = 0;
		}

		[HarmonyPatch(typeof(StartOfRound), "StartGame")]
		[HarmonyPostfix]
		private static void SetupCompanyLevelStuff()
		{
			FishingSpot fishingSpot = Object.FindObjectOfType<FishingSpot>();
			if (StartOfRound.Instance.currentLevel.sceneName == "CompanyBuilding")
			{
				if (!Object.op_Implicit((Object)(object)fishingSpot))
				{
					Object.Instantiate<GameObject>(companyFishingSpot);
					companyFishingSpot.GetComponent<NetworkObject>().Spawn(false);
				}
				else
				{
					fishingSpot.triggered = false;
				}
			}
			else if (Object.op_Implicit((Object)(object)fishingSpot))
			{
				Object.Destroy((Object)(object)((Component)((Component)fishingSpot).transform.parent).gameObject);
				companyFishingSpot.GetComponent<NetworkObject>().Despawn(true);
			}
		}

		[HarmonyPatch(typeof(KillLocalPlayer), "KillPlayer")]
		[HarmonyPrefix]
		private static void CompanyDrowningPatch(KillLocalPlayer __instance)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			Log.LogInfo((object)"Player drowned at the company building");
			FishingSpot fishingSpot = Object.FindObjectOfType<FishingSpot>();
			if ((int)__instance.causeOfDeath == 9 && StartOfRound.Instance.currentLevel.sceneName == "CompanyBuilding" && RecoverDrownedBodies.Value && (!Object.op_Implicit((Object)(object)fishingSpot) || !fishingSpot.triggered))
			{
				clientFishingSpotEvent.InvokeServer();
			}
		}
	}
}