Decompiled source of WoodenCrossbow v1.0.2

plugins/WoodenCrossbow.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using WoodenCrossbow.Configurations;
using WoodenCrossbow.Items;
using WoodenCrossbow.Localizations;
using WoodenCrossbow.Utilities;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WoodenCrossbow")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WoodenCrossbow")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.0.2")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.2.0")]
namespace WoodenCrossbow
{
	[BepInPlugin("com.naexn.WoodenCrossbow", "WoodenCrossbow", "1.0.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal class WoodenCrossbow : BaseUnityPlugin
	{
		public const string PluginGUID = "com.naexn.WoodenCrossbow";

		public const string PluginName = "WoodenCrossbow";

		public const string PluginVersion = "1.0.2";

		public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization();

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			Logger.LogInfo((object)"WoodenCrossbow v1.0.2 has landed!");
			CrossbowConfig.CreateConfigValues(((BaseUnityPlugin)this).Config);
			CrossbowConfig.RegisterChangeCallbacks();
			ModLocalizationManager.Init();
			PrefabManager.OnVanillaPrefabsAvailable += OnVanillaPrefabsAvailable;
			new Harmony("com.naexn.WoodenCrossbow").PatchAll();
		}

		private void OnVanillaPrefabsAvailable()
		{
			PrefabManager.OnVanillaPrefabsAvailable -= OnVanillaPrefabsAvailable;
			WoodenCrossbowItem.Register();
		}
	}
}
namespace WoodenCrossbow.Utilities
{
	public static class AssetHelper
	{
		public static Sprite LoadSpriteFromFile(string relativePath)
		{
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			if (directoryName == null)
			{
				return null;
			}
			string text = Path.Combine(directoryName, relativePath);
			if (!File.Exists(text))
			{
				Logger.LogWarning((object)("[AssetHelper] File not found at path: " + text));
				return null;
			}
			return AssetUtils.LoadSpriteFromFile(text);
		}
	}
	public static class AudioHelper
	{
		public static void ConfigureWeaponAudio(ItemDrop targetItemDrop, string bowPrefabName, float originalVolume = 0.2f, float bowVolume = 0.8f)
		{
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023f: Expected O, but got Unknown
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Expected O, but got Unknown
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0267: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Expected O, but got Unknown
			if (targetItemDrop?.m_itemData?.m_shared == null)
			{
				return;
			}
			SharedData shared = targetItemDrop.m_itemData.m_shared;
			GameObject prefab = PrefabManager.Instance.GetPrefab(bowPrefabName);
			SharedData val = ((prefab == null) ? null : prefab.GetComponent<ItemDrop>()?.m_itemData?.m_shared);
			if (val == null)
			{
				Logger.LogWarning((object)("[AudioHelper] Could not resolve SharedData for '" + bowPrefabName + "'."));
				return;
			}
			GameObject val2 = shared.m_triggerEffect?.m_effectPrefabs?.FirstOrDefault((Func<EffectData, bool>)((EffectData e) => (Object)(object)e.m_prefab != (Object)null && IsAudioPrefab(e.m_prefab)))?.m_prefab;
			GameObject val3 = val.m_triggerEffect?.m_effectPrefabs?.FirstOrDefault((Func<EffectData, bool>)((EffectData e) => (Object)(object)e.m_prefab != (Object)null && IsAudioPrefab(e.m_prefab)))?.m_prefab;
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null))
			{
				string arg = shared.m_name?.Replace("$", "").Replace(" ", "") ?? "CustomWeapon";
				GameObject val4 = PrefabManager.Instance.CreateClonedPrefab($"SFX_{arg}_Original_{Mathf.RoundToInt(originalVolume * 100f)}", val2);
				GameObject val5 = PrefabManager.Instance.CreateClonedPrefab($"SFX_{arg}_Bow_{Mathf.RoundToInt(bowVolume * 100f)}", val3);
				AdjustVolume(val4, originalVolume);
				AdjustVolume(val5, bowVolume);
				PrefabManager.Instance.AddPrefab(val4);
				PrefabManager.Instance.AddPrefab(val5);
				List<EffectData> list = shared.m_triggerEffect?.m_effectPrefabs?.Where((EffectData e) => (Object)(object)e.m_prefab != (Object)null && !IsAudioPrefab(e.m_prefab))?.ToList() ?? new List<EffectData>();
				list.Add(new EffectData
				{
					m_prefab = val4,
					m_enabled = true,
					m_attach = true
				});
				list.Add(new EffectData
				{
					m_prefab = val5,
					m_enabled = true,
					m_attach = true
				});
				shared.m_triggerEffect = new EffectList
				{
					m_effectPrefabs = list.ToArray()
				};
			}
		}

