Decompiled source of Fartheim v1.2.1

Fartheim.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Fartheim")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Fartheim")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("2483fa13-8406-413c-8bad-a5bf7982d98d")]
[assembly: AssemblyFileVersion("1.2.1")]
[assembly: TargetFramework(".NETFramework,Version=v4.6", FrameworkDisplayName = ".NET Framework 4.6")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.0")]
[module: UnverifiableCode]
namespace Fartheim;

public class RecipeStub
{
	public class RequirementStub
	{
		public string Component;

		public int Amount;

		public int AmountPerLevel;

		public bool Recoverable = true;

		private RequirementStub()
		{
		}

		public static RequirementStub Parse(string def)
		{
			string[] array = def.Split(new char[1] { ':' });
			if (array.Length < 2)
			{
				return null;
			}
			RequirementStub requirementStub = new RequirementStub();
			requirementStub.Component = array[0];
			int.TryParse(array[1], out requirementStub.Amount);
			if (array.Length > 2)
			{
				int.TryParse(array[2], out requirementStub.AmountPerLevel);
			}
			return requirementStub;
		}
	}

	public ItemDrop Item;

	public string CraftingStation;

	public string RepairStation;

	public int MinStationLevel = 1;

	public List<RequirementStub> Requirements = new List<RequirementStub>();

	public string Name => "Recipe" + ((Object)Item).name;
}
[HarmonyPatch]
public static class AssetHelper
{
	public static readonly List<GameObject> Prefabs = new List<GameObject>();

	private static readonly List<RecipeStub> RecipeStubs = new List<RecipeStub>();

	private static readonly List<KeyValuePair<string, StatusEffect>> StatusEffects = new List<KeyValuePair<string, StatusEffect>>();

	public static AssetBundle LoadAssetBundle(string name)
	{
		Assembly callingAssembly = Assembly.GetCallingAssembly();
		return AssetBundle.LoadFromStream(callingAssembly.GetManifestResourceStream(callingAssembly.GetName().Name + "." + name));
	}

	public static void RegisterPrefab(GameObject prefab)
	{
		Prefabs.Add(prefab);
		Object.DontDestroyOnLoad((Object)(object)prefab);
	}

	public static void RegisterRecipe(RecipeStub rs)
	{
		RecipeStubs.Add(rs);
	}

	public static void RegisterStatusEffect<T>(string name) where T : StatusEffect
	{
		StatusEffects.Add(new KeyValuePair<string, StatusEffect>(name, (StatusEffect)(object)ScriptableObject.CreateInstance<T>()));
	}

	public static RecipeStub GetRecipeStub(string itemName)
	{
		return RecipeStubs.Find((RecipeStub r) => ((Object)r.Item).name == itemName);
	}

	public static Recipe BuildRecipe(RecipeStub rs, ObjectDB odb)
	{
		//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d0: Expected O, but got Unknown
		Recipe val = ScriptableObject.CreateInstance<Recipe>();
		val.m_item = rs.Item;
		GameObject itemPrefab = odb.GetItemPrefab(rs.CraftingStation);
		val.m_craftingStation = ((itemPrefab != null) ? itemPrefab.GetComponentInChildren<CraftingStation>(true) : null);
		if ((Object)(object)val.m_craftingStation == (Object)null)
		{
			ZNetScene instance = ZNetScene.instance;
			object craftingStation;
			if (instance == null)
			{
				craftingStation = null;
			}
			else
			{
				GameObject prefab = instance.GetPrefab(rs.CraftingStation);
				craftingStation = ((prefab != null) ? prefab.GetComponentInChildren<CraftingStation>(true) : null);
			}
			val.m_craftingStation = (CraftingStation)craftingStation;
			if ((Object)(object)val.m_craftingStation == (Object)null)
			{
				Plugin.Log.LogInfo((object)("BuildRecipe couldn't find crafting station " + rs.CraftingStation + " for " + rs.Name));
				return null;
			}
		}
		if (!string.IsNullOrWhiteSpace(rs.RepairStation))
		{
			GameObject itemPrefab2 = odb.GetItemPrefab(rs.RepairStation);
			val.m_repairStation = ((itemPrefab2 != null) ? itemPrefab2.GetComponentInChildren<CraftingStation>(true) : null);
			if ((Object)(object)val.m_repairStation == (Object)null)
			{
				ZNetScene instance2 = ZNetScene.instance;
				object repairStation;
				if (instance2 == null)
				{
					repairStation = null;
				}
				else
				{
					GameObject prefab2 = instance2.GetPrefab(rs.RepairStation);
					repairStation = ((prefab2 != null) ? prefab2.GetComponentInChildren<CraftingStation>(true) : null);
				}
				val.m_repairStation = (CraftingStation)repairStation;
				if ((Object)(object)val.m_repairStation == (Object)null)
				{
					Plugin.Log.LogInfo((object)("BuildRecipe couldn't find declared repair station " + rs.RepairStation + " for " + rs.Name));
					return null;
				}
			}
			if ((Object)(object)val.m_repairStation == (Object)null)
			{
				return null;
			}
		}
		val.m_minStationLevel = Mathf.Max(1, rs.MinStationLevel);
		List<Requirement> list = new List<Requirement>();
		foreach (RecipeStub.RequirementStub requirement in rs.Requirements)
		{
			GameObject itemPrefab3 = odb.GetItemPrefab(requirement.Component);
			ItemDrop val2 = ((itemPrefab3 != null) ? itemPrefab3.GetComponentInChildren<ItemDrop>(true) : null);
			if (!Object.op_Implicit((Object)(object)val2))
			{
				Plugin.Log.LogInfo((object)("BuildRecipe couldn't get requirement component " + requirement.Component + " for " + rs.Name));
				return null;
			}
			Requirement val3 = new Requirement();
			val3.m_resItem = val2;
			val3.m_amount = requirement.Amount;
			val3.m_amountPerLevel = requirement.AmountPerLevel;
			val3.m_recover = requirement.Recoverable;
			list.Add(val3);
		}
		val.m_resources = list.ToArray();
		return val;
	}

	private static void PopulateObjectDB(ObjectDB odb)
	{
		if (Prefabs.Count > 0 && !Object.op_Implicit((Object)(object)odb.m_items.Find((GameObject p) => ((Object)p).name == ((Object)Prefabs[0]).name)))
		{
			foreach (GameObject prefab in Prefabs)
			{
				if (Object.op_Implicit((Object)(object)prefab.GetComponentInChildren<ItemDrop>(true)))
				{
					odb.m_items.Add(prefab);
				}
			}
			odb.UpdateRegisters();
		}
		if (RecipeStubs.Count > 0 && !Object.op_Implicit((Object)(object)odb.GetRecipe(RecipeStubs[0].Item.m_itemData)))
		{
			foreach (RecipeStub recipeStub in RecipeStubs)
			{
				Recipe val = BuildRecipe(recipeStub, odb);
				if (Object.op_Implicit((Object)(object)val))
				{
					odb.m_recipes.Add(val);
					Plugin.Log.LogInfo((object)("Added recipe " + ((Object)val).name));
				}
			}
		}
		if (StatusEffects.Count <= 0 || Object.op_Implicit((Object)(object)odb.GetStatusEffect(StringExtensionMethods.GetStableHashCode(StatusEffects[0].Key))))
		{
			return;
		}
		foreach (KeyValuePair<string, StatusEffect> statusEffect in StatusEffects)
		{
			odb.m_StatusEffects.Add(statusEffect.Value);
		}
	}

	public static void UpdateRecipes()
	{
		foreach (RecipeStub recipeStub in RecipeStubs)
		{
			Recipe r = BuildRecipe(recipeStub, ObjectDB.instance);
			if (Object.op_Implicit((Object)(object)r))
			{
				Recipe val = ObjectDB.instance.m_recipes.Find((Recipe rt) => ((Object)rt).name == ((Object)r).name);
				if (Object.op_Implicit((Object)(object)val))
				{
					ObjectDB.instance.m_recipes.Remove(val);
				}
				ObjectDB.instance.m_recipes.Add(r);
				Plugin.Log.LogInfo((object)("Updated recipe " + ((Object)r).name));
			}
		}
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(ObjectDB), "Awake")]
	public static void AwakePostfix(ObjectDB __instance)
	{
		PopulateObjectDB(__instance);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
	public static void CopyOtherDBPostfix(ObjectDB __instance, ObjectDB other)
	{
		PopulateObjectDB(__instance);
	}

	[HarmonyPostfix]
	[HarmonyPatch(typeof(ZNetScene), "Awake")]
	public static void AwakePostfix(ZNetScene __instance)
	{
		if (Prefabs.Count == 0)
		{
			return;
		}
		foreach (GameObject prefab in Prefabs)
		{
			__instance.m_namedPrefabs[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = prefab;
		}
	}
}
public class Farter : MonoBehaviour
{
	private static string[] BoneRoots = new string[3] { "Hip", "Hips", "l_hip" };

	private AudioSource AS;

	private Character Char;

	private bool Crouching;

	private float TimeSinceLastFart;

	private float FartTimerDelay;

	private ParticleSystem PS;

	private float SizeScalar = 1f;

	public void Awake()
	{
		//IL_0381: Unknown result type (might be due to invalid IL or missing references)
		//IL_0386: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
		Char = ((Component)this).GetComponentInChildren<Character>();
		AS = ((Component)this).gameObject.AddComponent<AudioSource>();
		AS.playOnAwake = false;
		AS.maxDistance = Plugin.FartNoiseRange.Value;
		AS.rolloffMode = (AudioRolloffMode)1;
		AS.spatialBlend = 1f;
		AS.outputAudioMixerGroup = AudioMan.m_instance.m_ambientMixer;
		Transform val = null;
		if (Object.op_Implicit((Object)(object)Char) && !((Object)((Component)this).gameObject).name.StartsWith("Skeleton") && !((Object)((Component)this).gameObject).name.StartsWith("Blob"))
		{
			string bone = null;
			SkinnedMeshRenderer componentInChildren = ((Component)this).gameObject.GetComponentInChildren<SkinnedMeshRenderer>();
			if (Object.op_Implicit((Object)(object)componentInChildren))
			{
				if (((Object)((Component)this).gameObject).name.StartsWith("Boar") || ((Object)((Component)this).gameObject).name.StartsWith("Wolf"))
				{
					bone = "Pelvis";
				}
				else if (((Object)((Component)this).gameObject).name.StartsWith("Deer"))
				{
					bone = "L Thigh";
				}
				else if (((Object)((Component)this).gameObject).name.StartsWith("Dragon"))
				{
					bone = "Hips.001";
				}
				else if (((Object)((Component)this).gameObject).name.StartsWith("Draugr"))
				{
					bone = "LeftHip";
				}
				else if (((Object)((Component)this).gameObject).name.StartsWith("Eikthyr"))
				{
					bone = "Bone.009";
				}
				else if (((Object)((Component)this).gameObject).name.StartsWith("Hatchling"))
				{
					bone = "Spine1";
				}
				else if (((Object)((Component)this).gameObject).name.StartsWith("Surtling"))
				{
					bone = "mixamorig:Hips";
				}
				else if (((Object)((Component)this).gameObject).name.StartsWith("Troll"))
				{
					bone = "Spine0";
				}
				if (bone != null)
				{
					val = ((IEnumerable<Transform>)componentInChildren.bones).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == bone));
					if (!Object.op_Implicit((Object)(object)val))
					{
						val = ((Component)this).transform;
					}
				}
				else
				{
					val = ((IEnumerable<Transform>)componentInChildren.bones).FirstOrDefault((Func<Transform, bool>)((Transform t) => BoneRoots.Contains(((Object)t).name)));
				}
			}
		}
		if (!Object.op_Implicit((Object)(object)val))
		{
			val = ((Component)this).transform;
		}
		GameObject val2 = Object.Instantiate<GameObject>(Plugin.FartSystemPrefab, val);
		PS = val2.GetComponent<ParticleSystem>();
		CapsuleCollider componentInChildren2 = ((Component)this).gameObject.GetComponentInChildren<CapsuleCollider>();
		if (Object.op_Implicit((Object)(object)componentInChildren2))
		{
			double num = componentInChildren2.radius;
			double num2 = componentInChildren2.height;
			double num3 = 4.1887902047863905 * Math.Pow(num, 3.0);
			if (num2 - 2.0 * num > 0.0)
			{
				num3 += Math.PI * Math.Pow(num, 2.0);
			}
			SizeScalar = (float)Math.Sqrt(num3);
		}
		else
		{
			SphereCollider componentInChildren3 = ((Component)this).gameObject.GetComponentInChildren<SphereCollider>();
			if (Object.op_Implicit((Object)(object)componentInChildren3))
			{
				double d = 4.1887902047863905 * Math.Pow(componentInChildren3.radius, 3.0);
				SizeScalar = (float)Math.Sqrt(d);
			}
		}
		if (SizeScalar != 1f)
		{
			MainModule main = PS.main;
			((MainModule)(ref main)).startSpeedMultiplier = SizeScalar;
			((MainModule)(ref main)).startSizeMultiplier = SizeScalar;
			VelocityOverLifetimeModule velocityOverLifetime = PS.velocityOverLifetime;
			((VelocityOverLifetimeModule)(ref velocityOverLifetime)).speedModifierMultiplier = SizeScalar;
		}
	}

	private void Fart()
	{
		//IL_011e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0123: 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_0133: 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_0148: Unknown result type (might be due to invalid IL or missing references)
		List<AudioClip> list = ((Object.op_Implicit((Object)(object)Char) && Char.InWater()) ? Plugin.WetFarts : Plugin.DryFarts);
		int index = ((!Object.op_Implicit((Object)(object)Char) || !Char.IsPlayer() || !Plugin.BunsOfSteel.Value) ? Mathf.Min(list.Count - 1, (int)(Random.value * (float)list.Count)) : Mathf.Min(list.Count - 1, (int)(TimeSinceLastFart / Plugin.MaxFartTime.Value * (float)list.Count)));
		AudioClip val = list[index];
		AS.pitch = (0.75f + Random.value * 0.5f) / SizeScalar;
		AS.PlayOneShot(val, Mathf.Clamp(TimeSinceLastFart / Plugin.MaxFartTime.Value, 0.25f, 1f));
		FartTimerDelay = val.length + 1f + Random.value;
		TimeSinceLastFart = 0f;
		((Component)PS).transform.rotation = Quaternion.LookRotation(-((Component)this).transform.forward, ((Component)this).transform.up);
		MainModule main = PS.main;
		((MainModule)(ref main)).duration = val.length;
		PS.Play();
	}

	public void Update()
	{
		//IL_012c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0131: 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_0198: Unknown result type (might be due to invalid IL or missing references)
		//IL_019b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
		//IL_0172: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		if (!Object.op_Implicit((Object)(object)Player.m_localPlayer))
		{
			return;
		}
		if (!Object.op_Implicit((Object)(object)Char) || !Char.IsPlayer() || !Plugin.BunsOfSteel.Value)
		{
			if (FartTimerDelay <= 0f)
			{
				TimeSinceLastFart += Time.deltaTime;
				float num = Random.value * Plugin.MaxFartTime.Value;
				if (TimeSinceLastFart >= num)
				{
					Fart();
				}
				else
				{
					FartTimerDelay += 0.5f + Random.value;
				}
			}
			else
			{
				FartTimerDelay -= Time.deltaTime;
				if (TimeSinceLastFart > 0f)
				{
					TimeSinceLastFart += Time.deltaTime;
				}
			}
		}
		else
		{
			TimeSinceLastFart += Time.deltaTime;
		}
		if (Object.op_Implicit((Object)(object)Char) && Char.IsCrouching())
		{
			if (!Crouching)
			{
				Crouching = true;
				Fart();
			}
		}
		else if (Crouching)
		{
			Crouching = false;
		}
		if (Object.op_Implicit((Object)(object)PS))
		{
			ForceOverLifetimeModule forceOverLifetime = PS.forceOverLifetime;
			if (Object.op_Implicit((Object)(object)Char) && (Char.InInterior() || (Char.IsPlayer() && ((Player)/*isinst with value type is only supported in some contexts*/).InShelter())))
			{
				((ForceOverLifetimeModule)(ref forceOverLifetime)).x = MinMaxCurve.op_Implicit(0f);
				((ForceOverLifetimeModule)(ref forceOverLifetime)).z = MinMaxCurve.op_Implicit(0f);
			}
			else
			{
				Vector3 windForce = EnvMan.instance.GetWindForce();
				((ForceOverLifetimeModule)(ref forceOverLifetime)).x = MinMaxCurve.op_Implicit(windForce.x * 3f);
				((ForceOverLifetimeModule)(ref forceOverLifetime)).z = MinMaxCurve.op_Implicit(windForce.z * 3f);
			}
		}
	}
}
[HarmonyPatch(typeof(Character))]
public class CharacterPatches
{
	[HarmonyPostfix]
	[HarmonyPatch("Awake")]
	public static void AwakePostfix(Character __instance)
	{
		if (!Plugin.OnlyPlayers.Value || __instance is Player)
		{
			((Component)__instance).gameObject.AddComponent<Farter>();
		}
	}
}
[HarmonyPatch(typeof(RandomFlyingBird))]
public class RandomFlyingBirdPatches
{
	[HarmonyPostfix]
	[HarmonyPatch("Awake")]
	public static void AwakePostfix(RandomFlyingBird __instance)
	{
		if (Plugin.ShouldBirdsFart.Value)
		{
			((Component)__instance).gameObject.AddComponent<Farter>();
		}
	}
}
[BepInPlugin("pfhoenix.fartheim", "Fartheim", "1.2.1")]
public class Plugin : BaseUnityPlugin
{
	public const string Version = "1.2.1";

