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 AimAssist v0.6.9
plugins/ValheimAimAssist.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ValheimAimAssist")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.6.9.0")] [assembly: AssemblyInformationalVersion("0.6.9+d86d949bc5b7cb112069757ffe7c03c38eac7007")] [assembly: AssemblyProduct("ValheimAimAssist")] [assembly: AssemblyTitle("ValheimAimAssist")] [assembly: InternalsVisibleTo("AimCheck")] [assembly: AssemblyVersion("0.6.9.0")] [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 ValheimAimAssist { internal static class AimAssist { private static readonly AimAssistCore Core = new AimAssistCore(); private static Func<PlayerController, bool, bool> _takeInput; private static Func<PlayerController, bool> _inInventoryEtc; private static FieldRef<GameCamera, Vector3> _cameraPlayerPos; private static FieldRef<GameCamera, Vector3> _cameraBaseOffset; private static bool _inLookUpdate; private static bool _takesInput; private static int _lastStepFrame = -10; private static bool _errorLogged; private static bool _toldEngaged; private static bool _toldMouse; private static float _nextDebugLog; internal static bool Init(List<string> report) { _takeInput = MakeDelegate<Func<PlayerController, bool, bool>>("TakeInput", new Type[1] { typeof(bool) }, report); _inInventoryEtc = MakeDelegate<Func<PlayerController, bool>>("InInventoryEtc", Type.EmptyTypes, report); try { _cameraPlayerPos = AccessTools.FieldRefAccess<GameCamera, Vector3>("m_playerPos"); _cameraBaseOffset = AccessTools.FieldRefAccess<GameCamera, Vector3>("m_currentBaseOffset"); } catch (Exception ex) { _cameraPlayerPos = null; _cameraBaseOffset = null; report.Add("GameCamera.m_playerPos / m_currentBaseOffset not found (" + ex.Message + "): own movement is measured from the player's eye."); } if (_takeInput != null) { return _inInventoryEtc != null; } return false; } private static Vector3 CameraPivot(Player player, GameCamera camera) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (_cameraPlayerPos == null || (Object)(object)camera == (Object)null) { return ((Character)player).m_eye.position; } return (((Object)(object)((Character)player).GetStandingOnShip() != (Object)null || ((Character)player).IsAttached()) ? ((Component)player).transform.position : _cameraPlayerPos.Invoke(camera)) + _cameraBaseOffset.Invoke(camera); } private static T MakeDelegate<T>(string name, Type[] parameters, List<string> report) where T : Delegate { MethodInfo methodInfo = AccessTools.Method(typeof(PlayerController), name, parameters, (Type[])null); if (methodInfo == null) { report.Add("PlayerController." + name + " not found."); return null; } try { return AccessTools.MethodDelegate<T>(methodInfo, (object)null, true); } catch (Exception ex) { report.Add("PlayerController." + name + " has an unexpected signature: " + ex.Message); return null; } } internal static void BeginLookUpdate(PlayerController controller) { _inLookUpdate = true; try { _takesInput = _takeInput(controller, arg2: true) && !_inInventoryEtc(controller) && !Hud.InRadial(); } catch (Exception e) { _takesInput = false; LogOnce(e); } } internal static void EndLookUpdate() { _inLookUpdate = false; } internal static void ApplyToLook(Player player, ref Vector2 mouseLook) { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0253: 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_0257: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_037a: Unknown result type (might be due to invalid IL or missing references) if (!_inLookUpdate || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return; } try { bool flag = ZInput.IsExclusiveGamepadActive(); bool flag2 = ModSettings.Enabled.Value && Courtesy.AllowsAssist; if (!flag2 || !_takesInput || !flag || !CanAim(player)) { if (!flag && !_toldMouse && flag2 && _takesInput && CanAim(player)) { TellIfMouseHidesTarget(player); } Core.Reset(); _lastStepFrame = -10; return; } int frameCount = Time.frameCount; if (frameCount != _lastStepFrame + 1) { Core.ForgetReference(); } _lastStepFrame = frameCount; GameCamera instance = GameCamera.instance; Vector3 val = CameraPivot(player, instance); AimInput input = new AimInput { DeltaTime = Time.deltaTime, Look = mouseLook, Stick = AimMath.StickToLook(ZInput.GetJoyRightStickX(), ZInput.GetJoyRightStickY(), PlayerController.m_invertCameraX, PlayerController.m_invertCameraY), Eye = val }; TargetInfo target = (ModeAllows(player) ? Targeting.Get(player) : default(TargetInfo)); if ((Object)(object)target.Target != (Object)null) { Vector3 val2 = (((Object)(object)instance != (Object)null) ? ((Component)instance).transform.position : ((Character)player).m_eye.position); Vector3 forward = ((Character)player).m_eye.forward; Vector3 nearest; float gap = AimMath.CapsuleGap(val2, forward, target.AxisA, target.AxisB, target.Radius, Targeting.RayLength, out nearest); input.HasTarget = true; input.TargetId = ((Object)target.Target).GetInstanceID(); input.Gap = gap; float num = Vector3.Distance(val2, nearest); input.HalfWidth = ((num > target.Radius) ? (Mathf.Asin(target.Radius / num) * 57.29578f) : 90f); input.Strength = AimMath.StrengthFromGap(gap, ModSettings.AngularRadius.Value); input.TargetPoint = target.Center; input.Distance = Vector3.Distance(val, target.Center); float value = ModSettings.AimHeight.Value; if (value > 0f) { Vector3 a = target.AxisA; Vector3 b = target.AxisB; AimMath.RaiseAxis(ref a, ref b, target.Radius, value); AimMath.CapsuleGap(val2, forward, a, b, target.Radius, Targeting.RayLength, out nearest); } input.TargetOffset = AimMath.LookDelta(forward, nearest - AimMath.TurnOrigin(val2, forward, val)); } ServerTuning? imposed = Courtesy.Imposed; AimTuning tuning = new AimTuning { Slowdown = (imposed.HasValue ? imposed.Value.SlowdownFactor : ModSettings.SlowdownFactor.Value), Tracking = (imposed.HasValue ? imposed.Value.TrackingStrength : ModSettings.TrackingStrength.Value), Magnetism = ModSettings.MagnetismRateOf(imposed.HasValue ? imposed.Value.Magnetism : ModSettings.Magnetism.Value), Smoothing = ModSettings.SmoothingTime.Value, OwnMovement = ModSettings.TrackOwnMovement.Value, MinDistance = ModSettings.MinDistance.Value, MaxSpeed = ModSettings.MaxAssistSpeed.Value }; mouseLook = Core.Step(in input, in tuning); Report(player, target, in input, mouseLook); } catch (Exception e) { Core.Reset(); LogOnce(e); } } private static bool CanAim(Player player) { if (!((Character)player).IsDead() && !((Character)player).InPlaceMode() && !((Character)player).IsAttached() && !((Character)player).InCutscene() && !((Character)player).InIntro()) { return !PlayerCustomizaton.IsBarberGuiVisible(); } return false; } internal static bool ModeAllows(Player player) { ItemData currentWeapon = ((Humanoid)player).GetCurrentWeapon(); if (!IsRanged(currentWeapon)) { return false; } if (ModSettings.Mode.Value == AssistMode.RangedEquipped) { return true; } Attack attack = currentWeapon.m_shared.m_attack; if (attack.m_bowDraw) { return ((Character)player).IsDrawingBow(); } if (attack.m_requiresReload) { return ((Humanoid)player).IsWeaponLoaded(); } return true; } internal static bool IsRanged(ItemData weapon) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (weapon == null || weapon.m_shared == null) { return false; } Attack attack = weapon.m_shared.m_attack; if (attack != null) { return IsRanged(weapon.m_shared.m_skillType, attack.m_attackType, attack.m_bowDraw, attack.m_requiresReload); } return false; } internal static bool IsRanged(SkillType skill, AttackType attackType, bool bowDraw, bool requiresReload) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Invalid comparison between Unknown and I4 //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 if (skill - 8 > 2 && (int)skill != 14) { if ((int)skill == 104) { return false; } if (!(bowDraw || requiresReload)) { return (int)attackType == 2; } return true; } return true; } private static void Report(Player player, TargetInfo target, in AimInput input, Vector2 output) { //IL_0015: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_017a: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target.Target == (Object)null)) { float num = Vector3.Distance(((Character)player).m_eye.position, target.Center); if (!_toldEngaged && target.UnderCrosshair) { _toldEngaged = true; Plugin.Log.LogInfo((object)($"Aim assist engaged: {NameOf(target.Target)} under the crosshair at {num:F0} m, " + $"gamepad input, mode {ModSettings.Mode.Value}. (Logged once per session.)")); } if (ModSettings.DebugLog.Value && !(Time.time < _nextDebugLog)) { _nextDebugLog = Time.time + 0.5f; float num2 = Mathf.Max(input.DeltaTime, 0.0001f); AimBreakdown last = Core.Last; Plugin.Log.LogInfo((object)string.Join(" | ", FormattableString.Invariant($"[debug] {NameOf(target.Target)} {num:F0} m, gap {input.Gap:F1}°, to axis {Show(input.TargetOffset)}°, strength {Core.Strength:F2}"), "stick " + Show(input.Stick) + " → " + Show(input.Look / num2) + "°/s, target moves " + Show(Core.Velocity) + "°/s", FormattableString.Invariant($"followed {Show(last.Follow)}, slowdown ×{last.Factor:F2}, tracking {Show(last.Tracking)}, magnet {Show(last.Pull / num2)}"), "camera turns " + Show(output / num2) + "°/s")); } } } private static void TellIfMouseHidesTarget(Player player) { if (ModeAllows(player) && Targeting.Get(player).UnderCrosshair) { _toldMouse = true; Plugin.Log.LogInfo((object)"A target is under the crosshair while aiming, but the game reads mouse/keyboard input: the aim assist only works with a gamepad, so it stays idle. (Logged once per session.)"); } } private static string NameOf(Character character) { string name = ((Object)((Component)character).gameObject).name; int num = name.IndexOf("(Clone)", StringComparison.Ordinal); if (num <= 0) { return name; } return name.Substring(0, num); } private static string Show(Vector2 v) { //IL_000d: 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) return FormattableString.Invariant($"({v.x:F1}, {v.y:F1})"); } private static void LogOnce(Exception e) { if (!_errorLogged) { _errorLogged = true; Plugin.Log.LogError((object)$"Aim assist error, the frame is left untouched (logged once): {e}"); } } } internal struct AimInput { internal float DeltaTime; internal Vector2 Look; internal Vector2 Stick; internal bool HasTarget; internal int TargetId; internal float Strength; internal float Gap; internal float HalfWidth; internal float Distance; internal Vector3 TargetPoint; internal Vector3 Eye; internal Vector2 TargetOffset; } internal struct AimTuning { internal float Slowdown; internal float Tracking; internal float Magnetism; internal float Smoothing; internal bool OwnMovement; internal float MinDistance; internal float MaxSpeed; } internal sealed class AimAssistCore { internal const float OppositionFull = 0.01f; internal const float EscapeStart = 0.6f; internal const float EscapeFull = 0.9f; internal const float MagnetStickFull = 0.02f; internal const float RestPullShare = 0.5f; internal const float RestPullFade = 0.3f; internal const float RestPullSideFade = 1.5f; internal const float RestPullSideWidths = 2f; internal const float RestPullMaxSpeed = 10f; internal const float AutoMaxSpeed = 55f; internal const float PullMaxSpeed = 45f; internal const float VelocitySmoothing = 0.05f; internal const float CatchUpTime = 0.08f; internal const float MaxStepDegrees = 10f; private float _strength; private int _trackedId; private bool _haveReference; private Vector3 _lastTarget; private Vector3 _lastEye; private Vector2 _velocity; private Vector2 _step; private bool _haveStep; private Vector2 _owed; internal float Strength => _strength; internal Vector2 Velocity => _velocity; internal AimBreakdown Last { get; private set; } internal void Reset() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: 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_001c: Unknown result type (might be due to invalid IL or missing references) _strength = 0f; _velocity = Vector2.zero; _owed = Vector2.zero; _haveStep = false; _haveReference = false; _trackedId = 0; Last = default(AimBreakdown); } internal void ForgetReference() { _haveReference = false; } internal Vector2 Step(in AimInput input, in AimTuning tuning) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02d1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0415: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_041f: Unknown result type (might be due to invalid IL or missing references) //IL_0424: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021b: 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_0238: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_0381: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_0493: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Unknown result type (might be due to invalid IL or missing references) //IL_049c: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Unknown result type (might be due to invalid IL or missing references) //IL_04a5: Unknown result type (might be due to invalid IL or missing references) //IL_04a7: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Unknown result type (might be due to invalid IL or missing references) //IL_04b9: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04cd: Unknown result type (might be due to invalid IL or missing references) //IL_045e: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0467: Unknown result type (might be due to invalid IL or missing references) //IL_0469: Unknown result type (might be due to invalid IL or missing references) //IL_046d: Unknown result type (might be due to invalid IL or missing references) //IL_0472: Unknown result type (might be due to invalid IL or missing references) //IL_0474: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Unknown result type (might be due to invalid IL or missing references) //IL_047d: Unknown result type (might be due to invalid IL or missing references) //IL_03e5: Unknown result type (might be due to invalid IL or missing references) //IL_0407: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03ca: Unknown result type (might be due to invalid IL or missing references) //IL_03cf: Unknown result type (might be due to invalid IL or missing references) //IL_04f3: Unknown result type (might be due to invalid IL or missing references) //IL_050e: Unknown result type (might be due to invalid IL or missing references) float deltaTime = input.DeltaTime; if (deltaTime <= 0f) { return input.Look; } float num = ((!input.HasTarget) ? 0f : ((tuning.MinDistance <= 0f) ? 1f : AimMath.SmoothStep(tuning.MinDistance, 2f * tuning.MinDistance, input.Distance))); float num2 = (input.HasTarget ? (Mathf.Clamp01(input.Strength) * num) : 0f); _strength = AimMath.Approach(_strength, num2, deltaTime, tuning.Smoothing); UpdateVelocity(in input, in tuning, deltaTime); Vector2 val = input.Look / deltaTime; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(FollowPart(val.x, _velocity.x), FollowPart(val.y, _velocity.y)); Vector2 val3 = val - val2; float num3 = _strength; Vector2 val4; if (num3 > 0f && ((Vector2)(ref val)).sqrMagnitude > 0f) { val4 = input.TargetOffset; if (((Vector2)(ref val4)).sqrMagnitude > 1E-06f) { Vector2 normalized = ((Vector2)(ref val)).normalized; val4 = input.TargetOffset; float num4 = Mathf.Clamp01(0f - Vector2.Dot(normalized, ((Vector2)(ref val4)).normalized)); val4 = input.Stick; float num5 = AimMath.SmoothStep(0.6f, 0.9f, ((Vector2)(ref val4)).magnitude); num3 *= 1f - num4 * num5; } } float num6 = Mathf.Lerp(1f, Mathf.Clamp01(tuning.Slowdown), num3); Vector2 val5 = val2 + val3 * num6; float num7 = Mathf.Clamp01(tuning.Tracking); Vector2 val6 = (_velocity - val2) * (num7 * _strength); if (input.HasTarget) { Vector2 val7 = (_haveStep ? _step : (_velocity * deltaTime)); _owed += (val7 - val2 * deltaTime) * (num7 * num2) - val6 * deltaTime; Vector2 val8 = _owed * (1f - Mathf.Exp((0f - deltaTime) / 0.08f)); _owed -= val8; val6 += val8 / deltaTime; } float num8 = Yield(input.Stick.x, val6.x); float num9 = Yield(input.Stick.y, val6.y); val6.x *= num8; val6.y *= num9; _owed.x *= num8; _owed.y *= num9; Vector2 val9 = Vector2.zero; if (tuning.Magnetism > 0f && input.HasTarget && _strength > 0f) { val4 = input.Stick; float num10 = AimMath.SmoothStep(0f, 0.02f, ((Vector2)(ref val4)).magnitude); float num11 = 1f - AimMath.SmoothStep(0f, RestPullReach(input.TargetOffset, input.HalfWidth), input.Gap); float num12 = num10 + (1f - num10) * 0.5f * num11; val9 = input.TargetOffset * ((1f - Mathf.Exp((0f - tuning.Magnetism) * deltaTime)) * num12 * _strength); float num13 = Mathf.Lerp(Mathf.Min(10f + ((Vector2)(ref _velocity)).magnitude, 45f), 45f, num10) * deltaTime; if (((Vector2)(ref val9)).sqrMagnitude > num13 * num13) { val9 = ((Vector2)(ref val9)).normalized * num13; } val9.x *= Yield(input.Stick.x, val9.x); val9.y *= Yield(input.Stick.y, val9.y); } Vector2 val10 = val6 * deltaTime + val9; float num14 = ((tuning.MaxSpeed > 0f) ? tuning.MaxSpeed : 55f) * deltaTime; if (((Vector2)(ref val10)).sqrMagnitude > num14 * num14) { float num15 = num14 / ((Vector2)(ref val10)).magnitude; val10 *= num15; val6 *= num15; val9 *= num15; } Last = new AimBreakdown { Factor = num6, Follow = val2, Tracking = val6, Pull = val9 }; Vector2 val11 = val5 * deltaTime + val10; if (input.Stick.x * val11.x < 0f) { val11.x = 0f; } if (input.Stick.y * val11.y < 0f) { val11.y = 0f; } return val11; } private static float FollowPart(float stick, float target) { if (stick * target <= 0f) { return 0f; } return Mathf.Sign(stick) * Mathf.Min(Mathf.Abs(stick), Mathf.Abs(target)); } private void UpdateVelocity(in AimInput input, in AimTuning tuning, float dt) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: 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_0061: 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_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) _haveStep = false; if (!input.HasTarget) { _haveReference = false; _velocity = AimMath.Approach(_velocity, Vector2.zero, dt, tuning.Smoothing); _owed = Vector2.zero; return; } if (input.TargetId != _trackedId) { _trackedId = input.TargetId; _haveReference = false; _velocity = Vector2.zero; _owed = Vector2.zero; } if (_haveReference) { Vector2 val = AimMath.LookDelta(_lastTarget - (tuning.OwnMovement ? _lastEye : input.Eye), input.TargetPoint - input.Eye); if (((Vector2)(ref val)).magnitude <= 10f) { _velocity = AimMath.Approach(_velocity, val / dt, dt, 0.05f); _step = val; _haveStep = true; } else { _velocity = Vector2.zero; _owed = Vector2.zero; } } _lastTarget = input.TargetPoint; _lastEye = input.Eye; _haveReference = true; } private static float RestPullReach(Vector2 offset, float halfWidth) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) float magnitude = ((Vector2)(ref offset)).magnitude; float num = ((magnitude > 1E-06f) ? AimMath.SmoothStep(0.3f, 0.8f, (0f - offset.y) / magnitude) : 0f); return Mathf.Lerp(Mathf.Max(1.5f, 2f * halfWidth), 0.3f, num); } private static float Yield(float stick, float assist) { if (stick * assist >= 0f) { return 1f; } return 1f - Mathf.Clamp01(Mathf.Abs(stick) / 0.01f); } } internal struct AimBreakdown { internal float Factor; internal Vector2 Follow; internal Vector2 Tracking; internal Vector2 Pull; } internal static class AimMath { internal static Vector2 LookAngles(Vector3 direction) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0021: 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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) float num = Mathf.Sqrt(direction.x * direction.x + direction.z * direction.z); return new Vector2(Mathf.Atan2(direction.x, direction.z) * 57.29578f, Mathf.Atan2(direction.y, num) * 57.29578f); } internal static Vector2 LookDelta(Vector3 from, Vector3 to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_0036: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Vector2 val = LookAngles(from); Vector2 val2 = LookAngles(to); return new Vector2((IsNearlyVertical(from) || IsNearlyVertical(to)) ? 0f : Mathf.DeltaAngle(val.x, val2.x), val2.y - val.y); } private static bool IsNearlyVertical(Vector3 d) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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) return d.x * d.x + d.z * d.z < 0.0025f * ((Vector3)(ref d)).sqrMagnitude; } internal static Vector3 TurnOrigin(Vector3 camera, Vector3 forward, Vector3 pivot) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) return camera + forward * Mathf.Max(0f, Vector3.Dot(pivot - camera, forward)); } internal static void RaiseAxis(ref Vector3 a, ref Vector3 b, float radius, float lift) { //IL_0000: 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_001c: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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) Vector3 val = Vector3.up * Mathf.Clamp(lift, 0f, 0.75f * radius); a += val; b += val; } internal static Vector2 StickToLook(float joyRightStickX, float joyRightStickY, bool invertX, bool invertY) { //IL_000f: 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_0020: Unknown result type (might be due to invalid IL or missing references) Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(joyRightStickX, 0f - joyRightStickY); if (invertX) { val.x = 0f - val.x; } if (invertY) { val.y = 0f - val.y; } return val; } internal static float CapsuleGap(Vector3 origin, Vector3 forward, Vector3 a, Vector3 b, float radius, float rayLength, out Vector3 nearest) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: 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_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_004b: 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) ClosestPoints(origin, origin + forward * rayLength, a, b, out var _, out nearest); Vector3 val = nearest - origin; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude <= radius) { return -90f; } float num = Mathf.Asin(radius / magnitude) * 57.29578f; return Vector3.Angle(forward, val) - num; } private static void ClosestPoints(Vector3 p1, Vector3 q1, Vector3 p2, Vector3 q2, out Vector3 c1, out Vector3 c2) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0011: Unknown result type (might be due to invalid IL or missing references) //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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) Vector3 val = q1 - p1; Vector3 val2 = q2 - p2; Vector3 val3 = p1 - p2; float num = Vector3.Dot(val, val); float num2 = Vector3.Dot(val2, val2); float num3 = Vector3.Dot(val2, val3); float num4; float num5; if (num <= 1E-06f && num2 <= 1E-06f) { num4 = 0f; num5 = 0f; } else if (num <= 1E-06f) { num4 = 0f; num5 = Mathf.Clamp01(num3 / num2); } else { float num6 = Vector3.Dot(val, val3); if (num2 <= 1E-06f) { num5 = 0f; num4 = Mathf.Clamp01((0f - num6) / num); } else { float num7 = Vector3.Dot(val, val2); float num8 = num * num2 - num7 * num7; num4 = ((num8 > 1E-06f) ? Mathf.Clamp01((num7 * num3 - num6 * num2) / num8) : 0f); num5 = (num7 * num4 + num3) / num2; if (num5 < 0f) { num5 = 0f; num4 = Mathf.Clamp01((0f - num6) / num); } else if (num5 > 1f) { num5 = 1f; num4 = Mathf.Clamp01((num7 - num6) / num); } } } c1 = p1 + val * num4; c2 = p2 + val2 * num5; } internal static float StrengthFromGap(float gap, float zone) { if (gap <= 0f) { return 1f; } if (zone <= 0f || gap >= zone) { return 0f; } return 1f - SmoothStep(0f, zone, gap); } internal static float SmoothStep(float edge0, float edge1, float x) { float num = Mathf.Clamp01((x - edge0) / (edge1 - edge0)); return num * num * (3f - 2f * num); } internal static float Approach(float current, float target, float deltaTime, float tau) { if (tau <= 0f) { return target; } return target + (current - target) * Mathf.Exp((0f - deltaTime) / tau); } internal static Vector2 Approach(Vector2 current, Vector2 target, float deltaTime, float tau) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (tau <= 0f) { return target; } return target + (current - target) * Mathf.Exp((0f - deltaTime) / tau); } } internal static class Courtesy { private sealed class GameChannel : ICourtesyChannel { public void Say(string text, IReadOnlyCollection<long> to) { if ((Object)(object)Player.m_localPlayer == (Object)null) { Pending.Add(new KeyValuePair<string, IReadOnlyCollection<long>>(text, to)); } else { SendChat(text, to); } } public void Show(LocalText text, bool center) { Notices.Add(new KeyValuePair<LocalText, bool>(text, center)); } public void Log(string text) { Plugin.Log.LogInfo((object)text); } } private const float TickPeriod = 0.5f; private static readonly CourtesyCore Core = new CourtesyCore(new GameChannel()); private static readonly List<PlayerSeen> Others = new List<PlayerSeen>(); private static readonly HashSet<string> Connected = new HashSet<string>(); private static readonly List<KeyValuePair<string, IReadOnlyCollection<long>>> Pending = new List<KeyValuePair<string, IReadOnlyCollection<long>>>(); private const float NoticeDelay = 2f; private static readonly List<KeyValuePair<LocalText, bool>> Notices = new List<KeyValuePair<LocalText, bool>>(); private static float _screenClearSince = -1f; private const float CenterLife = 4f; private static readonly FieldInfo CenterTextField = AccessTools.Field(typeof(MessageHud), "m_messageCenterText"); private static string _centerShown; private static float _centerShownAt; private static ParameterInfo[] _sayParameters; private static ParameterInfo[] _shoutParameters; private static int _sayHash; private static int _shoutHash; private static ZNet _net; private static ZRoutedRpc _registered; private static bool _begun; private static float _nextTick; private static bool _errorLogged; internal static bool AllowsAssist => Core.AllowsAssist; internal static LocalText BlockReason => Core.BlockReason; internal static ServerTuning? Imposed { get { if (Core.Rules != CourtesyRules.Server) { return null; } return Core.ServerTuning; } } internal static bool Init(List<string> report) { _sayParameters = ChatParameters(typeof(Talker), "RPC_Say", report); _shoutParameters = ChatParameters(typeof(Chat), "RPC_ChatMessage", report); _sayHash = StringExtensionMethods.GetStableHashCode("Say"); _shoutHash = StringExtensionMethods.GetStableHashCode("ChatMessage"); if (_sayParameters != null) { return _shoutParameters != null; } return false; } internal static void SetChatReadable(bool readable) { Core.ChatReadable = readable; } private static ParameterInfo[] ChatParameters(Type type, string name, List<string> report) { ParameterInfo[] array = AccessTools.Method(type, name, (Type[])null, (Type[])null)?.GetParameters(); if (array == null || array.Length == 0 || array[0].ParameterType != typeof(long) || !array.Any((ParameterInfo p) => p.ParameterType == typeof(UserInfo)) || !array.Any((ParameterInfo p) => p.ParameterType == typeof(string))) { report.Add(type.Name + "." + name + "(long sender, ..., UserInfo, string) not found: chat commands cannot be read."); return null; } return array; } internal unsafe static void Poll() { //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) try { ZNet val = ZNet.instance; if ((Object)(object)val == (Object)null) { val = null; } if (val != _net) { _net = val; _begun = false; Pending.Clear(); Notices.Clear(); _centerShown = null; Core.Reset(); } ZRoutedRpc instance = ZRoutedRpc.instance; if ((Object)(object)val == (Object)null || instance == null) { return; } if (instance != _registered) { _registered = instance; instance.Register<ZPackage>("moochi.AimAssist.Hello", (Action<long, ZPackage>)OnHello); instance.Register<ZPackage>("moochi.AimAssist.Rules", (Action<long, ZPackage>)OnRules); } float unscaledTime = Time.unscaledTime; if (!_begun) { if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } _begun = true; Core.Begin(unscaledTime, ZDOMan.GetSessionID(), val.IsServer()); instance.InvokeRoutedRPC(0L, "moochi.AimAssist.Hello", new object[1] { Protocol.WriteHello(wantsReply: true) }); } ShowNotices(unscaledTime); if ((Object)(object)Player.m_localPlayer == (Object)null || unscaledTime < _nextTick) { return; } _nextTick = unscaledTime + 0.5f; foreach (KeyValuePair<string, IReadOnlyCollection<long>> item2 in Pending) { SendChat(item2.Key, item2.Value); } Pending.Clear(); Others.Clear(); Connected.Clear(); long sessionID = ZDOMan.GetSessionID(); foreach (PlayerInfo player in val.GetPlayerList()) { HashSet<string> connected = Connected; PlatformUserID id = player.m_userInfo.m_id; connected.Add(((object)(*(PlatformUserID*)(&id))/*cast due to .constrained prefix*/).ToString()); ZDOID characterID = player.m_characterID; if (!((ZDOID)(ref characterID)).IsNone()) { characterID = player.m_characterID; if (((ZDOID)(ref characterID)).UserID != sessionID) { List<PlayerSeen> others = Others; PlayerSeen item = default(PlayerSeen); characterID = player.m_characterID; item.Peer = ((ZDOID)(ref characterID)).UserID; item.Name = player.m_name; others.Add(item); } } } Core.Tick(unscaledTime, ModSettings.Enabled.Value, Others, Connected); } catch (Exception e) { LogOnce(e); } } internal static void OnRoutedRpc(RoutedRPCData data) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown int methodHash = data.m_methodHash; ParameterInfo[] array = ((methodHash == _sayHash) ? _sayParameters : ((methodHash == _shoutHash) ? _shoutParameters : null)); if (array == null) { return; } try { ZPackage payload = new ZPackage(data.m_parameters.GetArray()); if (Protocol.TryReadChat(array, data.m_senderPeerID, payload, out var name, out var account, out var text)) { Core.OnChat(Time.unscaledTime, data.m_senderPeerID, name, account, text); } } catch (Exception e) { LogOnce(e); } } private static void ShowNotices(float now) { Hud instance = Hud.instance; if (!((Object)(object)Player.m_localPlayer != (Object)null) || !((Object)(object)instance != (Object)null) || !((Object)(object)instance.m_loadingScreen != (Object)null) || ((Component)instance.m_loadingScreen).gameObject.activeSelf) { _screenClearSince = -1f; return; } if (_screenClearSince < 0f) { _screenClearSince = now; } WatchCenter(now); if (Notices.Count == 0 || now - _screenClearSince < 2f || (Object)(object)MessageHud.instance == (Object)null) { return; } if (!ModSettings.ShowMessages.Value) { Notices.Clear(); return; } foreach (KeyValuePair<LocalText, bool> notice in Notices) { string text = Lang.Pick(notice.Key); MessageHud.instance.ShowMessage((MessageType)((!notice.Value) ? 1 : 2), text, 0, (Sprite)null, false, true); Plugin.Log.LogInfo((object)("Shown on screen" + (notice.Value ? " (centre)" : "") + ": \"" + text + "\"" + (Hud.IsUserHidden() ? ", but the HUD is hidden (Ctrl+F3)" : "") + ".")); if (notice.Value) { _centerShown = CenterText(); _centerShownAt = now; } } Notices.Clear(); } private static void WatchCenter(float now) { if (_centerShown != null) { string text = CenterText(); if (now - _centerShownAt > 4f || text == null) { _centerShown = null; } else if (text != _centerShown) { Plugin.Log.LogInfo((object)$"Replaced in the centre of the screen after {now - _centerShownAt:0.0} s by \"{text}\"."); _centerShown = null; } } } private static string CenterText() { object obj = (((Object)(object)MessageHud.instance != (Object)null && CenterTextField != null) ? CenterTextField.GetValue(MessageHud.instance) : null); if (obj == null) { return null; } return Traverse.Create(obj).Property<string>("text", (object[])null).Value; } private static void OnHello(long sender, ZPackage pkg) { try { if (sender != ZDOMan.GetSessionID()) { Protocol.ReadHello(pkg, out var modVersion, out var wantsReply); if (!Core.IsModPlayer(sender)) { Plugin.Log.LogInfo((object)(NameOf(sender) + " has AimAssist " + modVersion + ": their _aimassiston only takes back their own _aimassistoff.")); } Core.OnModPlayer(sender); if (wantsReply && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.InvokeRoutedRPC(sender, "moochi.AimAssist.Hello", new object[1] { Protocol.WriteHello(wantsReply: false) }); } } } catch (Exception e) { LogOnce(e); } } private static void OnRules(long sender, ZPackage pkg) { try { ZNetPeer val = (((Object)(object)ZNet.instance != (Object)null) ? ZNet.instance.GetServerPeer() : null); if (val != null && val.m_uid == sender) { Core.OnServerRules(Protocol.ReadRules(pkg)); } } catch (Exception e) { LogOnce(e); } } private static string NameOf(long peer) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_002b: 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_003a: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance != (Object)null) { foreach (PlayerInfo player in ZNet.instance.GetPlayerList()) { ZDOID characterID = player.m_characterID; if (!((ZDOID)(ref characterID)).IsNone()) { characterID = player.m_characterID; if (((ZDOID)(ref characterID)).UserID == peer) { return player.m_name; } } } ZNetPeer peer2 = ZNet.instance.GetPeer(peer); if (peer2 != null && !string.IsNullOrEmpty(peer2.m_playerName)) { return peer2.m_playerName; } } return $"Player {peer}"; } private static void SendChat(string text, IReadOnlyCollection<long> to) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)ZNet.instance == (Object)null) { return; } ZDOID localPlayerCharacterID = ZNet.instance.LocalPlayerCharacterID; long self = ((ZDOID)(ref localPlayerCharacterID)).UserID; long me = ZDOMan.GetSessionID(); Chat.CheckPermissionsAndSendChatMessageRPCsAsync((SendChatMessageRPCHandler)delegate(long user, bool filterText) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; ZRoutedRpc instance = ZRoutedRpc.instance; if ((Object)(object)localPlayer == (Object)null || instance == null) { return; } UserInfo val = default(UserInfo); string text2 = default(string); Chat.GetChatMessageData(text, filterText, ref val, ref text2); IEnumerable<long> enumerable3; if (user == 0L) { IEnumerable<long> enumerable; if (to != null) { enumerable = to.Concat(new long[1] { me }); } else { IEnumerable<long> enumerable2 = new long[1] { user }; enumerable = enumerable2; } enumerable3 = enumerable; } else { enumerable3 = ((to != null && user != self && !to.Contains(user)) ? new long[0] : new long[1] { user }); } foreach (long item in enumerable3) { instance.InvokeRoutedRPC(item, "ChatMessage", new object[4] { ((Character)localPlayer).GetHeadPoint(), 1, val, text2 }); } }); } private static void LogOnce(Exception e) { if (!_errorLogged) { _errorLogged = true; Plugin.Log.LogError((object)$"Chat announcement error (logged once): {e}"); } } } internal struct ServerTuning { internal bool Allowed; internal float SlowdownFactor; internal float TrackingStrength; internal float Magnetism; public override string ToString() { if (!Allowed) { return "not allowed"; } return FormattableString.Invariant($"allowed, SlowdownFactor {SlowdownFactor:0.##}, TrackingStrength {TrackingStrength:0.##}, Magnetism {Magnetism:0.##}"); } } internal struct PlayerSeen { internal long Peer; internal string Name; } internal sealed class LocalText { internal readonly Msg Message; internal readonly object[] Args; internal LocalText(Msg message, params object[] args) { Message = message; Args = args; } internal string In(string language) { return Texts.Get(language, Message, Args); } } internal interface ICourtesyChannel { void Say(string text, IReadOnlyCollection<long> to); void Show(LocalText text, bool center); void Log(string text); } internal enum CourtesyRules { Waiting, Chat, Server } internal sealed class CourtesyCore { private sealed class PendingCommand { internal long Sender; internal string Name; internal string Account; internal string Text; } internal const float AnnounceDelay = 15f; internal const float NewcomerDelay = 10f; internal const float ListenWindow = 600f; internal const float ServerTimeout = 10f; internal const float LeaveGrace = 3f; internal const string OffCommand = "_aimassistoff"; internal const string OnCommand = "_aimassiston"; internal const string ChatAnnouncement = "* I use AimAssist, monsters only. Disable it within 10 min: _aimassistoff"; internal const string ServerAnnouncement = "* I use AimAssist, monsters only, with this server's settings."; internal const string OffConfirmation = "* AimAssist off ({0}). Undo: _aimassiston"; internal const string OnConfirmation = "* AimAssist back on ({0})."; internal const string LeftConfirmation = "* AimAssist back on ({0} left)."; private readonly ICourtesyChannel _channel; private readonly HashSet<long> _modPlayers = new HashSet<long>(); private readonly Dictionary<long, float> _firstSeen = new Dictionary<long, float>(); private readonly HashSet<long> _told = new HashSet<long>(); private bool _started; private long _self; private long _vetoPeer; private string _vetoAccount; private float _vetoMissingSince = float.NaN; private PendingCommand _pending; private float _start; private float _serverDeadline; private float _listenUntil = float.NegativeInfinity; private int _othersPresent; internal CourtesyRules Rules { get; private set; } internal ServerTuning ServerTuning { get; private set; } internal string VetoBy { get; private set; } internal bool ChatReadable { get; set; } = true; internal bool AllowsAssist => BlockReason == null; internal LocalText BlockReason { get { if (!_started) { return null; } switch (Rules) { case CourtesyRules.Waiting: return new LocalText(Msg.WaitingForServer); case CourtesyRules.Server: if (!ServerTuning.Allowed) { return new LocalText(Msg.NotAllowedHere); } return null; default: if (VetoBy != null) { return new LocalText(Msg.OffForSession, VetoBy); } if (!ChatReadable && _othersPresent > 0) { return new LocalText(Msg.ChatUnreadable); } return null; } } } internal CourtesyCore(ICourtesyChannel channel) { _channel = channel; Reset(); } internal void Reset() { _modPlayers.Clear(); _firstSeen.Clear(); _told.Clear(); _started = false; _listenUntil = float.NegativeInfinity; _othersPresent = 0; Rules = CourtesyRules.Chat; ServerTuning = default(ServerTuning); VetoBy = null; _vetoPeer = 0L; _vetoAccount = null; _vetoMissingSince = float.NaN; _pending = null; } internal void Begin(float now, long self, bool hosting) { _started = true; _self = self; _start = now; _serverDeadline = now + 10f; _modPlayers.Remove(self); Rules = (hosting ? CourtesyRules.Chat : CourtesyRules.Waiting); _listenUntil = now + 600f; if (!hosting) { _channel.Log($"Joined a server: waiting {10f:0} s at most to learn whether it sets AimAssist rules."); } } internal void OnModPlayer(long peer) { if (peer != _self) { _modPlayers.Add(peer); } } internal bool IsModPlayer(long peer) { return _modPlayers.Contains(peer); } internal void OnServerRules(ServerTuning tuning) { if (_started) { bool num = Rules != CourtesyRules.Server; Rules = CourtesyRules.Server; if (_pending != null) { _channel.Log(_pending.Name + " typed a command while joining: dropped, this server sets the rules."); _pending = null; } ServerTuning = tuning; if (num) { _channel.Log($"This server has AimAssist and sets the rules: {tuning}, instead of your own settings until you leave. Chat commands are off here."); _channel.Show(new LocalText(tuning.Allowed ? Msg.ServerSets : Msg.ServerForbids), center: true); } } } internal void Tick(float now, bool enabled, IReadOnlyList<PlayerSeen> others, IReadOnlyCollection<string> connected = null) { if (!_started) { return; } if (Rules == CourtesyRules.Waiting && now >= _serverDeadline) { Rules = CourtesyRules.Chat; _channel.Log("No AimAssist on this server: other players can turn the aim assist off with _aimassistoff in the chat."); if (_pending != null) { PendingCommand pending = _pending; _pending = null; OnChat(now, pending.Sender, pending.Name, pending.Account, pending.Text); } } _othersPresent = others.Count; CheckVetoAuthorStillHere(now, connected); foreach (PlayerSeen other in others) { if (!_firstSeen.ContainsKey(other.Peer)) { _firstSeen[other.Peer] = now; _listenUntil = Math.Max(_listenUntil, now + 600f); } } if (!enabled || !AllowsAssist || now < _start + 15f) { return; } List<PlayerSeen> list = others.Where((PlayerSeen p) => !_told.Contains(p.Peer) && now >= _firstSeen[p.Peer] + 10f).ToList(); if (list.Count == 0) { return; } bool flag = Rules == CourtesyRules.Server; _channel.Say(flag ? "* I use AimAssist, monsters only, with this server's settings." : "* I use AimAssist, monsters only. Disable it within 10 min: _aimassistoff", list.Select((PlayerSeen p) => p.Peer).ToList()); foreach (PlayerSeen item in list) { _told.Add(item.Peer); } string text = string.Join(", ", list.Select((PlayerSeen p) => p.Name)); if (flag) { _channel.Log("Announced AimAssist in the chat to " + text + "."); return; } _listenUntil = now + 600f; _channel.Log(string.Format("Announced AimAssist in the chat to {0}: {1} / {2} accepted for {3:0} min.", text, "_aimassistoff", "_aimassiston", 10f)); } private void CheckVetoAuthorStillHere(float now, IReadOnlyCollection<string> connected) { if (VetoBy != null && _vetoAccount != null && connected != null && _vetoPeer != _self) { if (connected.Contains(_vetoAccount)) { _vetoMissingSince = float.NaN; } else if (float.IsNaN(_vetoMissingSince)) { _vetoMissingSince = now; } else if (!(now - _vetoMissingSince < 3f)) { string vetoBy = VetoBy; VetoBy = null; _vetoAccount = null; _channel.Say($"* AimAssist back on ({vetoBy} left).", null); _channel.Show(new LocalText(Msg.AssistOn), center: true); _channel.Log(vetoBy + ", who had typed _aimassistoff, left the game: aim assist back on."); } } } internal void OnChat(float now, long sender, string name, string text) { OnChat(now, sender, name, null, text); } internal void OnChat(float now, long sender, string name, string account, string text) { if (!_started) { return; } if (Rules == CourtesyRules.Chat && text != null && text.Trim() == "* I use AimAssist, monsters only. Disable it within 10 min: _aimassistoff") { _listenUntil = Math.Max(_listenUntil, now + 600f); return; } bool flag = IsCommand(text, "_aimassistoff"); bool flag2 = IsCommand(text, "_aimassiston"); if (flag || flag2) { string text2 = (flag ? "_aimassistoff" : "_aimassiston"); if (Rules == CourtesyRules.Server) { _channel.Log(name + " typed " + text2 + ": ignored, this server sets the rules."); } else if (Rules == CourtesyRules.Waiting) { _pending = new PendingCommand { Sender = sender, Name = name, Account = account, Text = text }; _channel.Log(name + " typed " + text2 + ": kept until this server's rules are known."); } else if (now > _listenUntil) { _channel.Log($"{name} typed {text2}: ignored, more than {10f:0} min after the last announcement or arrival."); } else if (flag2 && VetoBy != null && sender != _vetoPeer && (sender == _self || _modPlayers.Contains(sender))) { _channel.Log(name + " typed _aimassiston: ignored, a player who has AimAssist can only take back their own _aimassistoff."); } else if (flag && VetoBy == null) { VetoBy = name; _vetoPeer = sender; _vetoAccount = (string.IsNullOrEmpty(account) ? null : account); _vetoMissingSince = float.NaN; _channel.Say($"* AimAssist off ({name}). Undo: _aimassiston", null); _channel.Show(new LocalText(Msg.Vetoed, name), center: true); _channel.Log(name + " typed _aimassistoff: aim assist off until you leave this world."); } else if (flag2 && VetoBy != null) { VetoBy = null; _channel.Say($"* AimAssist back on ({name}).", null); _channel.Show(new LocalText(Msg.Unvetoed, name), center: true); _channel.Log(name + " typed _aimassiston: aim assist back on."); } } } internal static bool IsCommand(string text, string command) { if (text != null) { return string.Equals(text.Trim(), command, StringComparison.OrdinalIgnoreCase); } return false; } } internal static class CrosshairTint { private const float BiomeBlend = 0.3f; private static bool _errorLogged; private static Biome _biome = (Biome)(-1); private static string _biomeName; private static Color _shown; private static bool _hasShown; internal static void Apply(Hud hud, Player player, float bowDrawPercentage) { //IL_00a0: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } try { Color? val = null; if (ModSettings.TargetColorEnabled.Value && ModSettings.TargetColor.HasValue && Targeting.Get(player).UnderCrosshair) { val = ModSettings.TargetColor; } Color? val2 = val ?? BaseColor(player); if (val2.HasValue) { Image crosshair = hud.m_crosshair; if ((Object)(object)crosshair != (Object)null && (val.HasValue || !ModSettings.KeepInteractColor.Value || !IsInteractYellow(((Graphic)crosshair).color))) { ((Graphic)crosshair).color = val2.Value; } Image crosshairBow = hud.m_crosshairBow; if (bowDrawPercentage > 0f && (Object)(object)crosshairBow != (Object)null) { Color value = val2.Value; value.a *= Mathf.Clamp01(bowDrawPercentage); ((Graphic)crosshairBow).color = value; } } } catch (Exception arg) { if (!_errorLogged) { _errorLogged = true; Plugin.Log.LogError((object)$"Crosshair colour error, the game's colours are kept (logged once): {arg}"); } } } private unsafe static Color? BaseColor(Player player) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_005b: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_008e: Unknown result type (might be due to invalid IL or missing references) Biome currentBiome = player.GetCurrentBiome(); if (currentBiome != _biome) { _biome = currentBiome; _biomeName = ((object)(*(Biome*)(¤tBiome))/*cast due to .constrained prefix*/).ToString(); } Color? val = ModSettings.BaseColor(_biomeName); if (!val.HasValue) { _hasShown = false; return null; } _shown = (_hasShown ? Color.Lerp(_shown, val.Value, 1f - Mathf.Exp((0f - Time.deltaTime) / 0.3f)) : val.Value); _hasShown = true; return _shown; } private static bool IsInteractYellow(Color color) { //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_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0025: 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_003e: 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_0057: Unknown result type (might be due to invalid IL or missing references) Color yellow = Color.yellow; if (Mathf.Abs(color.r - yellow.r) < 0.01f && Mathf.Abs(color.g - yellow.g) < 0.01f && Mathf.Abs(color.b - yellow.b) < 0.01f) { return Mathf.Abs(color.a - yellow.a) < 0.01f; } return false; } } internal static class Lang { internal static string Current { get { if (Localization.instance == null) { return "English"; } return Localization.instance.GetSelectedLanguage(); } } internal static string Pick(LocalText text) { return text.In(Current); } internal static string Pick(Msg message, params object[] args) { return Texts.Get(Current, message, args); } } public enum AssistMode { RangedEquipped, RangedAiming } internal static class ModSettings { internal struct BiomeDefault { internal readonly string Biome; internal readonly string Color; internal readonly string Why; internal BiomeDefault(string biome, string color, string why) { Biome = biome; Color = color; Why = why; } } private const string AimSection = "AimAssist"; private const string CrosshairSection = "Crosshair"; private const string BiomeSection = "CrosshairByBiome"; private const string HotkeySection = "Hotkeys"; private const string MultiplayerSection = "Multiplayer"; private const string ServerSection = "Server"; internal static readonly BiomeDefault[] BiomeDefaults = new BiomeDefault[9] { new BiomeDefault("Meadows", "#FF40FF", "bright green grass and blue sky: magenta"), new BiomeDefault("BlackForest", "#FF80C0", "dark green forest: light pink"), new BiomeDefault("Swamp", "#40E0FF", "murky brown water and olive fog: cyan"), new BiomeDefault("Mountain", "#A020F0", "white snow and pale sky: violet"), new BiomeDefault("Plains", "#3060FF", "golden grass: blue"), new BiomeDefault("Mistlands", "#A0FF20", "purple mist and black rock: lime"), new BiomeDefault("AshLands", "#00FFFF", "red lava and ash: cyan"), new BiomeDefault("DeepNorth", "#A020F0", "white ice: violet"), new BiomeDefault("Ocean", "#FFA020", "blue water: orange") }; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<AssistMode> Mode; internal static ConfigEntry<float> SlowdownFactor; internal static ConfigEntry<float> TrackingStrength; internal static ConfigEntry<float> Magnetism; internal static ConfigEntry<float> AimHeight; internal static ConfigEntry<float> AngularRadius; internal static ConfigEntry<float> MaxDistance; internal static ConfigEntry<float> MinDistance; internal static ConfigEntry<float> MaxAssistSpeed; internal static ConfigEntry<bool> IncludePassiveAnimals; internal static ConfigEntry<bool> TrackOwnMovement; internal static ConfigEntry<float> SmoothingTime; internal static ConfigEntry<bool> DebugLog; internal static ConfigEntry<string> CrosshairColorText; internal static ConfigEntry<bool> ColorByBiome; internal static ConfigEntry<bool> TargetColorEnabled; internal static ConfigEntry<string> TargetColorText; internal static ConfigEntry<bool> KeepInteractColor; internal static ConfigEntry<KeyboardShortcut> ToggleKey; internal static ConfigEntry<string> ToggleGamepad; internal static ConfigEntry<bool> ShowMessages; internal static ConfigEntry<bool> AllowAimAssist; internal static ConfigEntry<float> ServerSlowdownFactor; internal static ConfigEntry<float> ServerTrackingStrength; internal static ConfigEntry<float> ServerMagnetism; internal static readonly Dictionary<string, ConfigEntry<string>> BiomeColorText = new Dictionary<string, ConfigEntry<string>>(); private static readonly Dictionary<string, Color?> BiomeColors = new Dictionary<string, Color?>(); internal static Color? CrosshairColor { get; private set; } internal static Color? TargetColor { get; private set; } internal static string[] GamepadChord { get; private set; } = new string[0]; internal static float MagnetismRate => MagnetismRateOf(Magnetism.Value); internal static event Action GamepadChordChanged; internal static float MagnetismRateOf(float magnetism) { return magnetism * 24f; } internal static void Bind(ConfigFile config) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Expected O, but got Unknown //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Expected O, but got Unknown //IL_03f1: Unknown result type (might be due to invalid IL or missing references) Enabled = config.Bind<bool>("AimAssist", "Enabled", true, "Aim assist on or off. Gamepad only: never applied to mouse input. Also flipped in game by the toggle hotkeys. In multiplayer, the mod announces it in the chat, and any player can turn it off for the session with _aimassistoff."); Mode = config.Bind<AssistMode>("AimAssist", "Mode", AssistMode.RangedAiming, "When the assist works. RangedEquipped: as soon as a bow, crossbow, staff or other ranged weapon is in hand. RangedAiming: bow while drawn, crossbow while loaded, staffs and thrown weapons while in hand (the game has no aiming state for those)."); SlowdownFactor = config.Bind<float>("AimAssist", "SlowdownFactor", 0.6f, new ConfigDescription("Right stick sensitivity multiplier while the crosshair is on a target. 1 = no slowdown. Whatever you do to follow a moving target is never slowed, nor is a firm push away from it; it fades out at the edge of the zone.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>())); TrackingStrength = config.Bind<float>("AimAssist", "TrackingStrength", 0.5f, new ConfigDescription("Fraction of a moving target's angular movement that the camera follows by itself, even with the stick at rest. 0 = off, 1 = follows it fully. Only movement is followed: a still target never pulls a crosshair at rest. Yields on each axis where the stick pushes the other way.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); Magnetism = config.Bind<float>("AimAssist", "Magnetism", 0.5f, new ConfigDescription("Pull of the crosshair toward the part of the target's body you aim at (its centre for a small one): full as soon as you move the right stick, even slightly; half with the stick at rest, and then only while the crosshair is on the target's body or just beside it, never above it, so an aim held just above a distant target (for arrow drop) stays where you put it. Yields where the stick pushes the other way. 0 = off, 1 = very strong.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); AimHeight = config.Bind<float>("AimAssist", "AimHeight", 0f, new ConfigDescription("Raises the point the magnetism pulls towards, in metres above the middle of the target's body (at most three quarters of its thickness, so it stays on small targets). Arrows leave from the bow hand, below the crosshair, and drop: raise this if your arrows land low. 0 = middle of the body.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); AngularRadius = config.Bind<float>("AimAssist", "AngularRadius", 5f, new ConfigDescription("Size of the zone around a target's body, in degrees. A target is picked when the crosshair is within this angle of its outline; the assist is full on the body and fades to nothing at this distance. Among several, the closest to the crosshair wins.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 20f), Array.Empty<object>())); MaxDistance = config.Bind<float>("AimAssist", "MaxDistance", 50f, new ConfigDescription("Targets farther than this from the player, in metres, are ignored.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 150f), Array.Empty<object>())); MinDistance = config.Bind<float>("AimAssist", "MinDistance", 2f, new ConfigDescription("Closer than this, in metres, the assist is off; it fades back in up to twice this distance. Point-blank, a monster fills the screen and its angular speed explodes: following it would whip the camera around. 0 = assist at any range.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 10f), Array.Empty<object>())); MaxAssistSpeed = config.Bind<float>("AimAssist", "MaxAssistSpeed", 55f, new ConfigDescription("Advanced. Fastest the camera turns by itself to follow a target, in degrees per second (your own stick is never limited). Up close, a monster crossing in front of you moves faster than this and is lost; raise it to keep up, at the risk of a jerkier camera.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(20f, 180f), Array.Empty<object>())); IncludePassiveAnimals = config.Bind<bool>("AimAssist", "IncludePassiveAnimals", false, "Also assist on wildlife that only flees (deer, hares...). Off: only creatures that fight back. Players, tamed animals, summons and peaceful Dvergr are never targets. Applies to the target colour too."); TrackOwnMovement = config.Bind<bool>("AimAssist", "TrackOwnMovement", true, "Advanced. Tracking also compensates for your own movement (strafing around a target), as in Call of Duty. Off: only the target's own movement is tracked."); SmoothingTime = config.Bind<float>("AimAssist", "SmoothingTime", 0.08f, new ConfigDescription("Advanced. Time constant, in seconds, of the transitions when a target appears, is lost, or the assist kicks in. 0 = instant.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>())); DebugLog = config.Bind<bool>("AimAssist", "DebugLog", false, "Advanced. Twice per second while the assist works on a target, write what it sees and does to BepInEx/LogOutput.log (for tuning or reporting a problem)."); CrosshairColorText = config.Bind<string>("Crosshair", "Color", "", "Crosshair colour, hexadecimal: #RRGGBB or #RRGGBBAA (AA = opacity, 00 transparent to FF opaque), e.g. #FF4040 or #FFFFFFB0. Applies to the normal crosshair and to the bow circle, which keeps its fade-in while drawing. Used where no biome colour applies (see CrosshairByBiome). Empty: the game's colours."); ColorByBiome = config.Bind<bool>("Crosshair", "ColorByBiome", true, "Colour the crosshair according to the biome you stand in, with the colours of the CrosshairByBiome section. Off: Color everywhere."); TargetColorEnabled = config.Bind<bool>("Crosshair", "TargetColorEnabled", true, "Use TargetColor while a valid target is under the crosshair (same rules as the aim assist, with or without a gamepad)."); TargetColorText = config.Bind<string>("Crosshair", "TargetColor", "#FF4040", "Crosshair colour while a valid target is under it, same format as Color."); KeepInteractColor = config.Bind<bool>("Crosshair", "KeepInteractColor", true, "Keep the game's yellow crosshair when pointing at something you can interact with, instead of Color."); BiomeDefault[] biomeDefaults = BiomeDefaults; for (int i = 0; i < biomeDefaults.Length; i++) { BiomeDefault biomeDefault = biomeDefaults[i]; string name = biomeDefault.Biome; ConfigEntry<string> entry = config.Bind<string>("CrosshairByBiome", name, biomeDefault.Color, "Crosshair colour in " + name + ", same format as Color. The default stands out there (" + biomeDefault.Why + "). Empty: Color."); BiomeColorText[name] = entry; entry.SettingChanged += delegate { BiomeColors[name] = ReadColor(entry); }; BiomeColors[name] = ReadColor(entry); } ToggleKey = config.Bind<KeyboardShortcut>("Hotkeys", "ToggleKey", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), "Keyboard key that turns the aim assist on or off, with a message on screen."); ToggleGamepad = config.Bind<string>("Hotkeys", "ToggleGamepad", "JoyAltKeys + JoyButtonX", "Gamepad combination that turns the aim assist on or off: ZInput button names joined by '+', hold the first ones and press the last. Default: hold LT and press X with the classic layout (X alone sits down; holding LT cancels that). Empty: no gamepad toggle."); ShowMessages = config.Bind<bool>("Multiplayer", "ShowMessages", true, "Show the mod's multiplayer messages in the middle of your screen: aim assist turned off or back on by a player, rules of a dedicated server. Off: they only go to BepInEx/LogOutput.log. The chat lines, yours and the other players', are unchanged, and the toggle hotkey message always shows."); CrosshairColorText.SettingChanged += delegate { CrosshairColor = ReadColor(CrosshairColorText); }; TargetColorText.SettingChanged += delegate { TargetColor = ReadColor(TargetColorText); }; ToggleGamepad.SettingChanged += delegate { ReadChord(); }; CrosshairColor = ReadColor(CrosshairColorText); TargetColor = ReadColor(TargetColorText); ReadChord(); } internal static void BindServer(ConfigFile config) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown AllowAimAssist = config.Bind<bool>("Server", "AllowAimAssist", true, "Whether players who have AimAssist may use its aim assist on this server. Off: it stays off for them (crosshair colours still work). Either way, with AimAssist on the server, the other players' chat commands (_aimassistoff) no longer apply: this file sets the rules."); ServerSlowdownFactor = config.Bind<float>("Server", "SlowdownFactor", 0.6f, new ConfigDescription("Imposed on players who have AimAssist, instead of their own SlowdownFactor: right stick sensitivity on a target (1 = no slowdown, lower = stronger). Default: the mod's default.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 1f), Array.Empty<object>())); ServerTrackingStrength = config.Bind<float>("Server", "TrackingStrength", 0.5f, new ConfigDescription("Imposed on players who have AimAssist, instead of their own TrackingStrength (0 = off, 1 = follows a moving target fully). Default: the mod's default.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); ServerMagnetism = config.Bind<float>("Server", "Magnetism", 0.5f, new ConfigDescription("Imposed on players who have AimAssist, instead of their own Magnetism (0 = off, 1 = very strong). Default: the mod's default.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); } internal static Color? BaseColor(string biome) { if (ColorByBiome.Value && biome != null && BiomeColors.TryGetValue(biome, out var value) && value.HasValue) { return value; } return CrosshairColor; } private static Color? ReadColor(ConfigEntry<string> entry) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(entry.Value)) { return null; } if (TryParseColor(entry.Value, out var color)) { return color; } Plugin.Warn("[" + ((ConfigEntryBase)entry).Definition.Section + "] " + ((ConfigEntryBase)entry).Definition.Key + " = \"" + entry.Value + "\" is not a colour like #FF4040 or #FF4040B0. The game's colour is used instead."); return null; } private static void ReadChord() { GamepadChord = ParseChord(ToggleGamepad.Value); ModSettings.GamepadChordChanged?.Invoke(); } internal static bool TryParseColor(string text, out Color color) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) color = default(Color); if (text == null) { return false; } string text2 = text.Trim(); if (text2.StartsWith("#", StringComparison.Ordinal)) { text2 = text2.Substring(1); } if (text2.Length == 3 || text2.Length == 4) { text2 = string.Concat(text2.Select((char c) => new string(c, 2))); } if (text2.Length != 6 && text2.Length != 8) { return false; } if (!uint.TryParse(text2, NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture, out var result)) { return false; } if (text2.Length == 6) { result = (result << 8) | 0xFF; } color = new Color((float)((result >> 24) & 0xFF) / 255f, (float)((result >> 16) & 0xFF) / 255f, (float)((result >> 8) & 0xFF) / 255f, (float)(result & 0xFF) / 255f); return true; } internal static string[] ParseChord(string text) { if (string.IsNullOrWhiteSpace(text)) { return new string[0]; } return (from part in text.Split(new char[1] { '+' }) select part.Trim() into part where part.Length > 0 select part).ToArray(); } } internal static class Patches { internal static bool ApplyAimAssist(Harmony harmony, List<string> report) { if (AimAssist.Init(report)) { return Apply(harmony, report, typeof(PlayerController_LateUpdate_Patch), typeof(Player_SetMouseLook_Patch)); } return false; } internal static bool ApplyCrosshair(Harmony harmony, List<string> report) { return Apply(harmony, report, typeof(Hud_UpdateCrosshair_Patch)); } internal static bool ApplyCourtesy(Harmony harmony, List<string> report) { if (Courtesy.Init(report)) { return Apply(harmony, report, typeof(ZRoutedRpc_HandleRoutedRPC_Patch)); } return false; } private static bool Apply(Harmony harmony, List<string> report, params Type[] patchClasses) { HashSet<MethodBase> before = new HashSet<MethodBase>(harmony.GetPatchedMethods()); foreach (Type type in patchClasses) { try { harmony.CreateClassProcessor(type).Patch(); } catch (Exception ex) { report.Add(type.Name + " could not be applied: " + ex.GetBaseException().Message); foreach (MethodBase item in (from m in harmony.GetPatchedMethods() where !before.Contains(m) select m).ToList()) { harmony.Unpatch(item, (HarmonyPatchType)0, harmony.Id); } return false; } } return true; } } [HarmonyPatch(typeof(PlayerController), "LateUpdate")] internal static class PlayerController_LateUpdate_Patch { private static void Prefix(PlayerController __instance) { AimAssist.BeginLookUpdate(__instance); } private static void Finalizer() { AimAssist.EndLookUpdate(); } } [HarmonyPatch(typeof(Player), "SetMouseLook")] internal static class Player_SetMouseLook_Patch { private static void Prefix(Player __instance, ref Vector2 mouseLook) { AimAssist.ApplyToLook(__instance, ref mouseLook); } } [HarmonyPatch(typeof(Hud), "UpdateCrosshair")] internal static class Hud_UpdateCrosshair_Patch { private static void Postfix(Hud __instance, Player player, float bowDrawPercentage) { CrosshairTint.Apply(__instance, player, bowDrawPercentage); } } [HarmonyPatch(typeof(ZRoutedRpc), "HandleRoutedRPC")] internal static class ZRoutedRpc_HandleRoutedRPC_Patch { private static void Prefix(RoutedRPCData data) { Courtesy.OnRoutedRpc(data); } } [BepInPlugin("moochi.aimassist", "AimAssist", "0.6.9")] [BepInProcess("valheim.exe")] [BepInProcess("valheim_server.exe")] public class Plugin : BaseUnityPlugin { public const string PluginGuid = "moochi.aimassist"; public const string PluginName = "AimAssist"; public const string PluginVersion = "0.6.9"; private Harmony _harmony; private FileSystemWatcher _watcher; private bool _server; internal static ManualLogSource Log { get; private set; } private void Awake() { Log = ((BaseUnityPlugin)this).Logger; _server = string.Equals(Path.GetFileNameWithoutExtension(Paths.ProcessName), "valheim_server", StringComparison.OrdinalIgnoreCase); if (_server) { AwakeOnServer(); } else { AwakeInGame(); } WatchConfigFile(); } private void AwakeOnServer() { ModSettings.BindServer(((BaseUnityPlugin)this).Config); Log.LogInfo((object)string.Format("{0} v{1} loaded on a dedicated server. Rules for players who have AimAssist: {2}.", "AimAssist", "0.6.9", ServerRules.Current)); } private void AwakeInGame() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown ModSettings.Bind(((BaseUnityPlugin)this).Config); List<string> list = new List<string>(); Targeting.Init(list); Toggle.Init(list); _harmony = new Harmony("moochi.aimassist"); bool flag = Patches.ApplyAimAssist(_harmony, list); bool flag2 = Patches.ApplyCrosshair(_harmony, list); bool flag3 = Patches.ApplyCourtesy(_harmony, list); Courtesy.SetChatReadable(flag3); foreach (string item in list) { Log.LogWarning((object)item); } if (!flag) { Log.LogError((object)"Aim assist is OFF: the game no longer looks like the version this mod was written for (see above)."); } if (!flag2) { Log.LogError((object)"Crosshair colours are OFF: the game no longer looks like the version this mod was written for (see above)."); } if (!flag3) { Log.LogError((object)"Chat commands are OFF: the game no longer looks like the version this mod was written for (see above). Other players could not turn the aim assist off, so it stays off while they are in the world, unless a server with AimAssist sets the rules."); } Log.LogInfo((object)("AimAssist v0.6.9 loaded: aim assist " + (flag ? "ready" : "OFF") + " " + string.Format("({0}, {1}), crosshair colours {2}, ", ModSettings.Enabled.Value ? "enabled" : "disabled", ModSettings.Mode.Value, flag2 ? "ready" : "OFF") + "chat announcement " + (flag3 ? "ready" : "OFF") + ".")); } private void Update() { if (_server) { ServerRules.Poll(); return; } Toggle.Poll(); Courtesy.Poll(); } private void WatchConfigFile() { _watcher = new FileSystemWatcher(Path.GetDirectoryName(((BaseUnityPlugin)this).Config.ConfigFilePath), Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath)); _watcher.Changed += delegate { ReloadConfig(); }; _watcher.Created += delegate { ReloadConfig(); }; _watcher.Renamed += delegate { ReloadConfig(); }; _watcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; _watcher.EnableRaisingEvents = true; } private void ReloadConfig() { if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { return; } try { ((BaseUnityPlugin)this).Config.Reload(); } catch (Exception ex) { Log.LogError((object)("Could not read " + Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath) + ": " + ex.Message)); } } internal static void Warn(string message) { if (Log != null) { Log.LogWarning((object)message); } } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } if (_watcher != null) { _watcher.Dispose(); } } } internal static class Protocol { internal const string Hello = "moochi.AimAssist.Hello"; internal const string Rules = "moochi.AimAssist.Rules"; private const int Format = 1; internal static ZPackage WriteHello(bool wantsReply) { //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_000c: 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_001f: Expected O, but got Unknown ZPackage val = new ZPackage(); val.Write(1); val.Write("0.6.9"); val.Write(wantsReply); return val; } internal static void ReadHello(ZPackage pkg, out string modVersion, out bool wantsReply) { pkg.ReadInt(); modVersion = pkg.ReadString();