		private static bool IsAudioPrefab(GameObject prefab)
		{
			if ((Object)(object)prefab == (Object)null)
			{
				return false;
			}
			if (((Object)prefab).name.StartsWith("sfx_", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (!((Object)(object)prefab.GetComponentInChildren<AudioSource>(true) != (Object)null))
			{
				return (Object)(object)prefab.GetComponentInChildren<ZSFX>(true) != (Object)null;
			}
			return true;
		}

		private static void AdjustVolume(GameObject sfxPrefab, float multiplier)
		{
			if (!((Object)(object)sfxPrefab == (Object)null))
			{
				AudioSource[] componentsInChildren = sfxPrefab.GetComponentsInChildren<AudioSource>(true);
				foreach (AudioSource obj in componentsInChildren)
				{
					obj.volume *= multiplier;
				}
				ZSFX[] componentsInChildren2 = sfxPrefab.GetComponentsInChildren<ZSFX>(true);
				foreach (ZSFX obj2 in componentsInChildren2)
				{
					obj2.m_minVol *= multiplier;
					obj2.m_maxVol *= multiplier;
				}
			}
		}
	}
	public static class MaterialHelper
	{
		public static void ApplyWoodenWeaponsMaterial(GameObject targetPrefab)
		{
			if ((Object)(object)targetPrefab == (Object)null)
			{
				return;
			}
			GameObject prefab = PrefabManager.Instance.GetPrefab("SwordWood");
			if ((Object)(object)prefab == (Object)null)
			{
				return;
			}
			Renderer val = ((IEnumerable<Renderer>)prefab.GetComponentsInChildren<Renderer>(true)).FirstOrDefault((Func<Renderer, bool>)((Renderer r) => r is MeshRenderer || r is SkinnedMeshRenderer));
			if ((Object)(object)((val != null) ? val.sharedMaterial : null) == (Object)null)
			{
				return;
			}
			Material sharedMaterial = val.sharedMaterial;
			Renderer[] componentsInChildren = targetPrefab.GetComponentsInChildren<Renderer>(true);
			foreach (Renderer val2 in componentsInChildren)
			{
				if (!(val2 is ParticleSystemRenderer))
				{
					val2.sharedMaterial = sharedMaterial;
				}
			}
		}
	}
}
namespace WoodenCrossbow.Patches
{
	[HarmonyPatch(typeof(Player))]
	public static class RecipePatches
	{
		[HarmonyPatch("AddKnownItem")]
		[HarmonyPostfix]
		private static void Postfix_AddKnownItem(Player __instance, ItemData item)
		{
			if (!((Object)(object)__instance == (Object)null) && item != null && WoodenCrossbowItem.UnlockTriggerTokens.Contains(item.m_shared.m_name))
			{
				WoodenCrossbowItem.UnlockRecipeForPlayer(__instance);
			}
		}

		[HarmonyPatch("OnSpawned")]
		[HarmonyPostfix]
		private static void Postfix_OnSpawned(Player __instance)
		{
			if ((Object)(object)__instance == (Object)null || !((Character)__instance).IsOwner())
			{
				return;
			}
			foreach (string unlockTriggerToken in WoodenCrossbowItem.UnlockTriggerTokens)
			{
				if (__instance.IsKnownMaterial(unlockTriggerToken))
				{
					WoodenCrossbowItem.UnlockRecipeForPlayer(__instance);
					break;
				}
			}
		}
	}
}
namespace WoodenCrossbow.Localizations
{
	public static class ModLocalizationManager
	{
		public static void Init()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string> { { "item_woodencrossbow", "Wooden Crossbow" } });
			text = "Czech";
			localization.AddTranslation(ref text, new Dictionary<string, string> { { "item_woodencrossbow", "Dřevěná kuše" } });
		}
	}
}
namespace WoodenCrossbow.Items
{
	internal class WoodenCrossbowItem
	{
		public const string ItemName = "WoodenCrossbow";

