using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using GameNetcodeStuff;
using HarmonyLib;
using LethalMDK;
using ScanTweaks.World;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityMDK.Config;
using UnityMDK.Injection;
using UnityMDK.Logging;
using UnityMDK.Reflection;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("ScanTweaks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.2.1")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("ScanTweaks")]
[assembly: AssemblyTitle("ScanTweaks")]
[assembly: AssemblyVersion("1.2.1.0")]
namespace ScanTweaks
{
public static class Player
{
public static bool IsServerOrHost
{
get
{
if (!NetworkManager.Singleton.IsHost)
{
return NetworkManager.Singleton.IsServer;
}
return true;
}
}
}
public class BatteryTextUpdater : MonoBehaviour
{
private GrabbableObject _grabbableObject;
private ScanNodeProperties _scanNode;
private static readonly string NoBatteryMsg = "No Battery";
private static readonly string[] BatteryPercentMsg = new string[2] { "Battery: ", "%" };
private int _currentBattery = int.MaxValue;
private void Awake()
{
_grabbableObject = ((Component)this).GetComponentInParent<GrabbableObject>(true);
_scanNode = ((Component)this).GetComponent<ScanNodeProperties>();
}
private void Update()
{
if (!((Behaviour)_scanNode).enabled)
{
return;
}
if (_grabbableObject.insertedBattery == null)
{
_scanNode.subText = NoBatteryMsg;
return;
}
int num = ((!_grabbableObject.insertedBattery.empty) ? ((int)Math.Ceiling(Math.Clamp(_grabbableObject.insertedBattery.charge * 100f, 0f, 100f))) : 0);
if (_currentBattery != num)
{
_currentBattery = num;
_scanNode.subText = string.Join(num.ToString(), BatteryPercentMsg);
}
}
}
public class CustomScanNodeProperties : ScanNodeProperties
{
[ConfigSection("PingScan")]
[ConfigDescription("Adds a scan node to every item that didn't already have one.")]
public static ConfigData<bool> EnableScanNodeForTools = new ConfigData<bool>(true);
private void Awake()
{
GrabbableObject componentInParent = ((Component)this).GetComponentInParent<GrabbableObject>(true);
if ((Object)(object)componentInParent != (Object)null && componentInParent.itemProperties.requiresBattery)
{
((Component)this).gameObject.AddComponent<BatteryTextUpdater>();
}
}
}
[InjectToComponent(typeof(IngamePlayerSettings), false)]
public class PingScan : MonoBehaviour
{
[ConfigSection("PingScan")]
[ConfigDescription("Enable/Disable the ping scan tweaks")]
public static readonly ConfigData<bool> PingScanDoPatch = new ConfigData<bool>(true);
[ConfigDescription("The delay between each ping scan step. A larger value will make the scan take longer to reach great distances.")]
private static readonly ConfigData<float> PingScanStepDuration = new ConfigData<float>(0.01f);
[ConfigDescription("Should dynamic objects (e.g. doors) block the ping scan")]
private static readonly ConfigData<bool> DynamicObjectsBlockRaycast = new ConfigData<bool>(true);
[ConfigDescription("Allows scanning objects in the hands of the players")]
private static readonly ConfigData<bool> PlayerHeldItemsScannable = new ConfigData<bool>(false);
[SerializeField]
private float _range = 80f;
[SerializeField]
private float _outOfFrustumPaddingHorizontal = 0.2f;
private readonly List<Collider> _currentScannedColliders = new List<Collider>();
private readonly List<ScanNodeProperties> _currentScannedNodes = new List<ScanNodeProperties>();
private readonly List<int> _currentScannedValues = new List<int>();
private readonly List<GrabbableObject> _currentScannedGrabbables = new List<GrabbableObject>();
private readonly Collider[] _hitAlloc = (Collider[])(object)new Collider[30];
private static readonly int _physicsMask = LayerMasks.Room;
private static readonly int _doorMask = LayerMasks.InteractableObject;
private float _outOfFrustumPaddingVertical => _outOfFrustumPaddingHorizontal * ((float)Screen.width / (float)Screen.height);
public static int PingedScrapValue { get; private set; }
public static int NodeUtility => 0;
public static int NodeCreature => 1;
public static int NodeScrap => 2;
public static event Action<ScanNodeProperties> ScanNodeAdded;
public static event Action<ScanNodeProperties> ScanNodeRemoved;
public static event Action DoPing;
internal static void TriggerPingScan()
{
PingScan.DoPing?.Invoke();
}
private void Update()
{
PlayerControllerB localPlayer = Player.LocalPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer))
{
return;
}
if (localPlayer.inSpecialInteractAnimation && _currentScannedNodes.Count > 0)
{
RemoveAll();
}
float outOfFrustumPaddingHorizontal = _outOfFrustumPaddingHorizontal;
float outOfFrustumPaddingVertical = _outOfFrustumPaddingVertical;
for (int num = _currentScannedNodes.Count - 1; num >= 0; num--)
{
ScanNodeProperties scanNode = _currentScannedNodes[num];
Collider nodeCollider = _currentScannedColliders[num];
GrabbableObject val = _currentScannedGrabbables[num];
if (!ConfigData<bool>.op_Implicit(PlayerHeldItemsScannable) && Object.op_Implicit((Object)(object)val) && val.isHeld && !val.isHeldByEnemy)
{
RemoveScanNodeAt(num);
}
else if (!IsNodeVisible(scanNode, nodeCollider, localPlayer.gameplayCamera, outOfFrustumPaddingHorizontal, outOfFrustumPaddingVertical))
{
RemoveScanNodeAt(num);
}
}
}
private void OnEnable()
{
DoPing += OnPingScan;
}
private void OnDisable()
{
DoPing -= OnPingScan;
RemoveAll();
}
private void RemoveAll()
{
for (int num = _currentScannedNodes.Count - 1; num >= 0; num--)
{
RemoveScanNodeAt(num);
}
}
private void OnPingScan()
{
Camera gameplayCamera = Player.LocalPlayer.gameplayCamera;
((MonoBehaviour)this).StartCoroutine(Pinging(gameplayCamera));
}
private IEnumerator Pinging(Camera camera)
{
Transform transform = ((Component)camera).transform;
Vector3 currentTestPos = transform.position;
Vector3 direction = transform.forward;
Quaternion boxOrientation = Quaternion.LookRotation(direction);
Vector3 screenPos = Vector3.one;
Vector3 extents = Vector3.one;
float currentLength = 0f;
float nextStep = Time.time;
while (currentLength < _range)
{
yield return null;
for (; Time.time >= nextStep; nextStep += ConfigData<float>.op_Implicit(PingScanStepDuration))
{
UpdateExtents();
DoPing();
currentTestPos += direction * 0.5f;
currentLength += 0.5f;
}
}
void DoPing()
{
//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_0013: Unknown result type (might be due to invalid IL or missing references)
int num = Physics.OverlapBoxNonAlloc(currentTestPos, extents, _hitAlloc, boxOrientation, LayerMasks.ScanNode, (QueryTriggerInteraction)2);
ScanNodeProperties val2 = default(ScanNodeProperties);
for (int i = 0; i < num; i++)
{
Collider val = _hitAlloc[i];
if (((Component)val).TryGetComponent<ScanNodeProperties>(ref val2) && IsNodeVisible(val2, val, camera, 0f, 0f))
{
AddScanNode(val2);
}
}
}
void UpdateExtents()
{
//IL_0023: 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)
//IL_002d: 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_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
screenPos.z = currentLength;
Vector3 val3 = ((Component)camera).transform.InverseTransformPoint(camera.ViewportToWorldPoint(screenPos));
extents = val3;
extents.z = 0.25f;
}
}
private static bool PointOutOfViewport(float point, float padding)
{
if (!(point > 1f + padding))
{
return point < 0f - padding;
}
return true;
}
private static bool IsNodeVisible(ScanNodeProperties scanNode, Collider nodeCollider, Camera camera, float paddingX, float paddingY)
{
//IL_003c: 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_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: 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_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: 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)
//IL_008f: 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_00ac: 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_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: 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)
if ((Object)(object)scanNode == (Object)null)
{
return false;
}
if (!((Behaviour)scanNode).enabled)
{
return false;
}
if (scanNode is CustomScanNodeProperties && !ConfigData<bool>.op_Implicit(CustomScanNodeProperties.EnableScanNodeForTools))
{
return false;
}
if ((Object)(object)nodeCollider == (Object)null)
{
return false;
}
Vector3 position = ((Component)camera).transform.position;
Bounds bounds = nodeCollider.bounds;
Vector3 val = position - ((Bounds)(ref bounds)).center;
float magnitude = ((Vector3)(ref val)).magnitude;
if (magnitude < (float)scanNode.minRange)
{
return false;
}
if (magnitude > (float)scanNode.maxRange)
{
return false;
}
bounds = nodeCollider.bounds;
Vector3 val2 = camera.WorldToViewportPoint(((Bounds)(ref bounds)).center);
if (PointOutOfViewport(val2.x, paddingX) || PointOutOfViewport(val2.y, paddingY) || val2.z < 0f)
{
return false;
}
int num = _physicsMask;
if (ConfigData<bool>.op_Implicit(DynamicObjectsBlockRaycast))
{
num |= _doorMask;
}
if (scanNode.requiresLineOfSight)
{
bounds = nodeCollider.bounds;
return !Linecast(position, ((Bounds)(ref bounds)).center, num);
}
return true;
}
private static bool Linecast(Vector3 start, Vector3 end, int layerMask)
{
//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_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: 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_0041: 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_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: 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)
//IL_0032: 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 = end - start;
if (Math.Abs(val.y) > 0.1f)
{
end = ((!(val.y > 0f)) ? (end + Vector3.up * 0.1f) : (end - Vector3.up * 0.1f));
}
RaycastHit val2 = default(RaycastHit);
if (!Physics.Linecast(start, end, ref val2, layerMask, (QueryTriggerInteraction)2))
{
return false;
}
if (((Component)((RaycastHit)(ref val2)).collider).gameObject.CompareTag(Tags.InteractTrigger))
{
return Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref val2)).collider).GetComponent<AnimatedObjectTrigger>());
}
return true;
}
private void AttemptScanNewCreature(int creatureID)
{
Terminal val = default(Terminal);
if (creatureID >= 0 && Object.op_Implicit((Object)(object)HUDManager.Instance) && ReflectionUtility.TryGetField<Terminal>((object)HUDManager.Instance, "terminalScript", ref val) && !val.scannedEnemyIDs.Contains(creatureID))
{
HUDManager.Instance.ScanNewCreatureServerRpc(creatureID);
}
}
private void AddScanNode(ScanNodeProperties scanNodeProperties)
{
if (Object.op_Implicit((Object)(object)scanNodeProperties) && !_currentScannedNodes.Contains(scanNodeProperties))
{
GrabbableObject componentInParent = ((Component)scanNodeProperties).GetComponentInParent<GrabbableObject>();
if (ConfigData<bool>.op_Implicit(PlayerHeldItemsScannable) || !Object.op_Implicit((Object)(object)componentInParent) || !componentInParent.isHeld || componentInParent.isHeldByEnemy)
{
Collider component = ((Component)scanNodeProperties).GetComponent<Collider>();
component.enabled = false;
AttemptScanNewCreature(scanNodeProperties.creatureScanID);
_currentScannedValues.Add((scanNodeProperties.nodeType == NodeScrap) ? scanNodeProperties.scrapValue : 0);
_currentScannedColliders.Add(component);
_currentScannedNodes.Add(scanNodeProperties);
_currentScannedGrabbables.Add(componentInParent);
CalculateTotalValue();
PingScan.ScanNodeAdded?.Invoke(scanNodeProperties);
}
}
}
private void RemoveScanNodeAt(int index)
{
if (index >= 0 && index < _currentScannedNodes.Count)
{
Collider val = _currentScannedColliders[index];
if (Object.op_Implicit((Object)(object)val))
{
val.enabled = true;
}
_currentScannedValues.RemoveAt(index);
CalculateTotalValue();
PingScan.ScanNodeRemoved?.Invoke(_currentScannedNodes[index]);
_currentScannedColliders.RemoveAt(index);
_currentScannedNodes.RemoveAt(index);
_currentScannedGrabbables.RemoveAt(index);
}
}
private void CalculateTotalValue()
{
PingedScrapValue = 0;
foreach (int currentScannedValue in _currentScannedValues)
{
PingedScrapValue += currentScannedValue;
}
}
}
[Initializer(0)]
public class ScanNodeCreator : ComponentInjector<GrabbableObject>
{
private static readonly string[] excludes = new string[1] { "sticky note" };
[Initializer(0)]
private static void Init()
{
SceneInjection.AddComponentInjector<GrabbableObject>((ComponentInjector<GrabbableObject>)new ScanNodeCreator(), true);
}
protected override bool CanBeInjected(GrabbableObject component)
{
if (Object.op_Implicit((Object)(object)((Component)component).GetComponentInChildren<ScanNodeProperties>(true)))
{
return false;
}
if (component is RagdollGrabbableObject)
{
return false;
}
if (!Object.op_Implicit((Object)(object)component.itemProperties))
{
return false;
}
if (string.IsNullOrEmpty(component.itemProperties.itemName))
{
return true;
}
string[] array = excludes;
foreach (string value in array)
{
if (component.itemProperties.itemName.Equals(value, StringComparison.InvariantCultureIgnoreCase))
{
return false;
}
}
return true;
}
protected override void Inject(GrabbableObject component)
{
//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_0028: 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_003a: 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_0049: 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_0059: Unknown result type (might be due to invalid IL or missing references)
Transform transform = ((Component)component).transform;
bool isScrap = component.itemProperties.isScrap;
GameObject val = new GameObject("Scan Node")
{
layer = Layers.ScanNode
};
val.transform.SetParent(transform);
val.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity);
val.AddComponent<BoxCollider>().size = Vector3.one * 0.2f;
CustomScanNodeProperties customScanNodeProperties = val.AddComponent<CustomScanNodeProperties>();
((ScanNodeProperties)customScanNodeProperties).headerText = component.itemProperties.itemName;
((ScanNodeProperties)customScanNodeProperties).subText = (isScrap ? $"Value: ${component.scrapValue}" : "???");
((ScanNodeProperties)customScanNodeProperties).minRange = 1;
((ScanNodeProperties)customScanNodeProperties).maxRange = 13;
((ScanNodeProperties)customScanNodeProperties).creatureScanID = -1;
((ScanNodeProperties)customScanNodeProperties).nodeType = (isScrap ? PingScan.NodeScrap : PingScan.NodeUtility);
((ScanNodeProperties)customScanNodeProperties).requiresLineOfSight = true;
}
}
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("Saradora.ScanTweaks", "Scan Tweaks", "1.7.0")]
public class PluginInitializer : BaseUnityPlugin
{
private readonly Harmony _harmonyInstance = new Harmony("Saradora.ScanTweaks");
private void Awake()
{
ConfigBinder.BindAll(((BaseUnityPlugin)this).Config);
_harmonyInstance.PatchAll();
}
}
public static class ScanTweaks
{
public const string ModGuid = "Saradora.ScanTweaks";
public const string ModVersion = "1.7.0";
public const string ModName = "Scan Tweaks";
}
}
namespace ScanTweaks.World
{
public class ApparaticeScrapValue : MonoBehaviour
{
[ConfigDescription("Minimum possible scrap value of the apparatice. This value has a x0.4 multiplier")]
private static readonly ConfigData<int> ApparaticeMinValue = new ConfigData<int>(125);
[ConfigDescription("Maximum possible scrap value of the apparatice. This value has a x0.4 multiplier")]
private static readonly ConfigData<int> ApparaticeMaxValue = new ConfigData<int>(350);
private LungProp _lungProp;
public static readonly List<LungProp> PatchedApparatices = new List<LungProp>();
[ConfigSection("Apparatice")]
[ConfigDescription("Make the apparatice have a random scrap value, also fixes the \"???\" on the scan node, Host-only")]
public static ConfigData<bool> ApparaticeMakeRandomValue { get; } = new ConfigData<bool>(true);
private void Awake()
{
_lungProp = ((Component)this).GetComponent<LungProp>();
}
private static bool IsLungPropValid(LungProp lungProp)
{
if (!lungProp.isLungDocked || !lungProp.isLungPowered)
{
return false;
}
return ((GrabbableObject)lungProp).isInFactory;
}
private IEnumerator Start()
{
yield return (object)new WaitForSeconds(5f);
if (IsLungPropValid(_lungProp) && ConfigData<bool>.op_Implicit(ApparaticeMakeRandomValue) && Player.IsServerOrHost)
{
int num = ConfigData<int>.op_Implicit(ApparaticeMinValue);
int num2 = ConfigData<int>.op_Implicit(ApparaticeMaxValue);
if (num > num2)
{
int num3 = num2;
num2 = num;
num = num3;
}
int scrapValue = (int)((float)RoundManager.Instance.AnomalyRandom.Next(num, num2) * RoundManager.Instance.scrapValueMultiplier);
((GrabbableObject)_lungProp).SetScrapValue(scrapValue);
PatchedApparatices.Add(_lungProp);
}
}
}
[InjectToPrefab("LungApparatus")]
public class ApparatusScrapValueInjector : IPrefabInjector
{
public void OnInject(GameObject obj)
{
if (ConfigData<bool>.op_Implicit(ApparaticeScrapValue.ApparaticeMakeRandomValue))
{
LungProp componentInChildren = obj.GetComponentInChildren<LungProp>();
if ((Object)(object)componentInChildren == (Object)null)
{
Log.Error((object)"Couldn't find apparatus on prefab.");
}
else
{
((Component)componentInChildren).gameObject.AddComponent<ApparaticeScrapValue>();
}
}
}
}
[InjectToPrefab("BreakerBox")]
public class BreakerBoxPatcher : IPrefabInjector
{
public void OnInject(GameObject obj)
{
BreakerBox componentInChildren = obj.GetComponentInChildren<BreakerBox>();
if ((Object)(object)componentInChildren == (Object)null)
{
Log.Error((object)"Couldn't patch breaker box");
}
else
{
((Component)componentInChildren).gameObject.AddComponent<BreakerBoxScanNode>();
}
}
}
public class BreakerBoxScanNode : MonoBehaviour
{
[ConfigSection("BreakerBox")]
[ConfigDescription("Adds a scan node to the breaker box")]
private static readonly ConfigData<bool> _breakerBoxScanNode = new ConfigData<bool>(true);
[ConfigDescription("Minimum range of the scan node")]
private static readonly ConfigData<int> _breakerBoxMinRange = new ConfigData<int>(3);
[ConfigDescription("Maximum range of the scan node")]
private static readonly ConfigData<int> _breakerBoxMaxRange = new ConfigData<int>(13);
private static readonly Vector3 Offset = new Vector3(-1f, -0.8f, -1.2f);
private ScanNodeProperties _scanNode;
private void Start()
{
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected O, but got Unknown
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: 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)
_breakerBoxScanNode.ConfigChanged += OnNodeActiveStateChanged;
_breakerBoxMinRange.ConfigChanged += OnMinRangeChanged;
_breakerBoxMaxRange.ConfigChanged += OnMaxRangeChanged;
_scanNode = ((Component)this).GetComponentInChildren<ScanNodeProperties>(true);
if (!Object.op_Implicit((Object)(object)_scanNode))
{
GameObject val = new GameObject("Scan Node")
{
layer = Layers.ScanNode
};
val.AddComponent<BoxCollider>().size = Vector3.one * 0.2f;
_scanNode = val.AddComponent<ScanNodeProperties>();
_scanNode.headerText = "Breaker Box";
_scanNode.subText = "Flip the switches! Maybe it'll do something?";
_scanNode.minRange = ConfigData<int>.op_Implicit(_breakerBoxMinRange);
_scanNode.maxRange = ConfigData<int>.op_Implicit(_breakerBoxMaxRange);
_scanNode.creatureScanID = -1;
_scanNode.nodeType = 0;
_scanNode.requiresLineOfSight = true;
val.transform.SetParent(((Component)this).transform);
val.transform.SetLocalPositionAndRotation(Offset, Quaternion.identity);
}
((Behaviour)_scanNode).enabled = ConfigData<bool>.op_Implicit(_breakerBoxScanNode);
}
private void OnNodeActiveStateChanged(bool value)
{
if (Object.op_Implicit((Object)(object)_scanNode))
{
((Behaviour)_scanNode).enabled = value;
}
}
private void OnMinRangeChanged(int value)
{
if (Object.op_Implicit((Object)(object)_scanNode))
{
_scanNode.minRange = value;
}
}
private void OnMaxRangeChanged(int value)
{
if (Object.op_Implicit((Object)(object)_scanNode))
{
_scanNode.maxRange = value;
}
}
private void OnDestroy()
{
_breakerBoxScanNode.ConfigChanged -= OnNodeActiveStateChanged;
_breakerBoxMinRange.ConfigChanged -= OnMinRangeChanged;
_breakerBoxMaxRange.ConfigChanged -= OnMaxRangeChanged;
}
}
[InjectToComponent(typeof(StartOfRound), false)]
public class RadarIcons : MonoBehaviour
{
[ConfigSection("Radar")]
[ConfigDescription("Fixes the item radar so that item icons properly disappear when the item itself is destroyed (e.g. when a player is eaten).")]
public static readonly ConfigData<bool> RadarPatchRadarIcons = new ConfigData<bool>(true);
private static readonly ConfigData<bool> ShouldScrapsInShipBeVisible = new ConfigData<bool>(false);
private static List<(GrabbableObject, MeshRenderer)> _radarIconList = new List<(GrabbableObject, MeshRenderer)>();
private static readonly Vector3 Offset = Vector3.up * 0.5f;
private void Update()
{
//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
for (int num = _radarIconList.Count - 1; num >= 0; num--)
{
var (val, val2) = _radarIconList[num];
if ((Object)(object)val == (Object)null)
{
if (Object.op_Implicit((Object)(object)val2))
{
Object.Destroy((Object)(object)((Component)val2).gameObject);
}
_radarIconList.RemoveAt(num);
}
else if ((Object)(object)val2 == (Object)null)
{
_radarIconList.RemoveAt(num);
}
else
{
bool flag = !ConfigData<bool>.op_Implicit(ShouldScrapsInShipBeVisible) && val.isInShipRoom;
if (((Renderer)val2).enabled = ((Component)val).gameObject.activeInHierarchy && !val.deactivated && (val.isHeld || !flag))
{
((Component)val2).transform.position = ((Component)val).transform.position + Offset;
}
}
}
}
public static void AddRadarIcon(GrabbableObject grabbableObject, MeshRenderer radarIcon)
{
if (Object.op_Implicit((Object)(object)grabbableObject) && Object.op_Implicit((Object)(object)radarIcon))
{
_radarIconList.Add((grabbableObject, radarIcon));
}
}
}
}
namespace ScanTweaks.UI
{
[InjectToComponent(typeof(HUDManager), false)]
public class PingScanUI : MonoBehaviour
{
private struct ScannedObject
{
public float distance;
public UIElement element;
public ScannedObject(float distance, UIElement element)
{
this.distance = distance;
this.element = element;
}
}
private class ScannedObjectComparer : IComparer<ScannedObject>
{
public int Compare(ScannedObject x, ScannedObject y)
{
if (x.distance > y.distance)
{
return -1;
}
return 1;
}
}
private struct UIElement
{
public RectTransform transform;
public TextMeshProUGUI mainText;
public TextMeshProUGUI subText;
public override int GetHashCode()
{
return ((object)transform).GetHashCode();
}
public override bool Equals(object obj)
{
Transform val = (Transform)((obj is Transform) ? obj : null);
if (val != null)
{
return (Object)(object)transform == (Object)(object)val;
}
return ((object)transform).Equals(obj);
}
}
[ConfigSection("PingScan")]
[ConfigDescription("The speed at which the scrap counter updates.")]
private static ConfigData<int> ScrapCounterUpdateSpeed = new ConfigData<int>(1000);
[SerializeField]
private float _counterInterval = 0.03f;
private float _nextCounterUpdate;
private HUDManager _hudManager;
private Canvas _canvas;
private RectTransform _canvasTransform;
private RectTransform _nodeContainer;
private Queue<UIElement> _uiElementsPool = new Queue<UIElement>();
private Dictionary<ScanNodeProperties, UIElement> _currentScanNodes = new Dictionary<ScanNodeProperties, UIElement>();
private static readonly int AColorNumber = Animator.StringToHash("colorNumber");
private static readonly int ADisplayBool = Animator.StringToHash("display");
private static readonly string DollarSign = "$";
private int _currentScrapValue;
private readonly List<ScannedObject> _scannedObjects = new List<ScannedObject>();
private readonly List<ScanNodeProperties> _toDelete = new List<ScanNodeProperties>();
private readonly ScannedObjectComparer _distanceComparer = new ScannedObjectComparer();
private void Awake()
{
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Expected O, but got Unknown
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_005d: Expected O, but got Unknown
_hudManager = ((Component)this).GetComponent<HUDManager>();
_canvas = ((Component)_hudManager.scanElements[0]).GetComponentInParent<Canvas>(true);
_canvasTransform = (RectTransform)((Component)_canvas).transform;
_nodeContainer = (RectTransform)((Component)((Transform)_hudManager.scanElements[0]).parent).transform;
for (int i = 1; i < _hudManager.scanElements.Length; i++)
{
_uiElementsPool.Enqueue(GetUIElementFromRectTransform(_hudManager.scanElements[i]));
}
}
private void OnEnable()
{
PingScan.ScanNodeAdded += OnScanNodeAdded;
PingScan.ScanNodeRemoved += OnScanNodeRemoved;
}
private void OnDisable()
{
PingScan.ScanNodeAdded -= OnScanNodeAdded;
PingScan.ScanNodeRemoved -= OnScanNodeRemoved;
}
private void LateUpdate()
{
UpdateNodeContainer();
UpdateScanNodes();
UpdateScrapValueCounter();
}
private void UpdateNodeContainer()
{
//IL_0006: 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)
_nodeContainer.sizeDelta = Vector2.zero;
((Transform)_nodeContainer).localPosition = Vector3.zero;
}
private void UpdateScanNodes()
{
//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_003e: 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_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d5: 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_00f8: Unknown result type (might be due to invalid IL or missing references)
//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: 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_0108: 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_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Unknown result type (might be due to invalid IL or missing references)
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Unknown result type (might be due to invalid IL or missing references)
PlayerControllerB localPlayer = Player.LocalPlayer;
if (!Object.op_Implicit((Object)(object)localPlayer))
{
return;
}
Camera gameplayCamera = localPlayer.gameplayCamera;
Vector3 position = ((Component)gameplayCamera).transform.position;
_toDelete.Clear();
_scannedObjects.Clear();
Vector2 sizeDelta = _canvasTransform.sizeDelta;
Vector2 val = Vector2.one * 0.5f;
foreach (var (val3, element) in _currentScanNodes)
{
if (!Object.op_Implicit((Object)(object)val3))
{
_toDelete.Add(val3);
continue;
}
((TMP_Text)element.mainText).text = val3.headerText;
((TMP_Text)element.subText).text = val3.subText;
Vector3 position2 = ((Component)val3).transform.position;
float distance = Vector3.SqrMagnitude(position2 - position);
_scannedObjects.Add(new ScannedObject(distance, element));
Vector3 val4 = gameplayCamera.WorldToViewportPoint(position2);
val4 = Vector2.op_Implicit((Vector2.op_Implicit(val4) - val) * sizeDelta);
((Transform)element.transform).localPosition = val4;
}
_scannedObjects.Sort(_distanceComparer);
foreach (ScanNodeProperties item in _toDelete)
{
OnScanNodeRemoved(item);
}
int count = _scannedObjects.Count;
for (int i = 0; i < count; i++)
{
((Transform)_scannedObjects[i].element.transform).SetSiblingIndex(i);
}
}
private void UpdateScrapValueCounter()
{
if (PingScan.PingedScrapValue != _currentScrapValue && !(Time.time < _nextCounterUpdate))
{
_nextCounterUpdate = Time.time + _counterInterval;
if (!_hudManager.scanInfoAnimator.GetBool(ADisplayBool))
{
_hudManager.scanInfoAnimator.SetBool(ADisplayBool, true);
}
if (_currentScrapValue < PingScan.PingedScrapValue)
{
float num = ConfigData<int>.op_Implicit(ScrapCounterUpdateSpeed);
int val = Math.Abs(PingScan.PingedScrapValue - _currentScrapValue);
val = Math.Max(100, val);
num *= (float)val * 0.01f;
_currentScrapValue = Mathf.RoundToInt(Mathf.MoveTowards((float)_currentScrapValue, (float)PingScan.PingedScrapValue, num * Time.deltaTime));
_hudManager.UIAudio.PlayOneShot(_hudManager.addToScrapTotalSFX);
}
else
{
_currentScrapValue = PingScan.PingedScrapValue;
}
((TMP_Text)_hudManager.totalValueText).text = DollarSign + _currentScrapValue;
if (_currentScrapValue == 0)
{
_hudManager.scanInfoAnimator.SetBool(ADisplayBool, false);
}
else if (PingScan.PingedScrapValue == _currentScrapValue)
{
_hudManager.UIAudio.PlayOneShot(_hudManager.finishAddingToTotalSFX);
}
}
}
private UIElement GetUIElementFromRectTransform(RectTransform instance)
{
TextMeshProUGUI[] componentsInChildren = ((Component)((Component)instance).transform).GetComponentsInChildren<TextMeshProUGUI>(true);
UIElement result = default(UIElement);
result.transform = instance;
result.mainText = componentsInChildren[0];
result.subText = componentsInChildren[1];
return result;
}
private UIElement GetFreeUIElement()
{
if (_uiElementsPool.Count > 0)
{
return _uiElementsPool.Dequeue();
}
RectTransform instance = Object.Instantiate<RectTransform>(_hudManager.scanElements[0], ((Component)_hudManager.scanElements[0]).transform.parent);
return GetUIElementFromRectTransform(instance);
}
private void OnScanNodeAdded(ScanNodeProperties scanNode)
{
if (!_currentScanNodes.ContainsKey(scanNode))
{
UIElement freeUIElement = GetFreeUIElement();
((Component)freeUIElement.transform).gameObject.SetActive(true);
((TMP_Text)freeUIElement.mainText).text = scanNode.headerText;
((TMP_Text)freeUIElement.subText).text = scanNode.subText;
((Component)freeUIElement.transform).GetComponent<Animator>().SetInteger(AColorNumber, scanNode.nodeType);
_currentScanNodes.Add(scanNode, freeUIElement);
}
}
private void OnScanNodeRemoved(ScanNodeProperties scanNode)
{
if (_currentScanNodes.ContainsKey(scanNode))
{
UIElement item = _currentScanNodes[scanNode];
((Component)item.transform).gameObject.SetActive(false);
_currentScanNodes.Remove(scanNode);
_uiElementsPool.Enqueue(item);
}
}
}
}
namespace ScanTweaks.Patches
{
[HarmonyPatch(typeof(GrabbableObject))]
internal static class GrabbableObject_Patching
{
[HarmonyPatch("Start")]
[HarmonyPostfix]
private static void Start_PostFix(GrabbableObject __instance)
{
if (ConfigData<bool>.op_Implicit(RadarIcons.RadarPatchRadarIcons))
{
PatchRadarIcon(__instance);
}
PatchPropColliders(__instance);
}
private static void PatchRadarIcon(GrabbableObject grabbableObject)
{
if (Object.op_Implicit((Object)(object)grabbableObject.radarIcon) && !(grabbableObject is RagdollGrabbableObject))
{
RadarIcons.AddRadarIcon(grabbableObject, ((Component)grabbableObject.radarIcon).GetComponent<MeshRenderer>());
((Component)grabbableObject.radarIcon).transform.SetParent(((Component)StartOfRound.Instance).transform);
grabbableObject.radarIcon = null;
}
}
private static void PatchPropColliders(GrabbableObject grabbableObject)
{
List<Collider> list = new List<Collider>();
Collider[] propColliders = grabbableObject.propColliders;
foreach (Collider val in propColliders)
{
if (((Component)val).gameObject.layer != Layers.ScanNode)
{
list.Add(val);
}
}
grabbableObject.propColliders = list.ToArray();
}
}
[HarmonyPatch(typeof(HUDManager))]
internal static class HUDManager_Patching
{
private static bool _insideUpdate;
[HarmonyPatch("CanPlayerScan")]
[HarmonyPrefix]
private static bool CanPlayerScan_Prefix(ref bool __result)
{
if (!ConfigData<bool>.op_Implicit(PingScan.PingScanDoPatch))
{
return true;
}
if (!_insideUpdate)
{
return true;
}
__result = false;
return false;
}
[HarmonyPatch("PingScan_performed")]
[HarmonyPostfix]
private static void PingScan_performed_Postfix(HUDManager __instance)
{
if (!((Object)(object)Player.LocalPlayer == (Object)null) && !(ReflectionUtility.GetField<float>((object)__instance, "playerPingingScan") < 0.3f))
{
PingScan.TriggerPingScan();
}
}
[HarmonyPatch("Update")]
[HarmonyPrefix]
[HarmonyPriority(0)]
private static void Update_Prefix()
{
_insideUpdate = true;
}
[HarmonyPatch("Update")]
[HarmonyPostfix]
[HarmonyPriority(800)]
private static void Update_Postfix()
{
_insideUpdate = false;
}
}
[HarmonyPatch(typeof(RoundManager))]
public static class RoundManager_Patching
{
[HarmonyPatch("waitForScrapToSpawnToSync")]
[HarmonyPrefix]
private static void waitForScrapToSpawnToSync_Prefix()
{
ApparaticeScrapValue.PatchedApparatices.Clear();
}
[HarmonyPatch("SyncScrapValuesClientRpc")]
[HarmonyPrefix]
private static void SyncScrapValuesClientRpc_Prefix(ref NetworkObjectReference[] spawnedScrap, ref int[] allScrapValue)
{
//IL_003c: 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_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
if (!Player.IsServerOrHost)
{
return;
}
List<NetworkObjectReference> list = spawnedScrap.ToList();
List<int> list2 = allScrapValue.ToList();
foreach (LungProp patchedApparatice in ApparaticeScrapValue.PatchedApparatices)
{
if (!((Object)(object)patchedApparatice == (Object)null))
{
NetworkObjectReference item = NetworkObjectReference.op_Implicit(((NetworkBehaviour)patchedApparatice).NetworkObject);
if (!list.Contains(item))
{
list.Add(item);
list2.Add(((GrabbableObject)patchedApparatice).scrapValue);
}
}
}
spawnedScrap = list.ToArray();
allScrapValue = list2.ToArray();
}
}
[HarmonyPatch(typeof(StartOfRound))]
public static class StartOfRound_Patching
{
[ConfigSection("Patches")]
[ConfigDescription("Patches the loot not being properly registered as inside the ship when joining a game as client.")]
public static readonly ConfigData<bool> PatchLootInShip = new ConfigData<bool>(true);
[HarmonyPatch("SyncAlreadyHeldObjectsServerRpc")]
[HarmonyPrefix]
private static void SyncAlreadyHeldObjectsServerRpc_Prefix(int joiningClientId)
{
if ((int)NetworkManager.Singleton.LocalClientId != joiningClientId)
{
return;
}
try
{
GameObject val = GameObject.Find("/Environment/HangarShip");
((MonoBehaviour)val.GetComponent<ElevatorAnimationEvents>()).StartCoroutine(WaitForSyncItems(val));
}
catch (Exception ex)
{
Debug.LogException(ex);
}
}
private static IEnumerator WaitForSyncItems(GameObject shipObject)
{
yield return (object)new WaitForSeconds(2f);
if (!ConfigData<bool>.op_Implicit(PatchLootInShip))
{
yield break;
}
GrabbableObject[] componentsInChildren = shipObject.GetComponentsInChildren<GrabbableObject>();
foreach (GrabbableObject val in componentsInChildren)
{
if (!val.isInShipRoom)
{
val.scrapPersistedThroughRounds = true;
GameNetworkManager.Instance.localPlayerController.SetItemInElevator(true, true, val);
}
}
}
}
}