using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using AzNean.SotfCommon;
using Ballistics;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.Attributes;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using ProjectileAimIndicator.Logic;
using ProjectileAimIndicator.Patches;
using Sons.Gui;
using Sons.Inventory;
using Sons.Items.Core;
using Sons.Weapon;
using TheForest.Utils;
using UnityEngine;
using UnityEngine.Rendering;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("ProjectileAimIndicator")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.2.20.0")]
[assembly: AssemblyInformationalVersion("0.2.20+e032234f27f1f72f2aff98afdebb24baaeee0ef9")]
[assembly: AssemblyProduct("ProjectileAimIndicator")]
[assembly: AssemblyTitle("ProjectileAimIndicator")]
[assembly: AssemblyVersion("0.2.20.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[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 AzNean.SotfCommon
{
internal static class ModLog
{
private static ManualLogSource _log;
private static ConfigEntry<bool> _full;
private static readonly HashSet<string> _once = new HashSet<string>();
private static readonly Dictionary<(int, string), int> _state = new Dictionary<(int, string), int>();
internal static bool Full => _full.Value;
internal static void Init(ManualLogSource log, ConfigEntry<bool> full)
{
_log = log;
_full = full;
}
internal static void Trace(string message)
{
if (_full.Value)
{
_log.LogInfo((object)message);
}
}
internal static bool Changed(int id, string what, int state)
{
if (!_full.Value || (_state.TryGetValue((id, what), out var value) && value == state))
{
return false;
}
_state[(id, what)] = state;
return true;
}
internal static void Once(string key, string message, LogLevel level = (LogLevel)16)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
if (_once.Add(key))
{
_log.Log(level, (object)message);
}
}
}
}
namespace ProjectileAimIndicator
{
public class AimWatcher : MonoBehaviour
{
internal static AimWatcher Instance;
private GameObject _linePrefab;
private GameObject _targetPrefab;
private LineRenderer _line;
private GameObject _target;
private float _targetMetres = 0.5f;
private bool _failed;
private int _heldId;
private RangedWeapon _weapon;
private RangedWeaponController _controller;
private WeaponKind _kind;
private bool _chosen;
private bool _shown;
private bool _gameOwn;
private GameObject _gameTarget;
private Vector3 _gameTargetScale;
private float _gameTargetMetres;
private float _nextLookup;
private float _nextPath;
private bool _hit;
private Vector3 _shownImpact;
private Vector3 _shownPos;
private Vector3 _shownDir;
private float _lastDraw = -1f;
private int _shotFrame = -1;
private IntPtr _pendingWeapon;
private Vector3 _pendingShown;
private Vector3 _pendingReplay;
private bool _pendingShownHit;
private bool _pendingReplayHit;
private float _pendingTime;
private WeaponKind _pendingKind;
private readonly HashSet<(int, bool)> _sizedCameras = new HashSet<(int, bool)>();
public AimWatcher(IntPtr ptr)
: base(ptr)
{
}
internal void Refresh()
{
_heldId = 0;
}
private void Awake()
{
Instance = this;
}
private void LateUpdate()
{
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Invalid comparison between Unknown and I4
if (_failed)
{
return;
}
RangedWeapon val = HeldWeapon();
if ((Object)(object)val != (Object)null && _gameOwn)
{
Hide();
if (_chosen)
{
TakeGameTarget(val);
}
return;
}
bool midAttack = (Object)(object)val != (Object)null && _controller._isCharging && (int)_controller._attackState == 2;
if (!((Object)(object)val != (Object)null) || !Decision.ShouldShow(_kind, _chosen, midAttack, _controller.IsAiming))
{
Hide();
return;
}
if (!_shown)
{
_nextPath = 0f;
}
_shown = true;
if (Time.unscaledTime >= _nextPath)
{
DrawPath(val);
}
}
private void Hide()
{
if (_shown)
{
_shown = false;
if ((Object)(object)_line != (Object)null)
{
((Component)_line).gameObject.SetActive(false);
}
if ((Object)(object)_target != (Object)null)
{
_target.SetActive(false);
}
}
}
private RangedWeapon HeldWeapon()
{
//IL_03cf: Unknown result type (might be due to invalid IL or missing references)
//IL_03df: Unknown result type (might be due to invalid IL or missing references)
if (!LocalPlayer.IsInWorld || PauseMenu.IsActive)
{
return null;
}
ItemInstance rightHandItem = LocalPlayer.Inventory.RightHandItem;
GameObject val = ((rightHandItem != null) ? rightHandItem.ItemObject : null);
int num = ((!((Object)(object)val == (Object)null)) ? ((Object)val).GetInstanceID() : 0);
bool flag = num != _heldId;
if (flag)
{
Hide();
ReleaseGameTarget();
}
if ((Object)(object)val == (Object)null)
{
_heldId = 0;
_weapon = null;
return null;
}
if (flag || (((Object)(object)_weapon == (Object)null || ((Object)(object)_controller == (Object)null && _kind == WeaponKind.Other)) && Time.unscaledTime >= _nextLookup))
{
_heldId = num;
_nextLookup = Time.unscaledTime + Plugin.LookupSeconds.Value;
_weapon = val.GetComponentInChildren<RangedWeapon>(true);
_controller = val.GetComponentInChildren<RangedWeaponController>(true);
_kind = KindOf(_controller, val);
_gameOwn = (Object)(object)_weapon != (Object)null && (Decision.GameDrawsOwn(_kind) || ((Object)(object)_controller != (Object)null && (Object)(object)_weapon._trajectoryPathPrefab != (Object)null && _weapon._showImpactLocation));
bool flag2 = (Object)(object)_weapon != (Object)null && ((Object)(object)_controller != (Object)null || _gameOwn);
_chosen = flag2 && Plugin.IsChosen(_kind) && (_gameOwn || Ready());
if (ModLog.Changed(num, "weapon", flag2 ? (1 + (_chosen ? 2 : 0) + (_gameOwn ? 4 : 0)) : 0))
{
ModLog.Trace("Held " + ((Object)val).name + ": " + (flag2 ? $"{_kind} ({(((Object)(object)_controller != (Object)null) ? ((MemberInfo)((Object)_controller).GetIl2CppType()).Name : "no ranged controller")}), {(_gameOwn ? $"the game draws its own target, sized by the mod={_chosen}" : $"indicator={_chosen}")} (game line={(Object)(object)_weapon._trajectoryPathPrefab != (Object)null}, game option={_weapon._showImpactLocation}), spawn point {(((Object)(object)((Weapon)_weapon).physicalSpawnPoint != (Object)null) ? ((Object)((Weapon)_weapon).physicalSpawnPoint).name : "none")} ({(((Object)(object)((Weapon)_weapon).physicalSpawnPoint == (Object)null || (Object)(object)_weapon.GetProjectileTransform() == (Object)null) ? "n/a" : $"{Vector3.Angle(((Weapon)_weapon).physicalSpawnPoint.forward, _weapon.GetProjectileTransform().forward):F2}")}° from the projectile axis), laser sight={_weapon.HasLaserSight()}, spawn is laser copy={(Object)(object)((Weapon)_weapon).physicalSpawnPoint != (Object)null && (Object)(object)((Weapon)_weapon).physicalSpawnPoint == (Object)(object)_weapon._projectilePhysicalSpawnPoint}, modified screen position={_weapon._useModifiedScreenPostion}, ammo {AmmoName(_weapon)}" : $"no ranged weapon yet (weapon={(Object)(object)_weapon != (Object)null}, controller={(Object)(object)_controller != (Object)null})"));
}
}
if (!((Object)(object)_weapon != (Object)null) || (!((Object)(object)_controller != (Object)null) && !_gameOwn))
{
return null;
}
return _weapon;
}
private static WeaponKind KindOf(RangedWeaponController c, GameObject held)
{
if ((Object)(object)c == (Object)null)
{
if ((Object)(object)held.GetComponentInChildren<SeveredLimbController>(true) != (Object)null)
{
return WeaponKind.Thrown;
}
if (!((Object)(object)held.GetComponentInChildren<SpearWeaponController>(true) != (Object)null))
{
return WeaponKind.Other;
}
return WeaponKind.Spear;
}
if ((Object)(object)((Il2CppObjectBase)c).TryCast<BowWeaponController>() != (Object)null)
{
return WeaponKind.Bow;
}
if ((Object)(object)((Il2CppObjectBase)c).TryCast<CrossbowWeaponController>() != (Object)null)
{
return WeaponKind.Crossbow;
}
if ((Object)(object)((Il2CppObjectBase)c).TryCast<SlingshotWeaponController>() != (Object)null)
{
return WeaponKind.Slingshot;
}
if ((Object)(object)((Il2CppObjectBase)c).TryCast<FlareWeaponController>() != (Object)null)
{
return WeaponKind.FlareGun;
}
if ((Object)(object)((Il2CppObjectBase)c).TryCast<RopeGunController>() != (Object)null)
{
return WeaponKind.RopeGun;
}
if ((Object)(object)((Il2CppObjectBase)c).TryCast<StunGunWeaponController>() != (Object)null)
{
return WeaponKind.StunGun;
}
if ((Object)(object)((Il2CppObjectBase)c).TryCast<GrenadeWeaponController>() != (Object)null || (Object)(object)((Il2CppObjectBase)c).TryCast<MolotovWeaponController>() != (Object)null || (Object)(object)((Il2CppObjectBase)c).TryCast<TimeBombWeaponController>() != (Object)null || (Object)(object)((Il2CppObjectBase)c).TryCast<SmallRockWeaponController>() != (Object)null)
{
return WeaponKind.Thrown;
}
return WeaponKind.Firearm;
}
private void TakeGameTarget(RangedWeapon weapon)
{
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_gameTarget != (Object)null)
{
return;
}
GameObject impactTargetInstance = weapon._impactTargetInstance;
if ((Object)(object)impactTargetInstance == (Object)null)
{
if (ModLog.Changed(_heldId, "game target", 0))
{
ModLog.Trace($"{_kind}: the game's own landing target does not exist yet (made the first time the game shows its indicator), sized then");
}
return;
}
_gameTarget = impactTargetInstance;
_gameTargetScale = impactTargetInstance.transform.localScale;
_gameTargetMetres = VisibleWidth(impactTargetInstance);
ModLog.Once($"game target {((Object)impactTargetInstance).GetInstanceID()}", $"{_kind}: the game's own landing target {((Object)impactTargetInstance).name} taken, {_gameTargetMetres:F2} m wide at its own scale", (LogLevel)16);
}
private void ReleaseGameTarget()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_gameTarget != (Object)null)
{
_gameTarget.transform.localScale = _gameTargetScale;
}
_gameTarget = null;
}
private static float VisibleWidth(GameObject target)
{
//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)
//IL_003f: 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_004f: 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_0055: 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_0061: Unknown result type (might be due to invalid IL or missing references)
foreach (MeshFilter componentsInChild in target.GetComponentsInChildren<MeshFilter>(true))
{
if (((Component)componentsInChild).gameObject.activeSelf && !((Object)(object)componentsInChild.sharedMesh == (Object)null))
{
Bounds bounds = componentsInChild.sharedMesh.bounds;
Vector3 val = Vector3.Scale(((Bounds)(ref bounds)).size, ((Component)componentsInChild).transform.lossyScale);
return Mathf.Max(val.x, Mathf.Max(val.y, val.z));
}
}
return 0f;
}
private bool Ready()
{
if ((Object)(object)_linePrefab == (Object)null && !FindSpear())
{
return false;
}
if ((Object)(object)_line == (Object)null)
{
_line = Hidden(_linePrefab).GetComponent<LineRenderer>();
}
if ((Object)(object)_target == (Object)null && (Object)(object)_targetPrefab != (Object)null)
{
_target = Hidden(_targetPrefab);
}
return (Object)(object)_line != (Object)null;
}
private static string AmmoName(RangedWeapon weapon)
{
Ammo ammo = weapon.GetAmmo();
AmmoProperties val = ((ammo != null) ? ammo._properties : null);
ProjectileInfo val2 = ((val != null) ? val.ProjectileInfo : null);
if (!((Object)(object)val == (Object)null))
{
return ((Object)val).name + " (" + ((val2 == null) ? "no flight data" : $"speed {((BulletInfo)val2).maxSpeed:F1} m/s, drag {((BulletInfo)val2).dragCoefficient:F2}, weight {((BulletInfo)val2).weight:F3}") + ")";
}
return "none";
}
private static GameObject Hidden(GameObject prefab)
{
GameObject obj = Object.Instantiate<GameObject>(prefab);
obj.SetActive(false);
return obj;
}
private void DrawPath(RangedWeapon weapon)
{
//IL_00c5: 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_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_0184: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: 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)
_nextPath = Time.unscaledTime + Plugin.PathUpdateSeconds.Value;
int num = ((!Ready()) ? 1 : ((!RefreshBulletInfo(weapon)) ? 2 : ((!Launch(weapon, out _shownPos, out _shownDir)) ? 3 : 0)));
if (ModLog.Changed(_heldId, "path", num))
{
ModLog.Trace($"{_kind}: {num switch
{
2 => "no aim path, no ammo with flight data loaded",
1 => "no aim path, the spear's line could not be copied",
0 => "aim path drawn",
_ => "no aim path, the weapon has no spawn point",
}}");
}
if (num != 0)
{
Hide();
_shown = true;
return;
}
TrajectoryData val = weapon.SimulateTrajectory(_shownPos, _shownDir);
List<Vector3> arcPoints = val.arcPoints;
int num2 = arcPoints?.Count ?? 0;
_line.positionCount = num2;
for (int i = 0; i < num2; i++)
{
_line.SetPosition(i, arcPoints[i]);
}
((Component)_line).gameObject.SetActive(num2 > 1);
_hit = val.surfaceImpactDetected;
_lastDraw = Time.unscaledTime;
if (_hit)
{
RaycastHit rayHit = val.resultingSurfaceImpactInfo.rayHit;
_shownImpact = ((RaycastHit)(ref rayHit)).point;
if ((Object)(object)_target != (Object)null)
{
Transform transform = _target.transform;
transform.position = ((RaycastHit)(ref rayHit)).point;
transform.up = ((RaycastHit)(ref rayHit)).normal;
SizeFor(Camera.main, _target, Vector3.one, _targetMetres);
}
}
if ((Object)(object)_target != (Object)null)
{
_target.SetActive(_hit);
}
}
private void SizeFor(Camera cam, GameObject target, Vector3 baseScale, float metres)
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: 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)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Expected O, but got Unknown
if ((Object)(object)cam == (Object)null || (Object)(object)target == (Object)null)
{
return;
}
Transform transform = target.transform;
float num = Vector3.Distance(((Component)cam).transform.position, transform.position);
float num2 = Decision.MarkerScale(num, cam.fieldOfView, Plugin.MarkerScreenSize.Value, Plugin.MarkerMaxMetres.Value, metres);
transform.localScale = baseScale * num2;
bool flag = (Object)(object)target == (Object)(object)_target;
if (_sizedCameras.Add((((Object)cam).GetInstanceID(), flag)))
{
ManualLogSource logger = Plugin.Logger;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(56, 5, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Landing target");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(flag ? "" : $" (game's own, {_kind})");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" sized for camera ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)cam).name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num2 * metres, "F2");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m wide at ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num, "F1");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" m (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(cam.fieldOfView, "F0");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("° view)");
}
logger.LogInfo(val);
}
}
internal static void BeforeCamera(ScriptableRenderContext context, Camera cam)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
AimWatcher instance = Instance;
if (!((Object)(object)instance == (Object)null))
{
if ((Object)(object)instance._target != (Object)null && instance._target.activeSelf)
{
instance.SizeFor(cam, instance._target, Vector3.one, instance._targetMetres);
}
if ((Object)(object)instance._gameTarget != (Object)null && instance._gameTarget.activeInHierarchy)
{
instance.SizeFor(cam, instance._gameTarget, instance._gameTargetScale, instance._gameTargetMetres);
}
}
}
[HideFromIl2Cpp]
private static bool Launch(RangedWeapon weapon, out Vector3 pos, out Vector3 dir)
{
//IL_001b: 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_0012: 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_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
Transform val = SpawnPoint(weapon);
pos = (Vector3)(((Object)(object)val == (Object)null) ? default(Vector3) : val.position);
dir = (Vector3)(((Object)(object)val == (Object)null) ? default(Vector3) : val.forward);
return (Object)(object)val != (Object)null;
}
private static Transform SpawnPoint(RangedWeapon weapon)
{
Transform physicalSpawnPoint = ((Weapon)weapon).physicalSpawnPoint;
if (!((Object)(object)physicalSpawnPoint != (Object)null) || !weapon.HasLaserSight() || !((Object)(object)physicalSpawnPoint == (Object)(object)weapon._projectilePhysicalSpawnPoint))
{
return physicalSpawnPoint;
}
return weapon.GetProjectileTransform();
}
private static bool RefreshBulletInfo(RangedWeapon weapon)
{
Ammo ammo = weapon.GetAmmo();
object obj;
if (ammo == null)
{
obj = null;
}
else
{
AmmoProperties properties = ammo._properties;
obj = ((properties != null) ? properties.ProjectileInfo : null);
}
ProjectileInfo val = (ProjectileInfo)obj;
if (val == null)
{
return false;
}
weapon._simulatedBulletInfo = (BulletInfo)(object)val;
if ((Object)(object)weapon._simulatedBullet == (Object)null)
{
weapon.SimulateTrajectory();
}
return true;
}
internal void Fired(RangedWeapon weapon, Vector3 direction, float zeroAngle)
{
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: 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_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: 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_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: 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_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_0237: Unknown result type (might be due to invalid IL or missing references)
//IL_0250: 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_0274: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Unknown result type (might be due to invalid IL or missing references)
//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
//IL_02a6: 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_02d3: Unknown result type (might be due to invalid IL or missing references)
if (!ModLog.Full || (Object)(object)_weapon == (Object)null || ((Il2CppObjectBase)weapon).Pointer != ((Il2CppObjectBase)_weapon).Pointer || !_chosen || _gameOwn || Time.frameCount == _shotFrame)
{
return;
}
_shotFrame = Time.frameCount;
Transform val = SpawnPoint(weapon);
if ((Object)(object)val == (Object)null)
{
ModLog.Trace($"Shot {_kind}: the weapon has no spawn point, not compared with the indicator");
return;
}
Vector3 position = val.position;
Vector3 normalized = ((Vector3)(ref direction)).normalized;
Transform projectileTransform = weapon.GetProjectileTransform();
if (_pendingWeapon != IntPtr.Zero)
{
ModLog.Trace($"{_pendingKind}: previous shot's impact never reported (lost or out of range)");
}
bool flag = _lastDraw >= 0f && Time.unscaledTime - _lastDraw < 1f;
bool flag2 = flag && _hit;
TrajectoryData val2 = weapon.SimulateTrajectory(position, normalized);
_pendingWeapon = ((Il2CppObjectBase)weapon).Pointer;
_pendingKind = _kind;
_pendingShown = _shownImpact;
_pendingShownHit = flag2;
_pendingReplayHit = val2.surfaceImpactDetected;
? pendingReplay;
if (!_pendingReplayHit)
{
pendingReplay = default(Vector3);
}
else
{
RaycastHit rayHit = val2.resultingSurfaceImpactInfo.rayHit;
pendingReplay = ((RaycastHit)(ref rayHit)).point;
}
_pendingReplay = (Vector3)pendingReplay;
_pendingTime = Time.time;
ModLog.Trace($"Shot {_kind}: indicator {((!flag) ? "not shown" : (flag2 ? $"showed impact {_shownImpact:F1}" : "showed no impact"))}; real launch {position:F2} differs by {Vector3.Distance(position, _shownPos):F2} m and {Vector3.Angle(normalized, _shownDir):F2}° (at this instant: spawn point axis {Vector3.Angle(normalized, val.forward):F2}°, projectile axis {(((Object)(object)projectileTransform == (Object)null) ? "n/a" : Vector3.Angle(normalized, projectileTransform.forward).ToString("F2"))}°) (zero angle {zeroAngle:F2}, ammo {AmmoName(weapon)}); replay from real launch: {(_pendingReplayHit ? ((Vector3)(ref _pendingReplay)).ToString("F1") : "no impact")}");
}
internal void Landed(Weapon weapon, Vector3 point)
{
//IL_0055: 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_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: 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)
if (!(_pendingWeapon == IntPtr.Zero) && !((Object)(object)weapon == (Object)null) && !(((Il2CppObjectBase)weapon).Pointer != _pendingWeapon))
{
_pendingWeapon = IntPtr.Zero;
string value = (_pendingShownHit ? $"{Vector3.Distance(_pendingShown, point):F2} m" : "n/a (no impact shown)");
string value2 = (_pendingReplayHit ? $"{Vector3.Distance(_pendingReplay, point):F2} m" : "n/a");
ModLog.Trace($"Impact {_pendingKind}: real {point:F1} after {Time.time - _pendingTime:F2} s; indicator off by {value}, replay from real launch off by {value2}");
}
}
private bool FindSpear()
{
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Expected O, but got Unknown
ItemData obj = ItemDatabaseManager.ItemById(ItemDatabase.CraftedSpearId);
object obj2;
if (obj == null)
{
obj2 = null;
}
else
{
Transform heldPrefab = obj.HeldPrefab;
obj2 = ((heldPrefab != null) ? ((Component)heldPrefab).GetComponentInChildren<RangedWeapon>(true) : null);
}
RangedWeapon val = (RangedWeapon)obj2;
if ((Object)(object)val == (Object)null || (Object)(object)val._trajectoryPathPrefab == (Object)null)
{
_failed = true;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(71, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("The spear's aim indicator was not found (ranged part=");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>((Object)(object)val != (Object)null);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("); the mod is off.");
}
logger.LogError(val2);
return false;
}
_linePrefab = val._trajectoryPathPrefab;
_targetPrefab = val._impactTargetPrefab;
float num = (((Object)(object)_targetPrefab != (Object)null) ? VisibleWidth(_targetPrefab) : 0f);
if (num > 0f)
{
_targetMetres = num;
}
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(60, 4);
defaultInterpolatedStringHandler.AppendLiteral("Spear indicator found: path=");
defaultInterpolatedStringHandler.AppendFormatted(((Object)_linePrefab).name);
defaultInterpolatedStringHandler.AppendLiteral(", target=");
GameObject targetPrefab = _targetPrefab;
defaultInterpolatedStringHandler.AppendFormatted((targetPrefab != null) ? ((Object)targetPrefab).name : null);
defaultInterpolatedStringHandler.AppendLiteral(", ");
defaultInterpolatedStringHandler.AppendFormatted(_targetMetres, "F2");
defaultInterpolatedStringHandler.AppendLiteral(" m wide at scale 1 (");
defaultInterpolatedStringHandler.AppendFormatted((num > 0f) ? "measured" : "not measurable, default kept");
defaultInterpolatedStringHandler.AppendLiteral(")");
ModLog.Trace(defaultInterpolatedStringHandler.ToStringAndClear());
return true;
}
}
[BepInPlugin("aznan.sotf.projectileaimindicator", "ProjectileAimIndicator", "0.2.20")]
public class Plugin : BasePlugin
{
internal const string Version = "0.2.20";
internal static ManualLogSource Logger;
internal static ConfigEntry<bool> FullLogging;
private static readonly Dictionary<WeaponKind, ConfigEntry<bool>> Chosen = new Dictionary<WeaponKind, ConfigEntry<bool>>();
internal static ConfigEntry<float> LookupSeconds;
internal static ConfigEntry<float> PathUpdateSeconds;
internal static ConfigEntry<float> MarkerScreenSize;
internal static ConfigEntry<float> MarkerMaxMetres;
internal static ConfigEntry<bool> Enabled;
private static Action<ScriptableRenderContext, Camera> _beforeCamera;
private static string Describe(WeaponKind kind)
{
return kind switch
{
WeaponKind.FlareGun => "flare gun",
WeaponKind.Spear => "thrown spear",
WeaponKind.Thrown => "thrown items (grenade, molotov, time bomb, rocks, severed limbs)",
WeaponKind.RopeGun => "rope gun",
WeaponKind.StunGun => "stun gun",
WeaponKind.Firearm => "firearms (pistol, revolver, shotgun, rifle)",
_ => kind.ToString().ToLowerInvariant(),
};
}
internal static bool IsChosen(WeaponKind kind)
{
if (Enabled.Value && Chosen.TryGetValue(kind, out var value))
{
return value.Value;
}
return false;
}
public override void Load()
{
//IL_0270: Unknown result type (might be due to invalid IL or missing references)
//IL_0277: Expected O, but got Unknown
//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
//IL_02e3: Expected O, but got Unknown
//IL_0314: Unknown result type (might be due to invalid IL or missing references)
//IL_031b: Expected O, but got Unknown
//IL_020d: Unknown result type (might be due to invalid IL or missing references)
//IL_0213: Expected O, but got Unknown
//IL_0249: Unknown result type (might be due to invalid IL or missing references)
Logger = ((BasePlugin)this).Log;
Decision.SelfCheck();
Enabled = ((BasePlugin)this).Config.Bind<bool>("General", "Enabled", true, "True = the weapons ticked in [Weapons] show the aim indicator, and the game's own landing target of the items ticked there keeps the same size on screen. False = nothing from this mod (the game's own indicators stay as the game draws them).");
bool flag = default(bool);
foreach (WeaponKind value in Enum.GetValues(typeof(WeaponKind)))
{
if (value != WeaponKind.Other)
{
Dictionary<WeaponKind, ConfigEntry<bool>> chosen = Chosen;
WeaponKind key = value;
ConfigFile config = ((BasePlugin)this).Config;
string text = value.ToString();
bool num = Decision.OnByDefault(value);
string text2;
if (!Decision.GameDrawsOwn(value))
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(92, 3);
defaultInterpolatedStringHandler.AppendLiteral("Show the thrown spear's aim indicator (path and landing target) while aiming the ");
defaultInterpolatedStringHandler.AppendFormatted(Describe(value));
defaultInterpolatedStringHandler.AppendFormatted((value == WeaponKind.FlareGun) ? " (if the game already draws its own, only its target is sized)" : "");
defaultInterpolatedStringHandler.AppendLiteral(". Default ");
flag = Decision.OnByDefault(value);
defaultInterpolatedStringHandler.AppendFormatted(flag.ToString().ToLowerInvariant());
defaultInterpolatedStringHandler.AppendLiteral(".");
text2 = defaultInterpolatedStringHandler.ToStringAndClear();
}
else
{
text2 = "The game draws its own aim indicator for the " + Describe(value) + ". True = its landing target keeps the size set in [Marker] in every view (yours and ProjectileCam's preview); false = the game's own size. Default true.";
}
chosen[key] = config.Bind<bool>("Weapons", text, num, text2);
}
}
MarkerScreenSize = ((BasePlugin)this).Config.Bind<float>("Marker", "ScreenSize", 0.02f, "Size of the landing target on your screen, as a share of the screen height: it keeps that size near or far. 0.02 = 2 % (default); the game's spear target is about 5 % at 10 m. Advised: 0.005 to 0.1.");
MarkerMaxMetres = ((BasePlugin)this).Config.Bind<float>("Marker", "MaxMetres", 1f, "Largest size of the landing target on the ground, in metres, so a far target never hides what you aim at (the game's spear target is 0.5 m). Default 1. Advised: 0.2 to 5.");
LookupSeconds = ((BasePlugin)this).Config.Bind<float>("Performance", "LookupSeconds", 0.5f, "While the item in your hand shows no ranged weapon yet (just equipped, or not a ranged weapon), seconds between two new looks. Advised: 0.1 to 5.");
PathUpdateSeconds = ((BasePlugin)this).Config.Bind<float>("Performance", "PathUpdateSeconds", 0f, "While aiming, seconds between two path calculations. 0 = every frame, like the game's spear indicator (smoothest). Raise it (advised up to 0.1) if aiming costs too much on your PC; the line then follows your aim in small steps. Default 0.");
FullLogging = ((BasePlugin)this).Config.Bind<bool>("Debug", "FullLogging", false, "True = the BepInEx log gets every step useful to diagnose a problem (decisions, values read, object aimed at, failures with their cause). False = only loading, version and errors.");
ModLog.Init(Logger, FullLogging);
ClassInjector.RegisterTypeInIl2Cpp<AimWatcher>();
GameObject val = new GameObject("ProjectileAimIndicator");
Object.DontDestroyOnLoad((Object)(object)val);
((Object)val).hideFlags = (HideFlags)61;
AimWatcher watcher = val.AddComponent<AimWatcher>();
((BasePlugin)this).Config.SettingChanged += delegate
{
watcher.Refresh();
};
try
{
new Harmony("aznan.sotf.projectileaimindicator").PatchAll(typeof(ShotPatches).Assembly);
}
catch (Exception ex)
{
ManualLogSource logger = Logger;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(68, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Shot patches not installed, no shot is compared with the indicator: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
}
logger.LogError(val2);
}
try
{
_beforeCamera = Action<ScriptableRenderContext, Camera>.op_Implicit((Action<ScriptableRenderContext, Camera>)AimWatcher.BeforeCamera);
RenderPipelineManager.beginCameraRendering += _beforeCamera;
}
catch (Exception ex2)
{
ManualLogSource logger2 = Logger;
BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(82, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Per-camera target size not installed, the target is sized for your own view only: ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex2.Message);
}
logger2.LogError(val2);
}
ManualLogSource logger3 = Logger;
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(30, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("ProjectileAimIndicator ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>("0.2.20");
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" loaded");
}
logger3.LogInfo(val3);
}
}
}
namespace ProjectileAimIndicator.Patches
{
public static class ShotPatches
{
[HarmonyPatch(typeof(RangedWeapon), "Shoot", new Type[]
{
typeof(Vector3),
typeof(float),
typeof(int)
})]
public static class Shoot
{
private static void Prefix(RangedWeapon __instance, Vector3 direction, float zeroAngle)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
AimWatcher.Instance?.Fired(__instance, direction, zeroAngle);
}
}
[HarmonyPatch(typeof(ProjectileImpactObject), "Impact")]
public static class Impact
{
private static void Prefix(SurfaceImpactInfo surfaceImpactInfo)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
AimWatcher instance = AimWatcher.Instance;
if (instance != null)
{
Weapon weapon = surfaceImpactInfo.weapon;
RaycastHit rayHit = surfaceImpactInfo.rayHit;
instance.Landed(weapon, ((RaycastHit)(ref rayHit)).point);
}
}
}
}
}
namespace ProjectileAimIndicator.Logic
{
public enum WeaponKind
{
Other,
Bow,
Crossbow,
Slingshot,
FlareGun,
Spear,
Thrown,
RopeGun,
StunGun,
Firearm
}
public static class Decision
{
public static bool OnByDefault(WeaponKind kind)
{
if (kind != WeaponKind.Other && kind != WeaponKind.Firearm)
{
return kind != WeaponKind.StunGun;
}
return false;
}
public static bool GameDrawsOwn(WeaponKind kind)
{
if (kind != WeaponKind.Spear && kind != WeaponKind.Thrown)
{
return kind == WeaponKind.RopeGun;
}
return true;
}
public static bool ShouldShow(WeaponKind kind, bool chosen, bool midAttack, bool aiming)
{
if (chosen)
{
switch (kind)
{
case WeaponKind.Other:
break;
default:
return midAttack || aiming;
case WeaponKind.Bow:
return midAttack;
}
}
return false;
}
public static float MarkerScale(float distance, float fovDegrees, float screenShare, float maxMetres, float targetMetres)
{
float val = Math.Min(2f * distance * (float)Math.Tan((double)fovDegrees * Math.PI / 360.0) * screenShare, maxMetres);
if (!(targetMetres > 0f))
{
return 1f;
}
return Math.Max(val, 0f) / targetMetres;
}
public static void SelfCheck()
{
if (!OnByDefault(WeaponKind.Bow) || !OnByDefault(WeaponKind.FlareGun) || OnByDefault(WeaponKind.Other) || !OnByDefault(WeaponKind.RopeGun) || !OnByDefault(WeaponKind.Thrown) || OnByDefault(WeaponKind.Firearm) || OnByDefault(WeaponKind.StunGun) || !GameDrawsOwn(WeaponKind.RopeGun) || !GameDrawsOwn(WeaponKind.Spear) || GameDrawsOwn(WeaponKind.Bow) || GameDrawsOwn(WeaponKind.Firearm))
{
throw new InvalidOperationException("Decision defaults are wrong.");
}
if (ShouldShow(WeaponKind.Bow, chosen: true, midAttack: false, aiming: true) || !ShouldShow(WeaponKind.Bow, chosen: true, midAttack: true, aiming: false) || !ShouldShow(WeaponKind.Slingshot, chosen: true, midAttack: false, aiming: true) || ShouldShow(WeaponKind.Slingshot, chosen: false, midAttack: true, aiming: true) || ShouldShow(WeaponKind.Other, chosen: true, midAttack: true, aiming: true))
{
throw new InvalidOperationException("Decision rules are wrong.");
}
if (Math.Abs(MarkerScale(10f, 90f, 0.02f, 1f, 0.5f) - 0.8f) > 0.0001f || Math.Abs(MarkerScale(100f, 90f, 0.02f, 1f, 0.5f) - 2f) > 0.0001f || MarkerScale(10f, 90f, 0.02f, 1f, 0f) != 1f || MarkerScale(10f, 90f, -1f, 1f, 0.5f) != 0f)
{
throw new InvalidOperationException("Decision.MarkerScale is wrong.");
}
}
}
}