Please disclose if any significant portion of your mod was created 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.8.0
ProjectileTweaks.dll
Decompiled a week agousing 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 Jotunn.Extensions; 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.8.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.8.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ProjectileTweaks { [BepInPlugin("Searica.Valheim.ProjectileTweaks", "ProjectileTweaks", "1.8.0")] [BepInDependency("com.jotunn.jotunn", "2.30.1")] [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 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 ConfigEntry<float> DepthOffset { 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, float defaultDepthOffset = float.NaN) { SectionName = sectionName; if (!float.IsNaN(defaultLoadSpeed)) { LoadSpeed = ConfigFileExtensions.BindConfigInOrder<float>(configFile, 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.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 2f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); LoadSpeed.SettingChanged += UpdateSettings; } else { LoadSpeed = null; } if (!float.IsNaN(defaultSpread)) { SpreadMult = ConfigFileExtensions.BindConfigInOrder<float>(configFile, sectionName, "Spread Multiplier", defaultSpread, "Multiplies the min and max projectile spread, so if you set it to zero your projectiles will have zero spread.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); SpreadMult.SettingChanged += UpdateSettings; } else { SpreadMult = null; } if (!float.IsNaN(defaultVelocity)) { VelocityMult = ConfigFileExtensions.BindConfigInOrder<float>(configFile, sectionName, "Velocity Multiplier", defaultVelocity, "Multiplies velocity of projectiles.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 2f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); VelocityMult.SettingChanged += UpdateSettings; } else { VelocityMult = null; } if (!float.IsNaN(defaultLaunchAngle)) { LaunchAngle = ConfigFileExtensions.BindConfigInOrder<float>(configFile, 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.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-5f, 5f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); LaunchAngle.SettingChanged += UpdateSettings; } else { LaunchAngle = null; } if (!float.IsNaN(defaultHorizontalOffset)) { HorizontalOffset = ConfigFileExtensions.BindConfigInOrder<float>(configFile, 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.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 0.75f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); HorizontalOffset.SettingChanged += UpdateSettings; } else { HorizontalOffset = null; } if (!float.IsNaN(defaultVerticalOffset)) { VerticalOffset = ConfigFileExtensions.BindConfigInOrder<float>(configFile, sectionName, "Vertical Offset", defaultVerticalOffset, "Offsets the location that projectiles are launched from when firing them. Positive shifts it upwards. Negative shifts it downwards.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 0.75f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); VerticalOffset.SettingChanged += UpdateSettings; } else { VerticalOffset = null; } if (!float.IsNaN(defaultDepthOffset)) { DepthOffset = ConfigFileExtensions.BindConfigInOrder<float>(configFile, sectionName, "Depth Offset", defaultDepthOffset, "Offsets the location that projectiles are launched from when firing them. Positive shifts it away from your character. Negative shifts it towards your character.", true, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.75f, 0.75f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); DepthOffset.SettingChanged += UpdateSettings; } else { DepthOffset = null; } } } public const string Author = "Searica"; public const string PluginName = "ProjectileTweaks"; public const string PluginGUID = "Searica.Valheim.ProjectileTweaks"; public const string PluginVersion = "1.8.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 ThrowingStaffSection = "Staff Tweaks (Throwing)"; private const string ShootingStaffSection = "Staff Tweaks (Shooting)"; private const string ZoomSection = "Zoom"; private static bool ShouldSaveConfig = false; internal static ConfigFileWatcher ConfigFileWatcher; internal static ProjectileConfig BowTweaks; internal static ProjectileConfig BombTweaks; internal static ProjectileConfig XBowTweaks; internal static ProjectileConfig SpearTweaks; internal static ProjectileConfig ThrowingStaffTweaks; internal static ProjectileConfig ShootingStaffTweaks; internal static ConfigEntry<string> ThrowingStavesConfig; internal static ConfigEntry<string> ShootingStavesConfig; internal static readonly HashSet<string> ThrowingStaffNames = new HashSet<string>(); internal static readonly HashSet<string> ShootingStaffNames = new HashSet<string>(); internal static bool ShouldUpdateStaffNames = true; private const string AmmoCountSection = "Ammo Count"; internal static ConfigEntry<bool> EnableBowZoom { get; private set; } internal static ConfigEntry<bool> EnableXBowZoom { get; private set; } internal static ConfigEntry<KeyCode> ZoomKey { get; private set; } internal static ConfigEntry<KeyCode> CancelDrawKey { get; private set; } internal static ConfigEntry<float> StayInZoomTime { get; private set; } internal static ConfigEntry<float> TimeToZoomIn { get; private set; } internal static ConfigEntry<float> ZoomFactor { get; private set; } internal static ConfigEntry<bool> AutoBowZoom { get; private set; } internal bool IsZoomEnabled { get { if (!EnableBowZoom.Value) { return EnableXBowZoom.Value; } return true; } } internal static ConfigEntry<bool> ShowAmmoIcon { get; private set; } internal static ConfigEntry<Vector2> AmmoIconPosition { get; private set; } internal static ConfigEntry<Vector2> AmmoIconSize { get; private set; } internal static ConfigEntry<int> AmmoTextSize { get; private set; } internal static ConfigEntry<TextAlignmentOptions> AmmoTextAlignment { get; private set; } internal static ConfigEntry<Color> AmmoTextColor { get; private set; } internal static ConfigEntry<Vector2> AmmoTextPosition { get; private set; } internal static bool ShouldResetIcon { get; set; } = true; public void Awake() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown Instance = this; Log.Init(((BaseUnityPlugin)this).Logger); ConfigFileExtensions.SetSaveOnConfigSet(((BaseUnityPlugin)this).Config, false); SetUpConfigEntries(); ((BaseUnityPlugin)this).Config.Save(); Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Searica.Valheim.ProjectileTweaks"); Game.isModded = true; ConfigFileWatcher = new ConfigFileWatcher(((BaseUnityPlugin)this).Config, 1000L); SynchronizationManager.OnConfigurationWindowClosed += delegate { UpdatePlugin(); }; SynchronizationManager.OnConfigurationSynchronized += delegate { UpdatePlugin(); }; } public void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetUpConfigEntries() { //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_0563: Unknown result type (might be due to invalid IL or missing references) //IL_05f2: Unknown result type (might be due to invalid IL or missing references) //IL_0626: 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, -0.25f); BombTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Bomb Tweaks", 1f, 1f, -1f, 0f, float.NaN, 0.5f, 0f, -0.25f); XBowTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Crossbow Tweaks", 1f, 1f, -1f, -1f, 1f, 0f, 0f, -0.25f); SpearTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Spear Tweaks", 1f, 1f, -1f, 0f, float.NaN, 0.5f, 0.1f, -0.25f); ThrowingStavesConfig = ConfigFileExtensions.BindConfigInOrder<string>(((BaseUnityPlugin)this).Config, "Staff Tweaks (Throwing)", "Throwing Staves", "StaffFireBall,StaffClusterBombs,StaffGreenRoots", "Comma or semi-colon seperated list of internal game ids for the staffs that use a throwing or lobbing animation when attacking.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ThrowingStaffTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Staff Tweaks (Throwing)", 1f, 1f, float.NaN, 0f, float.NaN, 0.5f, 0f, -0.25f); ThrowingStavesConfig.SettingChanged += UpdateSettings; ThrowingStavesConfig.SettingChanged += UpdateStaffNamesConfig; ShootingStavesConfig = ConfigFileExtensions.BindConfigInOrder<string>(((BaseUnityPlugin)this).Config, "Staff Tweaks (Shooting)", "Shooting Staves", "StaffIceShards,StaffOrbofAhri", "Comma or semi-colon seperated list of internal game ids for the staffs that use a crossbow or shooting like animation when attacking.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ShootingStavesConfig.SettingChanged += UpdateSettings; ShootingStavesConfig.SettingChanged += UpdateStaffNamesConfig; ShootingStaffTweaks = new ProjectileConfig(((BaseUnityPlugin)this).Config, "Staff Tweaks (Shooting)", 1f, 1f, float.NaN, 0f, float.NaN, 0.2f, 0f, -0.25f); UpdateStaffTypeHashSets(forceUpdate: true); EnableBowZoom = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Zoom", "Bow Zoom", true, "Set to true/enabled to allow zooming while using a bow.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); EnableBowZoom.SettingChanged += UpdateSettings; EnableXBowZoom = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Zoom", "Crossbow Zoom", true, "Set to true/enabled to allow zooming while using a crossbow.", true, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); EnableXBowZoom.SettingChanged += UpdateSettings; ZoomKey = ConfigFileExtensions.BindConfigInOrder<KeyCode>(((BaseUnityPlugin)this).Config, "Zoom", "Zoom Key", (KeyCode)324, "Set the key used to zoom in while using a bow or crossbow.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ZoomKey.SettingChanged += UpdateSettings; CancelDrawKey = ConfigFileExtensions.BindConfigInOrder<KeyCode>(((BaseUnityPlugin)this).Config, "Zoom", "Cancel Draw Key", (KeyCode)101, "Set the key used to cancel drawing your bow.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); CancelDrawKey.SettingChanged += UpdateSettings; TimeToZoomIn = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Zoom", "Time to Zoom in", 1f, "Time that it takes to zoom in all the way. '1' is default and recommended.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 2f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); TimeToZoomIn.SettingChanged += UpdateSettings; StayInZoomTime = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "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.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); StayInZoomTime.SettingChanged += UpdateSettings; ZoomFactor = ConfigFileExtensions.BindConfigInOrder<float>(((BaseUnityPlugin)this).Config, "Zoom", "Zoom Factor", 2f, "Set how much too zoom in relative to current camera view.", false, true, true, (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 4f), (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); ZoomFactor.SettingChanged += UpdateSettings; AutoBowZoom = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Zoom", "Auto Bow Zoom", false, "Set to true/enabled to make bows automatically zoom in as they are drawn.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AutoBowZoom.SettingChanged += UpdateSettings; ShowAmmoIcon = ConfigFileExtensions.BindConfigInOrder<bool>(((BaseUnityPlugin)this).Config, "Ammo Count", "Show Ammo Icon", true, "Whether to show ammo count icon in hot bar.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AmmoIconPosition = ConfigFileExtensions.BindConfigInOrder<Vector2>(((BaseUnityPlugin)this).Config, "Ammo Count", "Icon Position", new Vector2(0f, 32f), "Icon Position.", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AmmoIconSize = ConfigFileExtensions.BindConfigInOrder<Vector2>(((BaseUnityPlugin)this).Config, "Ammo Count", "Icon Size", new Vector2(20f, 20f), "Icon Size", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AmmoTextSize = ConfigFileExtensions.BindConfigInOrder<int>(((BaseUnityPlugin)this).Config, "Ammo Count", "Text Size", 16, "Text Size", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AmmoTextAlignment = ConfigFileExtensions.BindConfigInOrder<TextAlignmentOptions>(((BaseUnityPlugin)this).Config, "Ammo Count", "Text Alignment", (TextAlignmentOptions)260, "Text Alignment", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AmmoTextColor = ConfigFileExtensions.BindConfigInOrder<Color>(((BaseUnityPlugin)this).Config, "Ammo Count", "Text Color", new Color(1f, 1f, 1f, 1f), "Text Color", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); AmmoTextPosition = ConfigFileExtensions.BindConfigInOrder<Vector2>(((BaseUnityPlugin)this).Config, "Ammo Count", "Text Positio", new Vector2(-6f, -4f), "Offset of text relative to icon", false, true, true, (AcceptableValueBase)null, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); 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 UpdatePlugin() { UpdateStaffTypeHashSets(); if (ShouldSaveConfig) { ((BaseUnityPlugin)this).Config.Save(); ShouldSaveConfig = false; } } private static void UpdateSettings(object obj, EventArgs e) { ShouldSaveConfig |= !ShouldSaveConfig; } private static void UpdateStaffNamesConfig(object obj, EventArgs e) { ShouldUpdateStaffNames |= !ShouldUpdateStaffNames; } private static void SetUpdateIcon(object obj, EventArgs e) { ShouldResetIcon |= !ShouldResetIcon; } private static void UpdateStaffTypeHashSets(bool forceUpdate = false) { if (ShouldUpdateStaffNames || forceUpdate) { ShootingStaffNames.Clear(); ThrowingStaffNames.Clear(); ShootingStaffNames.UnionWith(ParseStringList(ShootingStavesConfig.Value)); ThrowingStaffNames.UnionWith(ParseStringList(ThrowingStavesConfig.Value)); ShouldUpdateStaffNames = false; } } private static string[] ParseStringList(string stringList) { string text = stringList.Trim(); if (text.Length >= 1) { return text.Split(new char[2] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries); } return Array.Empty<string>(); } } [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_0017: Unknown result type (might be due to invalid IL or missing references) if (ProjectileTweaks.Instance.IsZoomEnabled) { if (attackHold) { blockHold = Input.GetKey(ProjectileTweaks.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_002c: 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.ZoomKey.Value); bool num = (key || ProjectileTweaks.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.TimeToZoomIn.Value, ZoomInTimer); LastZoomFov = Mathf.Lerp(BaseFov, BaseFov / ProjectileTweaks.ZoomFactor.Value, num); GameCamera.instance.m_fov = LastZoomFov; NewZoomFov = LastZoomFov; } public static void ZoomOut() { if (CurrentZoomState != ZoomState.Fixed) { 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.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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Invalid comparison between Unknown and I4 ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (currentWeapon != null) { SkillType skillType = currentWeapon.m_shared.m_skillType; bool num = ProjectileTweaks.EnableBowZoom.Value && (int)skillType == 8; bool flag = ProjectileTweaks.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 const FontStyles FontStyle = (FontStyles)0; private static TMP_FontAsset _CurrentFont; private const string AmmoCountName = "AmmoCount"; private const string AmmoTextName = "AmmoText"; private const string AmmoIconName = "AmmoIcon"; private static TMP_FontAsset CurrentFont { get { if (_CurrentFont == null) { _CurrentFont = GUIManager.Instance.TMP_AveriaSansLibre; } 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) || CurrentFont == null) { 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0117: 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) GameObject val = new GameObject("AmmoCount"); val.SetActive(false); val.transform.SetParent(gameObject.transform); val.AddComponent<RectTransform>().anchoredPosition = Vector2.zero; ammoCount = val.transform; GameObject val2 = new GameObject("AmmoText"); val2.SetActive(false); val2.transform.SetParent(val.transform); TextMeshProUGUI obj = val2.AddComponent<TextMeshProUGUI>(); RectTransform rectTransform = ((TMP_Text)obj).rectTransform; rectTransform.anchoredPosition = ProjectileTweaks.AmmoTextPosition.Value; rectTransform.sizeDelta = new Vector2(90f, 90f); ((TMP_Text)obj).font = CurrentFont; ((TMP_Text)obj).fontSize = ProjectileTweaks.AmmoTextSize.Value; ((TMP_Text)obj).fontStyle = (FontStyles)0; ((TMP_Text)obj).alignment = ProjectileTweaks.AmmoTextAlignment.Value; ((Graphic)obj).color = ProjectileTweaks.AmmoTextColor.Value; val2.SetActive(ProjectileTweaks.ShowAmmoIcon.Value); if (ProjectileTweaks.ShowAmmoIcon.Value) { GameObject val3 = new GameObject("AmmoIcon"); val3.transform.SetParent(val.transform); val3.AddComponent<Image>(); RectTransform component = val3.GetComponent<RectTransform>(); component.anchoredPosition = ProjectileTweaks.AmmoIconPosition.Value; component.sizeDelta = ProjectileTweaks.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("AmmoText")).GetComponent<TextMeshProUGUI>()).text = ammoItemData.m_stack.ToString(); if (ProjectileTweaks.ShowAmmoIcon.Value) { ((Component)go.transform.Find("AmmoIcon")).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] internal static class AttackPatch { private static ProjectileTweaks.ProjectileConfig RefProjectileConfig; 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(typeof(Attack), "Start")] internal static void AttackStartPrefix(Attack __instance) { if (TryGetProjectileConfig(GetPlayerWeapon(__instance), out RefProjectileConfig)) { SetVelocity(__instance, RefProjectileConfig.VelocityMult); SetSpread(__instance, RefProjectileConfig.SpreadMult); if (RefProjectileConfig.LaunchAngle != null) { SetLaunchAngle(__instance, RefProjectileConfig.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(typeof(Attack), "GetProjectileSpawnPoint")] private static void GetProjectileSpawnPointPostfix(Attack __instance, ref Vector3 spawnPoint, ref Vector3 aimDir) { if (TryGetProjectileConfig(GetPlayerWeapon(__instance), out RefProjectileConfig)) { ApplyOffset(ref spawnPoint, ref aimDir, RefProjectileConfig.VerticalOffset.Value, RefProjectileConfig.HorizontalOffset.Value, RefProjectileConfig.DepthOffset.Value); } } private static bool TryGetProjectileConfig(ItemData weapon, out ProjectileTweaks.ProjectileConfig projectileConfig) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Invalid comparison between Unknown and I4 //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Invalid comparison between Unknown and I4 //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Invalid comparison between Unknown and I4 if (weapon == null) { projectileConfig = null; return false; } SkillType skillType = weapon.m_shared.m_skillType; if ((int)skillType == 8) { projectileConfig = ProjectileTweaks.BowTweaks; return true; } if ((int)skillType == 14) { projectileConfig = ProjectileTweaks.XBowTweaks; return true; } if ((int)skillType == 5) { projectileConfig = ProjectileTweaks.SpearTweaks; return true; } if ((int)skillType == 9 || (int)skillType == 10) { if (ProjectileTweaks.ShootingStaffNames.Contains(((Object)weapon.m_dropPrefab).name)) { projectileConfig = ProjectileTweaks.ShootingStaffTweaks; return true; } if (ProjectileTweaks.ThrowingStaffNames.Contains(((Object)weapon.m_dropPrefab).name)) { projectileConfig = ProjectileTweaks.ThrowingStaffTweaks; return true; } } else if (IsBomb(weapon)) { projectileConfig = ProjectileTweaks.BombTweaks; return true; } projectileConfig = null; return false; } private static void ApplyOffset(ref Vector3 spawnPoint, ref Vector3 aimDir, float vertOffset, float horzOffset, float depthOffset) { //IL_0002: 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_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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) Vector3 val = spawnPoint; Vector3 val2 = new Vector3(aimDir.x, 0f, aimDir.z); spawnPoint = val + depthOffset * ((Vector3)(ref val2)).normalized; Vector3 val3 = spawnPoint; val2 = new Vector3(aimDir.z, 0f, 0f - aimDir.x); spawnPoint = val3 + horzOffset * ((Vector3)(ref val2)).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.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.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!"); } } } }