		private const string BaseBowAudioPrefab = "BowFineWood";

		private const float CrossbowSnapVolume = 0.4f;

		private const float BowReleaseVolume = 0.6f;

		public static readonly HashSet<string> UnlockTriggerTokens = new HashSet<string> { "$item_crossbow_arbalest", "$item_crossbow_ripper", "$item_crossbow_gold", "$item_crossbow_bloodlightning_gold", "$item_crossbow_frostfire_gold" };

		public static void Register()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			ItemConfig val = CreateItemConfig();
			CustomItem val2 = new CustomItem("WoodenCrossbow", "CrossbowArbalest", val);
			if (val2.Recipe != null)
			{
				val2.Recipe.Recipe.m_enabled = false;
			}
			ConfigureItemStats(val2.ItemDrop);
			Sprite val3 = AssetHelper.LoadSpriteFromFile("Assets/WoodenCrossbow_icon.png");
			if ((Object)(object)val3 != (Object)null)
			{
				val2.ItemDrop.m_itemData.m_shared.m_icons = (Sprite[])(object)new Sprite[1] { val3 };
			}
			MaterialHelper.ApplyWoodenWeaponsMaterial(val2.ItemPrefab);
			ItemManager.Instance.AddItem(val2);
			GameObject prefab = PrefabManager.Instance.GetPrefab("WoodenCrossbow");
			ItemDrop targetItemDrop = default(ItemDrop);
			if ((Object)(object)prefab != (Object)null && prefab.TryGetComponent<ItemDrop>(ref targetItemDrop))
			{
				AudioHelper.ConfigureWeaponAudio(targetItemDrop, "BowFineWood", 0.4f, 0.6f);
			}
		}

		private static ItemConfig CreateItemConfig()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			ItemConfig val = new ItemConfig
			{
				Name = "$item_woodencrossbow",
				Description = "$item_atgeir_wood_description",
				CraftingStation = CraftingStations.Workbench,
				MinStationLevel = 1
			};
			val.AddRequirement("Wood", 10, 1);
			val.AddRequirement("FineWood", 5, 1);
			val.AddRequirement("YggdrasilWood", 2, 1);
			val.AddRequirement("Root", 2, 1);
			return val;
		}

		private static void ConfigureItemStats(ItemDrop itemDrop)
		{
			if (itemDrop?.m_itemData?.m_shared != null)
			{
				SharedData shared = itemDrop.m_itemData.m_shared;
				shared.m_damages.m_pierce = CrossbowConfig.PierceDamage.Value;
				shared.m_damages.m_chop = 0f;
				shared.m_attackForce = CrossbowConfig.KnockbackForce.Value;
				if (shared.m_attack != null)
				{
					shared.m_attack.m_recoilPushback = CrossbowConfig.RecoilPushbackForce.Value;
					Attack attack = shared.m_attack;
					attack.m_reloadTime *= CrossbowConfig.ReloadTimeMultiplier.Value;
					Attack attack2 = shared.m_attack;
					attack2.m_projectileVel *= CrossbowConfig.ProjectileVelocityMultiplier.Value;
					Attack attack3 = shared.m_attack;
					attack3.m_projectileVelMin *= CrossbowConfig.ProjectileVelocityMultiplier.Value;
				}
				shared.m_maxQuality = 1;
				shared.m_scaleByQuality = 0f;
			}
		}

		public static void ApplyConfigStats()
		{
			GameObject prefab = PrefabManager.Instance.GetPrefab("WoodenCrossbow");
			ItemDrop itemDrop = default(ItemDrop);
			if ((Object)(object)prefab != (Object)null && prefab.TryGetComponent<ItemDrop>(ref itemDrop))
			{
				ConfigureItemStats(itemDrop);
			}
		}

		public static void UnlockRecipeForPlayer(Player player)
		{
			CustomItem item = ItemManager.Instance.GetItem("WoodenCrossbow");
			if (!((Object)(object)((item != null) ? item.ItemDrop : null) == (Object)null) && !((Object)(object)player == (Object)null))
			{
				ObjectDB instance = ObjectDB.instance;
				Recipe val = ((instance != null) ? instance.GetRecipe(item.ItemDrop.m_itemData) : null);
				if ((Object)(object)val != (Object)null)
				{
					val.m_enabled = true;
					player.UpdateKnownRecipesList();
				}
			}
		}
	}
}
namespace WoodenCrossbow.Configurations
{
	public class ConfigurationManagerAttributes
	{
		public int? Order;

