Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ProjectileTweaks v1.6.0
ProjectileTweaks.dll
Decompiled a year agousing 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; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Configs; using HarmonyLib; using Jotunn.Managers; using Jotunn.Utils; using Logging; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ProjectileTweaks")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ProjectileTweaks")] [assembly: AssemblyCopyright("Copyright © 2023")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("1.6.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.6.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 ProjectileTweaks { [BepInPlugin("Searica.Valheim.ProjectileTweaks", "ProjectileTweaks", "1.6.0")] [BepInDependency("com.jotunn.jotunn", "2.22.0")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [SynchronizationMode(/*Could not decode attribute arguments.*/)] internal class ProjectileTweaks : BaseUnityPlugin { internal class ProjectileConfig { public string SectionName { get; private set; } public string ProjectileType { get; private set; } public float DefaultSpread { get; private set; } public float DefaultVelocity { get; private set; } public float DefaultLaunchAngle { get; private set; } public float DefaultLoadSpeed { get; private set; } public float DefaultVerticalOffset { get; private set; } public float DefaultHorizontalOffset { get; private set; } public ConfigEntry<float> SpreadMult { get; private set; } public ConfigEntry<float> VelocityMult { get; private set; } public ConfigEntry<float> LaunchAngle { get; private set; } public ConfigEntry<float> LoadSpeed { get; private set; } public ConfigEntry<float> VerticalOffset { get; private set; } public ConfigEntry<float> HorizontalOffset { get; private set; } public ProjectileConfig(ConfigFile configFile, string sectionName, float defaultSpread = 1f, float defaultVelocity = 1f, float defaultLaunchAngle = -1f, float defaultVanillaLaunchAngle = float.NaN, float defaultLoadSpeed = 1f, float defaultVerticalOffset = float.NaN, float defaultHorizontalOffset = float.NaN) { SectionName = sectionName; if (defaultLoadSpeed != float.NaN) { LoadSpeed = configFile.BindConfigInOrder(sectionName, "Load/Draw Speed Multiplier", defaultLoadSpeed, "Multiplier for speed of loading projectiles or drawing bows. Set to 2 to load/draw twice as fast. Does not affect Vanilla scaling with skill level.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f)); LoadSpeed.SettingChanged += UpdateSettings; } if (defaultSpread != float.NaN) { SpreadMult = configFile.BindConfigInOrder(sectionName, "Spread Multiplier", defaultSpread, "Multiplies the min and max projectile spread, so if you set it to zero your projectiles will have zero spread.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f)); SpreadMult.SettingChanged += UpdateSettings; } if (defaultVelocity != float.NaN) { VelocityMult = configFile.BindConfigInOrder(sectionName, "Velocity Multiplier", defaultVelocity, "Multiplies velocity of projectiles.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f)); VelocityMult.SettingChanged += UpdateSettings; } if (defaultLaunchAngle != float.NaN) { LaunchAngle = configFile.BindConfigInOrder(sectionName, "Launch Angle", defaultLaunchAngle, "Changes the launch angle of projectiles. " + ((defaultVanillaLaunchAngle != float.NaN) ? $"Vanilla default is {defaultVanillaLaunchAngle}. " : string.Empty) + "Negative values angle upwards, and positive values angle downwards.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f)); LaunchAngle.SettingChanged += UpdateSettings; } if (defaultHorizontalOffset != float.NaN) { HorizontalOffset = configFile.BindConfigInOrder(sectionName, "Horizontal Offset", defaultHorizontalOffset, "Offsets the location that projectiles are launched from when firing them. Positive shifts it to your characters right. Negative shifts it to your characters left.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 0.75f)); HorizontalOffset.SettingChanged += UpdateSettings; } if (defaultVerticalOffset != float.NaN) { VerticalOffset = configFile.BindConfigInOrder(sectionName, "Vertical Offset", defaultVerticalOffset, "Offsets the location that projectiles are launched from when firing them.Positive shifts it upwards.Negative shifts it downwards.", synced: true, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 0.75f)); VerticalOffset.SettingChanged += UpdateSettings; } } } public const string Author = "Searica"; public const string PluginName = "ProjectileTweaks"; public const string PluginGUID = "Searica.Valheim.ProjectileTweaks"; public const string PluginVersion = "1.6.0"; public static ProjectileTweaks Instance; private const string BombSection = "Bomb Tweaks"; private const string BowSection = "Bow Tweaks"; private const string XbowSection = "Crossbow Tweaks"; private const string SpearSection = "Spear Tweaks"; private const string StaffSection = "Staff Tweaks"; private const string ZoomSection = "Zoom"; private static bool ShouldSaveConfig = false; internal ProjectileConfig BowTweaks; internal ProjectileConfig BombTweaks; internal ProjectileConfig XBowTweaks; internal ProjectileConfig SpearTweaks; internal ProjectileConfig StaffTweaks; private const string AmmoCountSection = "Ammo Count"; internal ConfigEntry<bool> EnableBowZoom { get; private set; } internal ConfigEntry<bool> EnableXbowZoom { get; private set; } internal ConfigEntry<KeyCode> ZoomKey { get; private set; } internal ConfigEntry<KeyCode> CancelDrawKey { get; private set; } internal ConfigEntry<float> StayInZoomTime { get; private set; } internal ConfigEntry<float> TimeToZoomIn { get; private set; } internal ConfigEntry<float> ZoomFactor { get; private set; } internal ConfigEntry<bool> AutoBowZoom { get; private set; } internal bool IsZoomEnabled { get { if (!EnableBowZoom.Value) { return EnableXbowZoom.Value; } return true; } } internal ConfigEntry<bool> ShowAmmoIcon { get; private set; } internal ConfigEntry<Vector2> AmmoIconPosition { get; private set; } internal ConfigEntry<Vector2> AmmoIconSize { get; private set; } internal ConfigEntry<int> AmmoTextSize { get; private set; } internal ConfigEntry<TextAlignmentOptions> AmmoTextAlignment { get; private set; } internal ConfigEntry<Color> AmmoTextColor { get; private set; } internal ConfigEntry<Vector2> AmmoTextPosition { get; private set; } internal static bool ShouldResetIcon { get; set; } = true; public void Awake() { Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); ((BaseUnityPlugin)this).Config.Init("Searica.Valheim.ProjectileTweaks"); SetUpConfigEntries(); ((BaseUnityPlugin)this).Config.Save(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.ProjectileTweaks"); Game.isModded = true; ((BaseUnityPlugin)this).Config.SetupWatcher(); SynchronizationManager.OnConfigurationWindowClosed += delegate { UpdateConfigFile(); }; SynchronizationManager.OnConfigurationSynchronized += delegate { UpdateConfigFile(); }; } public void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetUpConfigEntries() { //IL_0402: Unknown result type (might be due to invalid IL or missing references) //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_04c9: Unknown result type (might be due to invalid IL or missing references) //IL_04fe: Unknown result type (might be due to invalid IL or missing references) BowTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Bow Tweaks", 1f, 1f, -1f, 0f, 1f, 0.2f, 0.2f); BombTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Bomb Tweaks", 1f, 1f, -1f, 0f, float.NaN, 0.5f, 0f); XBowTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Crossbow Tweaks", 1f, 1f, -1f, -1f, 1f, 0f, 0f); SpearTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Spear Tweaks", 1f, 1f, -1f, 0f, float.NaN, 0.5f, 0.1f); StaffTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Staff Tweaks", 1f, 1f, float.NaN, 0f, float.NaN, 0.3f, 0f); EnableBowZoom = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Bow Zoom", defaultValue: true, "Set to true/enabled to allow zooming while using a bow."); EnableBowZoom.SettingChanged += UpdateSettings; EnableXbowZoom = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Crossbow Zoom", defaultValue: true, "Set to true/enabled to allow zooming while using a crossbow."); EnableXbowZoom.SettingChanged += UpdateSettings; ZoomKey = ((BaseUnityPlugin)this).Config.BindConfigInOrder<KeyCode>("Zoom", "Zoom Key", (KeyCode)324, "Set the key used to zoom in while using a bow or crossbow.", synced: false); ZoomKey.SettingChanged += UpdateSettings; CancelDrawKey = ((BaseUnityPlugin)this).Config.BindConfigInOrder<KeyCode>("Zoom", "Cancel Draw Key", (KeyCode)101, "Set the key used to cancel drawing your bow.", synced: false); CancelDrawKey.SettingChanged += UpdateSettings; TimeToZoomIn = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Time to Zoom in", 1f, "Time that it takes to zoom in all the way. '1' is default and recommended.", synced: false, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 2f)); TimeToZoomIn.SettingChanged += UpdateSettings; StayInZoomTime = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Stay In-Zoom Time", 2f, "Set the maximum time the camera will stay zoomed in while holding the zoom key after firing a projectile.", synced: false, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f)); StayInZoomTime.SettingChanged += UpdateSettings; ZoomFactor = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Zoom Factor", 2f, "Set how much too zoom in relative to current camera view.", synced: false, sectionOrder: true, settingOrder: true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f)); ZoomFactor.SettingChanged += UpdateSettings; AutoBowZoom = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Zoom", "Auto Bow Zoom", defaultValue: false, "Set to true/enabled to make bows automatically zoom in as they are drawn.", synced: false); AutoBowZoom.SettingChanged += UpdateSettings; ShowAmmoIcon = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Ammo Count", "Show Ammo Icon", defaultValue: true, "Whether to show ammo count icon in hot bar.", synced: false); AmmoIconPosition = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Vector2>("Ammo Count", "Icon Position", new Vector2(0f, 32f), "Icon Position.", synced: false); AmmoIconSize = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Vector2>("Ammo Count", "Icon Size", new Vector2(20f, 20f), "Icon Size", synced: false); AmmoTextSize = ((BaseUnityPlugin)this).Config.BindConfigInOrder("Ammo Count", "Text Size", 16, "Text Size", synced: false); AmmoTextAlignment = ((BaseUnityPlugin)this).Config.BindConfigInOrder<TextAlignmentOptions>("Ammo Count", "Text Alignment", (TextAlignmentOptions)260, "Text Alignment", synced: false); AmmoTextColor = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Color>("Ammo Count", "Text Color", new Color(1f, 1f, 1f, 1f), "Text Color", synced: false); AmmoTextPosition = ((BaseUnityPlugin)this).Config.BindConfigInOrder<Vector2>("Ammo Count", "Text Positio", new Vector2(-6f, -4f), "Offset of text relative to icon", synced: false); ShowAmmoIcon.SettingChanged += UpdateSettings; AmmoIconPosition.SettingChanged += UpdateSettings; AmmoIconSize.SettingChanged += UpdateSettings; AmmoTextSize.SettingChanged += UpdateSettings; AmmoTextAlignment.SettingChanged += UpdateSettings; AmmoTextColor.SettingChanged += UpdateSettings; AmmoTextPosition.SettingChanged += UpdateSettings; ShowAmmoIcon.SettingChanged += SetUpdateIcon; AmmoIconPosition.SettingChanged += SetUpdateIcon; AmmoIconSize.SettingChanged += SetUpdateIcon; AmmoTextSize.SettingChanged += SetUpdateIcon; AmmoTextAlignment.SettingChanged += SetUpdateIcon; AmmoTextColor.SettingChanged += SetUpdateIcon; AmmoTextPosition.SettingChanged += SetUpdateIcon; } private void UpdateConfigFile() { if (ShouldSaveConfig) { ((BaseUnityPlugin)this).Config.Save(); ShouldSaveConfig = false; } } private static void UpdateSettings(object obj, EventArgs e) { ShouldSaveConfig |= !ShouldSaveConfig; } private static void SetUpdateIcon(object obj, EventArgs e) { ShouldResetIcon |= !ShouldResetIcon; } } [HarmonyPatch] internal static class ZoomManager { internal enum ZoomState { Fixed, ZoomingIn, ZoomingOut } private static ZoomState CurrentZoomState; private static float ZoomInTimer; private static float ZoomOutTimer; private static float ZoomOutDelayTimer; private static float BaseFov; private static float LastZoomFov; private static float NewZoomFov; private const float DiffTol = 0.1f; private const float PercTol = 0.01f; private const float ZoomOutDuration = 1f; [HarmonyPrefix] [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyPriority(0)] private static void UpdateCameraPrefix(GameCamera __instance) { if (ProjectileTweaks.Instance.IsZoomEnabled && (CurrentZoomState == ZoomState.ZoomingOut || CurrentZoomState == ZoomState.ZoomingIn)) { __instance.m_fov = NewZoomFov; } } [HarmonyPostfix] [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyPriority(200)] private static void UpdateCameraPostfix(GameCamera __instance) { if ((Object)(object)__instance != (Object)null && ProjectileTweaks.Instance.IsZoomEnabled && CurrentZoomState == ZoomState.Fixed && Mathf.Abs(__instance.m_fov - BaseFov) > 0.1f) { BaseFov = __instance.m_fov; } } [HarmonyPrefix] [HarmonyPatch(typeof(Player), "SetControls")] private static void SetControlsPrefix(Player __instance, ref bool attackHold, ref bool blockHold) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (ProjectileTweaks.Instance.IsZoomEnabled) { if (attackHold) { blockHold = Input.GetKey(ProjectileTweaks.Instance.CancelDrawKey.Value); } else if (CurrentZoomState == ZoomState.ZoomingIn && HasZoomableItem(__instance)) { blockHold = false; } } } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "UpdateCrosshair")] [HarmonyPriority(0)] private static void UpdateCrosshairPostfix(Player player, float bowDrawPercentage) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) if (!ProjectileTweaks.Instance.IsZoomEnabled || BaseFov == 0f) { return; } if (!HasZoomableItem(player)) { ZoomOut(); return; } bool key = Input.GetKey(ProjectileTweaks.Instance.ZoomKey.Value); bool num = (key || ProjectileTweaks.Instance.AutoBowZoom.Value) && bowDrawPercentage > 0.01f; bool flag = key && ((Humanoid)player).IsWeaponLoaded(); if (num || flag) { ZoomIn(); } else if (key && bowDrawPercentage <= 0.01f) { ProcessZoomOutDelay(); } else { ZoomOut(); } } internal static void ZoomIn() { ZoomInTimer += Time.deltaTime; CurrentZoomState = ZoomState.ZoomingIn; float num = Mathf.InverseLerp(0.05f, ProjectileTweaks.Instance.TimeToZoomIn.Value, ZoomInTimer); LastZoomFov = Mathf.Lerp(BaseFov, BaseFov / ProjectileTweaks.Instance.ZoomFactor.Value, num); GameCamera.instance.m_fov = LastZoomFov; NewZoomFov = LastZoomFov; } public static void ZoomOut() { if (CurrentZoomState != 0) { if (CurrentZoomState == ZoomState.ZoomingIn) { CurrentZoomState = ZoomState.ZoomingOut; ZoomOutTimer = 0f; ZoomInTimer = 0f; } else { ZoomOutTimer += Time.deltaTime; if (ZoomOutTimer > 1f) { GameCamera.instance.m_fov = BaseFov; CurrentZoomState = ZoomState.Fixed; ZoomOutDelayTimer = 0f; return; } } float num = Mathf.InverseLerp(0f, 0.3f, ZoomOutTimer); NewZoomFov = Mathf.Lerp(LastZoomFov, BaseFov, num); GameCamera.instance.m_fov = NewZoomFov; } else if (Mathf.Abs(GameCamera.instance.m_fov - BaseFov) >= 0.1f) { GameCamera.instance.m_fov = BaseFov; } } internal static void ProcessZoomOutDelay() { ZoomOutDelayTimer += Time.deltaTime; if (ZoomOutDelayTimer > ProjectileTweaks.Instance.StayInZoomTime.Value) { ZoomOut(); } } internal static bool HasZoomableItem(Player player) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Invalid comparison between Unknown and I4 ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon != null) { SkillType skillType = currentWeapon.m_shared.m_skillType; bool num = ProjectileTweaks.Instance.EnableBowZoom.Value && (int)skillType == 8; bool flag = ProjectileTweaks.Instance.EnableXbowZoom.Value && (int)skillType == 14; return num || flag; } return false; } } } namespace ProjectileTweaks.Patches { [HarmonyPatch] internal static class AmmoCountPatches { private const string FontName = "Valheim-AveriaSansLibre"; private static bool HasWarnedAboutFont; private const FontStyles FontStyle = 1; private static TMP_FontAsset _CurrentFont; private const string AmmoCountName = "AmmoCount"; private static TMP_FontAsset CurrentFont { get { if (_CurrentFont == null) { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (((Object)val).name == "Valheim-AveriaSansLibre") { _CurrentFont = val; break; } } } if (!HasWarnedAboutFont && _CurrentFont == null) { HasWarnedAboutFont = true; Log.LogWarning("Could not find font Valheim-AveriaSansLibre! Falling back to default font."); } return _CurrentFont; } } [HarmonyPostfix] [HarmonyPatch(typeof(HotkeyBar), "Update")] private static void UpdateHotkeyBarAmmoCounter(HotkeyBar __instance) { if (!Object.op_Implicit((Object)(object)__instance) || !Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return; } for (int i = 0; i < __instance.m_items.Count(); i++) { ItemData val = __instance.m_items[i]; int x = val.m_gridPos.x; if (x >= 0 && x < __instance.m_elements.Count() && __instance.m_elements[x] != null) { ElementData val2 = __instance.m_elements[x]; GameObject go = val2.m_go; Transform ammoCount = go.transform.Find("AmmoCount"); if (Object.op_Implicit((Object)(object)ammoCount) && (ProjectileTweaks.ShouldResetIcon || val2.m_used)) { Object.DestroyImmediate((Object)(object)((Component)ammoCount).gameObject); AddAmmoCounter(go, out ammoCount); } else if (!Object.op_Implicit((Object)(object)ammoCount)) { AddAmmoCounter(go, out ammoCount); } CheckAmmoCount(val, ((Component)ammoCount).gameObject); } } ProjectileTweaks.ShouldResetIcon = false; } private static void AddAmmoCounter(GameObject gameObject, out Transform ammoCount) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0022: 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_003e: 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_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: 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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("AmmoCount"); val.transform.SetParent(gameObject.transform); val.AddComponent<RectTransform>().anchoredPosition = Vector2.zero; ammoCount = val.transform; GameObject val2 = new GameObject("Text"); val2.transform.SetParent(val.transform); TextMeshProUGUI val3 = val2.AddComponent<TextMeshProUGUI>(); RectTransform rectTransform = ((TMP_Text)val3).rectTransform; rectTransform.anchoredPosition = ProjectileTweaks.Instance.AmmoTextPosition.Value; rectTransform.sizeDelta = new Vector2(90f, 90f); if ((Object)(object)CurrentFont != (Object)null) { ((TMP_Text)val3).font = CurrentFont; } ((TMP_Text)val3).fontSize = ProjectileTweaks.Instance.AmmoTextSize.Value; ((TMP_Text)val3).fontStyle = (FontStyles)1; ((TMP_Text)val3).alignment = ProjectileTweaks.Instance.AmmoTextAlignment.Value; ((Graphic)val3).color = ProjectileTweaks.Instance.AmmoTextColor.Value; if (ProjectileTweaks.Instance.ShowAmmoIcon.Value) { GameObject val4 = new GameObject("Icon"); val4.transform.SetParent(val.transform); val4.AddComponent<Image>(); RectTransform component = val4.GetComponent<RectTransform>(); component.anchoredPosition = ProjectileTweaks.Instance.AmmoIconPosition.Value; component.sizeDelta = ProjectileTweaks.Instance.AmmoIconSize.Value; } } private static void CheckAmmoCount(ItemData itemData, GameObject go) { if (!TryGetAmmo(itemData, out var ammoItemData)) { go.SetActive(false); return; } go.SetActive(true); ((TMP_Text)((Component)go.transform.Find("Text")).GetComponent<TextMeshProUGUI>()).text = ammoItemData.m_stack.ToString(); if (ProjectileTweaks.Instance.ShowAmmoIcon.Value) { ((Component)go.transform.Find("Icon")).GetComponent<Image>().sprite = ammoItemData.GetIcon(); } } private static bool TryGetAmmo(ItemData weapon, out ItemData ammoItemData) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 ammoItemData = null; if (string.IsNullOrEmpty(weapon.m_shared.m_ammoType) || (int)weapon.m_shared.m_itemType == 9) { return false; } ammoItemData = ((Humanoid)Player.m_localPlayer).GetAmmoItem(); if (ammoItemData != null && (!((Humanoid)Player.m_localPlayer).GetInventory().ContainsItem(ammoItemData) || ammoItemData.m_shared.m_ammoType != weapon.m_shared.m_ammoType)) { ammoItemData = null; } if (ammoItemData == null) { ammoItemData = ((Humanoid)Player.m_localPlayer).GetInventory().GetAmmoItem(weapon.m_shared.m_ammoType, (string)null); } return ammoItemData != null; } } [HarmonyPatch(typeof(Attack))] internal static class AttackPatch { private static float m_projectileVel; private static float m_projectileVelMin; private static float m_projectileAccuracy; private static float m_projectileAccuracyMin; [HarmonyPostfix] [HarmonyBefore(new string[] { "blacks7ar.BowPlugin" })] [HarmonyPriority(700)] [HarmonyPatch("Start")] internal static void AttackStartPrefix(Attack __instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0019: Invalid comparison between Unknown and I4 //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Invalid comparison between Unknown and I4 //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Invalid comparison between Unknown and I4 //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Invalid comparison between Unknown and I4 ItemData playerWeapon = GetPlayerWeapon(__instance); if (playerWeapon != null) { SkillType skillType = playerWeapon.m_shared.m_skillType; if ((int)skillType == 8) { SetVelocity(__instance, ProjectileTweaks.Instance.BowTweaks.VelocityMult); SetSpread(__instance, ProjectileTweaks.Instance.BowTweaks.SpreadMult); SetLaunchAngle(__instance, ProjectileTweaks.Instance.BowTweaks.LaunchAngle); } else if ((int)skillType == 14) { SetVelocity(__instance, ProjectileTweaks.Instance.XBowTweaks.VelocityMult); SetSpread(__instance, ProjectileTweaks.Instance.XBowTweaks.SpreadMult); SetLaunchAngle(__instance, ProjectileTweaks.Instance.XBowTweaks.LaunchAngle); } else if ((int)skillType == 5) { SetVelocity(__instance, ProjectileTweaks.Instance.SpearTweaks.VelocityMult); SetSpread(__instance, ProjectileTweaks.Instance.SpearTweaks.SpreadMult); SetLaunchAngle(__instance, ProjectileTweaks.Instance.SpearTweaks.LaunchAngle); } else if ((int)skillType == 9) { SetVelocity(__instance, ProjectileTweaks.Instance.StaffTweaks.VelocityMult); SetSpread(__instance, ProjectileTweaks.Instance.StaffTweaks.SpreadMult); } else if (IsBomb(playerWeapon)) { SetVelocity(__instance, ProjectileTweaks.Instance.BombTweaks.VelocityMult); SetSpread(__instance, ProjectileTweaks.Instance.BombTweaks.SpreadMult); SetLaunchAngle(__instance, ProjectileTweaks.Instance.BombTweaks.LaunchAngle); } } } private static void SetVelocity(Attack attack, ConfigEntry<float> velocityMultiplier) { m_projectileVel = attack.m_projectileVel; m_projectileVelMin = attack.m_projectileVelMin; velocityMultiplier.SettingChanged += delegate { attack.m_projectileVel = m_projectileVel * velocityMultiplier.Value; attack.m_projectileVelMin = m_projectileVelMin * velocityMultiplier.Value; }; Attack obj = attack; obj.m_projectileVel *= velocityMultiplier.Value; Attack obj2 = attack; obj2.m_projectileVelMin *= velocityMultiplier.Value; } private static void SetSpread(Attack attack, ConfigEntry<float> spreadConfig) { m_projectileAccuracy = attack.m_projectileAccuracy; m_projectileAccuracyMin = attack.m_projectileAccuracyMin; spreadConfig.SettingChanged += delegate { attack.m_projectileAccuracy = m_projectileAccuracy * spreadConfig.Value; attack.m_projectileAccuracyMin = m_projectileAccuracyMin * spreadConfig.Value; }; Attack obj = attack; obj.m_projectileAccuracy *= spreadConfig.Value; Attack obj2 = attack; obj2.m_projectileAccuracyMin *= spreadConfig.Value; } private static void SetLaunchAngle(Attack attack, ConfigEntry<float> angleConfig) { angleConfig.SettingChanged += delegate { attack.m_launchAngle = angleConfig.Value; }; attack.m_launchAngle = angleConfig.Value; } [HarmonyPostfix] [HarmonyPatch("GetProjectileSpawnPoint")] private static void GetProjectileSpawnPointPostfix(Attack __instance, ref Vector3 spawnPoint, ref Vector3 aimDir) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0019: Invalid comparison between Unknown and I4 //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Invalid comparison between Unknown and I4 //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Invalid comparison between Unknown and I4 //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Invalid comparison between Unknown and I4 ItemData playerWeapon = GetPlayerWeapon(__instance); if (playerWeapon != null) { SkillType skillType = playerWeapon.m_shared.m_skillType; if ((int)skillType == 8) { ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.BowTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.BowTweaks.HorizontalOffset.Value); } else if ((int)skillType == 14) { ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.XBowTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.XBowTweaks.HorizontalOffset.Value); } else if ((int)skillType == 5) { ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.SpearTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.SpearTweaks.HorizontalOffset.Value); } else if ((int)skillType == 9) { ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.StaffTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.StaffTweaks.HorizontalOffset.Value); } else if (IsBomb(playerWeapon)) { ApplyOffset(ref spawnPoint, ref aimDir, ProjectileTweaks.Instance.BombTweaks.VerticalOffset.Value, ProjectileTweaks.Instance.BombTweaks.HorizontalOffset.Value); } } } private static void ApplyOffset(ref Vector3 spawnPoint, ref Vector3 aimDir, float vertOffset, float horzOffset) { //IL_0012: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0051: 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) Vector3 val = new Vector3(aimDir.z, 0f, 0f - aimDir.x); Vector3 normalized = ((Vector3)(ref val)).normalized; normalized *= horzOffset; spawnPoint += normalized; spawnPoint += new Vector3(0f, vertOffset, 0f); } private static ItemData GetPlayerWeapon(Attack attack) { if (attack != null) { Humanoid character = attack.m_character; Player val = (Player)(object)((character is Player) ? character : null); if (val != null && (((Character)val).m_name == "Human" || (Object)(object)val == (Object)(object)Player.m_localPlayer)) { return ((Humanoid)val).GetCurrentWeapon(); } } return null; } private static bool IsBomb(ItemData item) { return item.m_shared.m_attack.m_attackAnimation == "throw_bomb"; } } [HarmonyPatch(typeof(Humanoid))] internal static class HumanoidPatch { [HarmonyPrefix] [HarmonyPriority(0)] [HarmonyPatch("GetAttackDrawPercentage")] private static void GetAttackDrawPercentagePrefix(Humanoid __instance, out float __state) { if (Object.op_Implicit((Object)(object)__instance) && (Object)(object)((__instance is Player) ? __instance : null) == (Object)(object)Player.m_localPlayer) { ItemData currentWeapon = __instance.GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_shared.m_attack.m_bowDraw) { __state = currentWeapon.m_shared.m_attack.m_drawDurationMin; currentWeapon.m_shared.m_attack.m_drawDurationMin = __state * (1f / ProjectileTweaks.Instance.BowTweaks.LoadSpeed.Value); return; } } __state = -1f; } [HarmonyPostfix] [HarmonyPriority(800)] [HarmonyPatch("GetAttackDrawPercentage")] private static void GetAttackDrawPercentagePostfix(Humanoid __instance, ref float __state) { if (__state != -1f) { ItemData currentWeapon = __instance.GetCurrentWeapon(); if (currentWeapon != null && currentWeapon.m_shared.m_attack.m_bowDraw) { currentWeapon.m_shared.m_attack.m_drawDurationMin = __state; } } } } [HarmonyPatch(typeof(ItemData))] internal static class ItemDataPatch { [HarmonyPrefix] [HarmonyPriority(0)] [HarmonyPatch("GetWeaponLoadingTime")] public static void GetWeaponLoadingTimePrefix(ItemData __instance, out float __state) { if (__instance.m_shared.m_attack.m_requiresReload) { __state = __instance.m_shared.m_attack.m_reloadTime; Attack attack = __instance.m_shared.m_attack; attack.m_reloadTime *= 1f / ProjectileTweaks.Instance.XBowTweaks.LoadSpeed.Value; } else { __state = -1f; } } [HarmonyPostfix] [HarmonyPriority(800)] [HarmonyPatch("GetWeaponLoadingTime")] public static void GetWeaponLoadingTimePostfix(ItemData __instance, ref float __state) { if (__instance.m_shared.m_attack.m_requiresReload && __state != -1f) { __instance.m_shared.m_attack.m_reloadTime = __state; } } } } namespace Logging { internal static class Log { internal enum InfoLevel { Low, Medium, High } private static ManualLogSource logSource; internal static ConfigEntry<InfoLevel> Verbosity { get; set; } internal static InfoLevel VerbosityLevel => Verbosity.Value; internal static bool IsVerbosityLow => Verbosity.Value >= InfoLevel.Low; internal static bool IsVerbosityMedium => Verbosity.Value >= InfoLevel.Medium; internal static bool IsVerbosityHigh => Verbosity.Value >= InfoLevel.High; internal static void Init(ManualLogSource logSource) { Log.logSource = logSource; } internal static void LogDebug(object data) { logSource.LogDebug(data); } internal static void LogError(object data) { logSource.LogError(data); } internal static void LogFatal(object data) { logSource.LogFatal(data); } internal static void LogMessage(object data) { logSource.LogMessage(data); } internal static void LogWarning(object data) { logSource.LogWarning(data); } internal static void LogInfo(object data, InfoLevel level = InfoLevel.Low) { if (Verbosity == null || VerbosityLevel >= level) { logSource.LogInfo(data); } } internal static void LogGameObject(GameObject prefab, bool includeChildren = false) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown LogInfo("***** " + ((Object)prefab).name + " *****"); Component[] components = prefab.GetComponents<Component>(); for (int i = 0; i < components.Length; i++) { LogComponent(components[i]); } if (!includeChildren) { return; } LogInfo("***** " + ((Object)prefab).name + " (children) *****"); foreach (Transform item in prefab.transform) { Transform val = item; if (Object.op_Implicit((Object)(object)val)) { LogInfo(" - " + ((Object)val).name); components = ((Component)val).GetComponents<Component>(); for (int i = 0; i < components.Length; i++) { LogComponent(components[i]); } } } } internal static void LogComponent(Component compo) { if (!Object.op_Implicit((Object)(object)compo)) { return; } try { LogInfo("--- " + ((object)compo).GetType().Name + ": " + ((Object)compo).name + " ---"); } catch (Exception ex) { LogError(ex.ToString()); LogWarning("Could not get type name for component!"); return; } try { foreach (PropertyInfo declaredProperty in AccessTools.GetDeclaredProperties(((object)compo).GetType())) { try { LogInfo($" - {declaredProperty.Name} = {declaredProperty.GetValue(compo)}"); } catch (Exception ex2) { LogError(ex2.ToString()); LogWarning("Could not get property: " + declaredProperty.Name + " for component!"); } } } catch (Exception ex3) { LogError(ex3.ToString()); LogWarning("Could not get properties for component!"); } try { foreach (FieldInfo declaredField in AccessTools.GetDeclaredFields(((object)compo).GetType())) { try { LogInfo($" - {declaredField.Name} = {declaredField.GetValue(compo)}"); } catch (Exception ex4) { LogError(ex4.ToString()); LogWarning("Could not get field: " + declaredField.Name + " for component!"); } } } catch (Exception ex5) { LogError(ex5.ToString()); LogWarning("Could not get fields for component!"); } } } } namespace Configs { public static class ConfigFileManager { internal class ConfigFileOrderingMaps { public Dictionary<string, int> sectionToSectionNumber = new Dictionary<string, int>(); public Dictionary<string, int> sectionToSettingOrder = new Dictionary<string, int>(); } internal static string ConfigFileName; internal static string ConfigFileFullPath; internal static DateTime lastRead = DateTime.MinValue; private static readonly Dictionary<string, ConfigFileOrderingMaps> _configFileOrderingMaps = new Dictionary<string, ConfigFileOrderingMaps>(); private static readonly List<string> ConfigManagerGUIDs = new List<string> { "_shudnal.ConfigurationManager", "com.bepis.bepinex.configurationmanager" }; private static BaseUnityPlugin _configManager = null; private const string WindowChangedEventName = "DisplayingWindowChanged"; private const string DisplayingWindowName = "DisplayingWindow"; private static PropertyInfo _dispWindowInfo = null; private static BaseUnityPlugin ConfigManager { get { if ((Object)(object)_configManager == (Object)null) { foreach (string configManagerGUID in ConfigManagerGUIDs) { if (Chainloader.PluginInfos.TryGetValue(configManagerGUID, out var value) && Object.op_Implicit((Object)(object)value.Instance)) { _configManager = value.Instance; break; } } } return _configManager; } } private static PropertyInfo DisplayWindowInfo { get { if ((object)_dispWindowInfo == null) { _dispWindowInfo = ((object)ConfigManager).GetType().GetProperty("DisplayingWindow"); } return _dispWindowInfo; } } internal static event Action OnConfigFileReloaded; internal static event Action OnConfigWindowClosed; private static string GetOrderedSectionName(this ConfigFile configFile, string section) { if (!_configFileOrderingMaps.TryGetValue(configFile.ConfigFilePath, out var value)) { value = new ConfigFileOrderingMaps(); _configFileOrderingMaps.Add(configFile.ConfigFilePath, value); } if (!value.sectionToSectionNumber.TryGetValue(section, out var value2)) { value2 = value.sectionToSectionNumber.Count + 1; value.sectionToSectionNumber[section] = value2; } return $"{value2} - {section}"; } private static int GetSettingOrder(this ConfigFile configFile, string section) { if (!_configFileOrderingMaps.TryGetValue(configFile.ConfigFilePath, out var value)) { value = new ConfigFileOrderingMaps(); _configFileOrderingMaps.Add(configFile.ConfigFilePath, value); } if (!value.sectionToSettingOrder.TryGetValue(section, out var value2)) { value2 = 0; } value.sectionToSettingOrder[section] = value2 - 1; return value2; } internal static string GetExtendedDescription(string description, bool synchronizedSetting) { return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"); } private static void InvokeOnConfigFileReloaded() { Action onConfigFileReloaded = ConfigFileManager.OnConfigFileReloaded; if (onConfigFileReloaded != null) { onConfigFileReloaded.SafeInvoke(); } } private static void InvokeOnConfigWindowClosed() { Action onConfigWindowClosed = ConfigFileManager.OnConfigWindowClosed; if (onConfigWindowClosed != null) { onConfigWindowClosed.SafeInvoke(); } } public static void Init(this ConfigFile configFile, string GUID, bool saveOnConfigSet = false) { configFile.SaveOnConfigSet = saveOnConfigSet; ConfigFileName = GUID + ".cfg"; ConfigFileFullPath = Path.Combine(Paths.ConfigPath, ConfigFileName); } public static bool DisableSaveOnConfigSet(this ConfigFile configFile) { bool saveOnConfigSet = configFile.SaveOnConfigSet; configFile.SaveOnConfigSet = false; return saveOnConfigSet; } public static ConfigEntry<T> BindConfigInOrder<T>(this ConfigFile configFile, string section, string key, T defaultValue, string description, bool synced = true, bool sectionOrder = true, bool settingOrder = true, AcceptableValueBase acceptableValues = null, Action<ConfigEntryBase> customDrawer = null, ConfigurationManagerAttributes configAttributes = null) { section = (sectionOrder ? configFile.GetOrderedSectionName(section) : section); int value = (settingOrder ? configFile.GetSettingOrder(section) : 0); return configFile.BindConfig(section, key, defaultValue, description, synced, value, acceptableValues, customDrawer, configAttributes); } public static ConfigEntry<T> BindConfig<T>(this ConfigFile configFile, string section, string key, T defaultValue, string description, bool synced = true, int? order = null, AcceptableValueBase acceptableValues = null, Action<ConfigEntryBase> customDrawer = null, ConfigurationManagerAttributes configAttributes = null) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown string extendedDescription = GetExtendedDescription(description, synced); if (configAttributes == null) { configAttributes = new ConfigurationManagerAttributes(); } configAttributes.IsAdminOnly = synced; configAttributes.Order = order; configAttributes.CustomDrawer = customDrawer; return configFile.Bind<T>(section, key, defaultValue, new ConfigDescription(extendedDescription, acceptableValues, new object[1] { configAttributes })); } internal static void SetupWatcher(this ConfigFile configFile) { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += configFile.ReloadConfigFile; fileSystemWatcher.Created += configFile.ReloadConfigFile; fileSystemWatcher.Renamed += configFile.ReloadConfigFile; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } internal static void ReloadConfigFile(this ConfigFile configFile, object sender, FileSystemEventArgs eventArgs) { if (!File.Exists(ConfigFileFullPath)) { return; } try { DateTime lastWriteTime = File.GetLastWriteTime(eventArgs.FullPath); if (lastRead != lastWriteTime) { Log.LogInfo("Reloading config file"); bool saveOnConfigSet = configFile.DisableSaveOnConfigSet(); configFile.Reload(); configFile.SaveOnConfigSet = saveOnConfigSet; InvokeOnConfigFileReloaded(); lastRead = lastWriteTime; } } catch { Log.LogError("There was an issue loading your " + ConfigFileName); Log.LogError("Please check your config entries for spelling and format!"); } } internal static void CheckForConfigManager(this ConfigFile config) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)SystemInfo.graphicsDeviceType != 4 && !((Object)(object)ConfigManager == (Object)null)) { Log.LogDebug("Configuration manager found, hooking DisplayingWindowChanged"); EventInfo @event = ((object)ConfigManager).GetType().GetEvent("DisplayingWindowChanged"); if (!(@event == null)) { Action<object, object> action = OnConfigManagerDisplayingWindowChanged; Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, action.Target, action.Method); @event.AddEventHandler(ConfigManager, handler); } } } private static void OnConfigManagerDisplayingWindowChanged(object sender, object e) { if (!(DisplayWindowInfo == null) && !(bool)DisplayWindowInfo.GetValue(ConfigManager, null)) { InvokeOnConfigWindowClosed(); } } private static void SafeInvoke(this Action events) { if (events == null) { return; } Delegate[] invocationList = events.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { Action action = (Action)invocationList[i]; try { action(); } catch (Exception arg) { Log.LogWarning("Exception thrown at event " + new StackFrame(1).GetMethod().Name + $" in {action.Method.DeclaringType.Name}.{action.Method.Name}:\n{arg}"); } } } } }