	public const string ModName = "Fartheim";

	private Harmony _Harmony;

	public static ManualLogSource Log;

	private AssetBundle AB;

	public static List<AudioClip> DryFarts = new List<AudioClip>();

	public static List<AudioClip> WetFarts = new List<AudioClip>();

	public static GameObject FartSystemPrefab;

	public static ConfigEntry<float> MaxFartTime;

	public static ConfigEntry<float> FartNoiseRange;

	public static ConfigEntry<bool> BunsOfSteel;

	public static ConfigEntry<bool> ShouldBirdsFart;

	public static ConfigEntry<bool> OnlyPlayers;

	private void Awake()
	{
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_000b: Expected O, but got Unknown
		Log = new ManualLogSource((string)null);
		AB = AssetHelper.LoadAssetBundle("fartheim");
		AudioClip[] array = AB.LoadAllAssets<AudioClip>();
		foreach (AudioClip val in array)
		{
			if (((Object)val).name.Contains("water"))
			{
				WetFarts.Add(val);
			}
			else
			{
				DryFarts.Add(val);
			}
		}
		if (DryFarts.Count > 0)
		{
			DryFarts = DryFarts.OrderBy((AudioClip f) => f.length).ToList();
		}
		if (WetFarts.Count > 0)
		{
			WetFarts = WetFarts.OrderBy((AudioClip f) => f.length).ToList();
		}
		FartSystemPrefab = AB.LoadAsset<GameObject>("Assets\\FartSystem.prefab");
		AssetHelper.RegisterPrefab(FartSystemPrefab);
		MaxFartTime = ((BaseUnityPlugin)this).Config.Bind<float>("Farts", "Maximum Fart Time", 30f, (ConfigDescription)null);
		FartNoiseRange = ((BaseUnityPlugin)this).Config.Bind<float>("Farts", "Fart Noise Range", 32f, (ConfigDescription)null);
		BunsOfSteel = ((BaseUnityPlugin)this).Config.Bind<bool>("Farts", "Players Only Fart When Crouching", true, (ConfigDescription)null);
		ShouldBirdsFart = ((BaseUnityPlugin)this).Config.Bind<bool>("Farts", "Should Birds Fart", true, (ConfigDescription)null);
		OnlyPlayers = ((BaseUnityPlugin)this).Config.Bind<bool>("Farts", "Only Players Fart (unrealistic)", false, (ConfigDescription)null);
		_Harmony = Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), (string)null);
	}

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