		public bool? HideSettingName;

		public bool? ReadOnly;

		public bool? IsAdminOnly;
	}
	internal static class CrossbowConfig
	{
		internal static ConfigEntry<float> PierceDamage;

		internal static ConfigEntry<float> KnockbackForce;

		internal static ConfigEntry<float> RecoilPushbackForce;

		internal static ConfigEntry<float> ReloadTimeMultiplier;

		internal static ConfigEntry<float> ProjectileVelocityMultiplier;

		internal static void CreateConfigValues(ConfigFile config)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Expected O, but got Unknown
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Expected O, but got Unknown
			//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fe: Expected O, but got Unknown
			ConfigurationManagerAttributes configurationManagerAttributes = new ConfigurationManagerAttributes
			{
				IsAdminOnly = true
			};
			config.Bind<string>("Important Notice", "RestartWarning", "Changes require a game restart to take effect.", new ConfigDescription("General mod notice.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigurationManagerAttributes
				{
					Order = 1000,
					HideSettingName = true,
					ReadOnly = true
				}
			}));
			PierceDamage = config.Bind<float>("Stats", "Pierce Damage", 1f, new ConfigDescription("Base pierce damage for the Wooden Crossbow.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 200f), new object[2]
			{
				new ConfigurationManagerAttributes
				{
					Order = 100
				},
				configurationManagerAttributes
			}));
			KnockbackForce = config.Bind<float>("Stats", "Knockback Force", 5f, new ConfigDescription("Force applied to targets when hit.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[2]
			{
				new ConfigurationManagerAttributes
				{
					Order = 90
				},
				configurationManagerAttributes
			}));
			RecoilPushbackForce = config.Bind<float>("Stats", "Recoil Pushback Force", 0f, new ConfigDescription("Pushback force applied to the player when firing the crossbow.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), new object[2]
			{
				new ConfigurationManagerAttributes
				{
					Order = 80
				},
				configurationManagerAttributes
			}));
			ReloadTimeMultiplier = config.Bind<float>("Combat", "Reload Time Multiplier", 0.7f, new ConfigDescription("Multiplier applied to reload duration (0.7 = 30% faster reload).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), new object[2]
			{
				new ConfigurationManagerAttributes
				{
					Order = 70
				},
				configurationManagerAttributes
			}));
			ProjectileVelocityMultiplier = config.Bind<float>("Combat", "Projectile Velocity Multiplier", 0.4f, new ConfigDescription("Multiplier for bolt velocity relative to base Arbalest. Visual only.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), new object[2]
			{
				new ConfigurationManagerAttributes
				{
					Order = 60
				},
				configurationManagerAttributes
			}));
		}

		internal static void RegisterChangeCallbacks()
		{
			PierceDamage.SettingChanged += delegate
			{
				UpdateLiveWeaponStats();
			};
			KnockbackForce.SettingChanged += delegate
			{
				UpdateLiveWeaponStats();
			};
			RecoilPushbackForce.SettingChanged += delegate
			{
				UpdateLiveWeaponStats();
			};
			ReloadTimeMultiplier.SettingChanged += delegate
			{
				UpdateLiveWeaponStats();
			};
			ProjectileVelocityMultiplier.SettingChanged += delegate
			{
				UpdateLiveWeaponStats();
			};
		}

		private static void UpdateLiveWeaponStats()
		{
			WoodenCrossbowItem.ApplyConfigStats();
		}
	}
}