Decompiled source of KerfusCompanion v1.0.0

KerfusCompanion.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using OtherLoader;
using Packer.LootCompanion;
using UnityEngine;
using UnityEngine.AI;
using UnityEngine.UI;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
public class DigitalClock : MonoBehaviour
{
	private Text textClock;

	private void Awake()
	{
		textClock = ((Component)this).GetComponent<Text>();
	}

	private void Update()
	{
		DateTime now = DateTime.Now;
		string text = LeadingZero(now.Hour);
		string text2 = LeadingZero(now.Minute);
		string text3 = LeadingZero(now.Second);
		textClock.text = text + ":" + text2 + ":" + text3;
	}

	private string LeadingZero(int n)
	{
		return n.ToString().PadLeft(2, '0');
	}
}
public class RandomPhoneRing : MonoBehaviour
{
	[Header("Phone Behavior")]
	public AudioSource audioSource;

	public List<AudioClip> ringClips;

	public List<AudioClip> speechClips;

	public AudioClip phoneTone;

	public float minRingInterval = 5f;

	public float maxRingInterval = 15f;

	public float ringDuration = 10f;

	public float speechStartDelay = 2f;

	public float ringCooldown = 20f;

	[Header("Blinking Light")]
	public GameObject lightObject;

	public float lightBlinkInterval = 0.5f;

	private bool isRinging = false;

	private bool isHeld = false;

	private bool isCooldown = false;

	private Coroutine ringCoroutine;

	private Coroutine blinkCoroutine;

	private void Start()
	{
		StartRandomRinging();
	}

	private void Update()
	{
		FVRPhysicalObject component = ((Component)this).GetComponent<FVRPhysicalObject>();
		if (!((Object)(object)component != (Object)null))
		{
			return;
		}
		bool flag = ((FVRInteractiveObject)component).IsHeld;
		if (flag != isHeld)
		{
			isHeld = flag;
			if (isHeld)
			{
				HandlePickup();
			}
			else
			{
				HandlePutDown();
			}
		}
	}

	private void HandlePickup()
	{
		if (isRinging)
		{
			StopRinging();
			((MonoBehaviour)this).StartCoroutine(PlaySpeechAfterDelay(speechStartDelay));
		}
		else if (!isRinging && (Object)(object)phoneTone != (Object)null)
		{
			PlayPhoneTone();
		}
	}

	private void HandlePutDown()
	{
		StopAudio();
		if (!isCooldown)
		{
			((MonoBehaviour)this).StartCoroutine(CooldownBeforeNextRing());
		}
	}

	private void StartRandomRinging()
	{
		if (ringCoroutine == null)
		{
			ringCoroutine = ((MonoBehaviour)this).StartCoroutine(RandomRingRoutine());
		}
	}

	private void StopRinging()
	{
		if (audioSource.isPlaying && isRinging)
		{
			audioSource.Stop();
		}
		if (blinkCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(blinkCoroutine);
			blinkCoroutine = null;
		}
		if ((Object)(object)lightObject != (Object)null)
		{
			lightObject.SetActive(false);
		}
		isRinging = false;
	}

	private IEnumerator RandomRingRoutine()
	{
		while (true)
		{
			float interval = Random.Range(minRingInterval, maxRingInterval);
			yield return (object)new WaitForSeconds(interval);
			if (!isHeld && !isCooldown && ringClips.Count > 0)
			{
				isRinging = true;
				audioSource.clip = ringClips[Random.Range(0, ringClips.Count)];
				audioSource.loop = true;
				audioSource.Play();
				if (blinkCoroutine == null)
				{
					blinkCoroutine = ((MonoBehaviour)this).StartCoroutine(BlinkLightRoutine());
				}
				yield return (object)new WaitForSeconds(ringDuration);
				if (isRinging)
				{
					StopRinging();
				}
				if (!isHeld)
				{
					((MonoBehaviour)this).StartCoroutine(CooldownBeforeNextRing());
				}
			}
		}
	}

	private IEnumerator BlinkLightRoutine()
	{
		while (true)
		{
			if ((Object)(object)lightObject != (Object)null)
			{
				lightObject.SetActive(!lightObject.activeSelf);
			}
			yield return (object)new WaitForSeconds(lightBlinkInterval);
		}
	}

	private IEnumerator PlaySpeechAfterDelay(float delay)
	{
		yield return (object)new WaitForSeconds(delay);
		if (isHeld && speechClips.Count > 0)
		{
			audioSource.loop = false;
			audioSource.clip = speechClips[Random.Range(0, speechClips.Count)];
			audioSource.Play();
		}
		((MonoBehaviour)this).StartCoroutine(CooldownBeforeNextRing());
	}

	private void PlayPhoneTone()
	{
		if ((Object)(object)phoneTone != (Object)null && !audioSource.isPlaying)
		{
			audioSource.loop = true;
			audioSource.clip = phoneTone;
			audioSource.Play();
		}
	}

	private void StopAudio()
	{
		if (audioSource.isPlaying)
		{
			audioSource.Stop();
		}
	}

	private IEnumerator CooldownBeforeNextRing()
	{
		isCooldown = true;
		yield return (object)new WaitForSeconds(ringCooldown);
		isCooldown = false;
		StartRandomRinging();
	}
}
public class PlateRackToggle : SteelPopTarget
{
	public List<HingeJoint> hingeJointsToToggle;

	public override void Start()
	{
		((SteelPopTarget)this).Start();
		bool useSpring = base.SpringSwitchJoint.useSpring;
		UpdateHingeJointsSpring(useSpring);
	}

	private void Update()
	{
		bool useSpring = base.SpringSwitchJoint.useSpring;
		UpdateHingeJointsSpring(useSpring);
	}

	private void UpdateHingeJointsSpring(bool springEnabled)
	{
		foreach (HingeJoint item in hingeJointsToToggle)
		{
			item.useSpring = springEnabled;
		}
	}
}
public class CombatCompanion : FVRInteractiveObject
{
	public enum CompanionModeEnum
	{
		LootCompanion,
		CombatHelper
	}

	public enum AnimationTypeEnum
	{
		Rotation,
		Translation
	}

	public enum AxisEnum
	{
		X,
		Y,
		Z
	}

	[Header("Mode Configuration")]
	public CompanionModeEnum mode = CompanionModeEnum.LootCompanion;

	[Header("Interactive Geometry Config")]
	[Tooltip("The moving transform representing the physical switch or button")]
	public Transform ButtonGeo;

	[Tooltip("Choose whether the button rotates or slides/depresses")]
	public AnimationTypeEnum AnimationType = AnimationTypeEnum.Rotation;

	[Tooltip("The local axis along which the transformation occurs")]
	public AxisEnum TargetAxis = AxisEnum.Z;

	[Tooltip("Speed of the animation transition (use larger numbers for rotation)")]
	public float AnimationSpeed = 800f;

	[Tooltip("The value on the targeted axis when the state is OFF (Degrees for Rotation, Local Units for Translation)")]
	public float OffValue = 0f;

	[Tooltip("The value on the targeted axis when the state is ON (Degrees for Rotation, Local Units for Translation)")]
	public float OnValue = 90f;

	[Header("Toggle Audio Events")]
	public AudioEvent AudEvent_ToggleOn;

	public AudioEvent AudEvent_ToggleOff;

	[Header("Combat Sensory Range")]
	[Tooltip("Maximum range to detect and target enemies")]
	public float maxCombatRange = 40f;

	[Tooltip("Field of View angle for enemy detection")]
	public float maxCombatFOV = 120f;

	[Tooltip("Layer mask used for line of sight occlusion checks")]
	public LayerMask visualOcclusionMask;

	[Header("Tactical Combat Movement")]
	[Tooltip("The distance the companion tries to maintain from the enemy. It will stop moving closer once inside this range.")]
	public float combatStandoffDistance = 5f;

	[Tooltip("How fast the companion physically rotates its body to face the enemy")]
	public float bodyRotationSpeed = 8f;

	[Header("Combat Animations")]
	[Tooltip("Custom combat idle animation. Falls back to standard Idle if empty.")]
	public string animCombatIdle = "CombatIdle";

	[Tooltip("Custom combat wait animation. Falls back to standard Wait if empty.")]
	public string animCombatWait = "CombatWait";

	[Tooltip("Custom combat run animation. Falls back to standard Run if empty.")]
	public string animCombatRun = "CombatRun";

	[Header("Aggression Scaling")]
	[Range(0f, 1f)]
	public float currentThreat = 0f;

	[Tooltip("Slowest shoot delay (in seconds) when calm")]
	public float maxShootDelay = 2f;

	[Tooltip("Fastest shoot delay (in seconds) under heavy threat")]
	public float minShootDelay = 0.15f;

	[Header("Developer Debugging")]
	[Tooltip("Check this to output state changes, targeting changes, and firing logs to your BepInEx console")]
	public bool enableDebugLogs = false;

	[Tooltip("Draws a visual sight cone and targeting laser in the Unity Editor scene view")]
	public bool drawDebugGizmos = true;

	private LootCompanion lootComp;

	private NavMeshAgent agent;

	private AIEntity selfAIEntity;

	private AIEntity targetEntity;

	private float nextShootTime = 0f;

	private float suppressionThreatSpike = 0f;

	private Vector3 m_defaultLocalPos;

	private Vector3 m_defaultLocalRot;

	private float m_curValue;

	private float m_tarValue;

	private bool m_isOn;

	public override void Awake()
	{
		//IL_0020: 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_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)
		((FVRInteractiveObject)this).Awake();
		if ((Object)(object)ButtonGeo != (Object)null)
		{
			m_defaultLocalPos = ButtonGeo.localPosition;
			m_defaultLocalRot = ButtonGeo.localEulerAngles;
		}
		m_curValue = OffValue;
		m_tarValue = OffValue;
	}

	public override void Start()
	{
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_0054: Expected O, but got Unknown
		((FVRInteractiveObject)this).Start();
		lootComp = ((Component)this).GetComponentInParent<LootCompanion>();
		agent = ((Component)this).GetComponentInParent<NavMeshAgent>();
		selfAIEntity = ((Component)this).GetComponentInParent<AIEntity>();
		if ((Object)(object)selfAIEntity != (Object)null)
		{
			selfAIEntity.AIReceiveSuppressionEvent += new AIReceiveSuppression(OnSuppressionReceived);
		}
		if (enableDebugLogs)
		{
			Debug.Log((object)("[CombatCompanion] Initialization completed on companion: " + ((Object)((Component)this).gameObject).name));
		}
	}

	public override void OnDestroy()
	{
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Expected O, but got Unknown
		((FVRInteractiveObject)this).OnDestroy();
		if ((Object)(object)selfAIEntity != (Object)null)
		{
			selfAIEntity.AIReceiveSuppressionEvent -= new AIReceiveSuppression(OnSuppressionReceived);
		}
	}

	private void OnSuppressionReceived(Vector3 pos, Vector3 dir, int iffcode, float intensity, float range)
	{
		suppressionThreatSpike = Mathf.Clamp01(suppressionThreatSpike + intensity * 0.25f);
		if (enableDebugLogs)
		{
			Debug.Log((object)("[CombatCompanion] Suppression received! Intensity: " + intensity + ". Current Spike: " + suppressionThreatSpike));
		}
	}

	public override void SimpleInteraction(FVRViveHand hand)
	{
		((FVRInteractiveObject)this).SimpleInteraction(hand);
		ToggleButtonState();
	}

	private void ToggleButtonState()
	{
		if (m_isOn)
		{
			SetStateOff();
		}
		else
		{
			SetStateOn();
		}
	}

	private void SetStateOn()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		if (!m_isOn)
		{
			m_isOn = true;
			m_tarValue = OnValue;
			mode = CompanionModeEnum.CombatHelper;
			if (enableDebugLogs)
			{
				Debug.Log((object)"[CombatCompanion] State changed to: COMBAT HELPER");
			}
			if (AudEvent_ToggleOn != null)
			{
				SM.PlayCoreSound((FVRPooledAudioType)10, AudEvent_ToggleOn, ((Component)this).transform.position);
			}
		}
	}

	private void SetStateOff()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		if (m_isOn)
		{
			m_isOn = false;
			m_tarValue = OffValue;
			mode = CompanionModeEnum.LootCompanion;
			if (enableDebugLogs)
			{
				Debug.Log((object)"[CombatCompanion] State changed to: LOOT COMPANION");
			}
			if (AudEvent_ToggleOff != null)
			{
				SM.PlayCoreSound((FVRPooledAudioType)10, AudEvent_ToggleOff, ((Component)this).transform.position);
			}
		}
	}

	public override void FVRUpdate()
	{
		//IL_015b: 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)
		((FVRInteractiveObject)this).FVRUpdate();
		if ((Object)(object)ButtonGeo != (Object)null && Mathf.Abs(m_tarValue - m_curValue) > 0.001f)
		{
			m_curValue = Mathf.MoveTowards(m_curValue, m_tarValue, Time.deltaTime * AnimationSpeed);
			if (AnimationType == AnimationTypeEnum.Rotation)
			{
				float num = ((TargetAxis != AxisEnum.X) ? m_defaultLocalRot.x : m_curValue);
				float num2 = ((TargetAxis != AxisEnum.Y) ? m_defaultLocalRot.y : m_curValue);
				float num3 = ((TargetAxis != AxisEnum.Z) ? m_defaultLocalRot.z : m_curValue);
				ButtonGeo.localEulerAngles = new Vector3(num, num2, num3);
			}
			else
			{
				float num4 = ((TargetAxis != AxisEnum.X) ? m_defaultLocalPos.x : m_curValue);
				float num5 = ((TargetAxis != AxisEnum.Y) ? m_defaultLocalPos.y : m_curValue);
				float num6 = ((TargetAxis != AxisEnum.Z) ? m_defaultLocalPos.z : m_curValue);
				ButtonGeo.localPosition = new Vector3(num4, num5, num6);
			}
		}
		if ((Object)(object)lootComp == (Object)null)
		{
			return;
		}
		if (mode == CompanionModeEnum.LootCompanion)
		{
			if (!((Behaviour)lootComp).enabled)
			{
				((Behaviour)lootComp).enabled = true;
			}
			return;
		}
		if (((Behaviour)lootComp).enabled)
		{
			((Behaviour)lootComp).enabled = false;
		}
		UpdateThreat();
		HandleCombatMovement();
		HandleCombatShooting();
	}

	private void LateUpdate()
	{
		if (mode == CompanionModeEnum.CombatHelper && (Object)(object)targetEntity != (Object)null)
		{
			FVRFireArm firstAvailableWeapon = GetFirstAvailableWeapon();
			if ((Object)(object)firstAvailableWeapon != (Object)null)
			{
				AimWeaponAtTarget(firstAvailableWeapon);
			}
		}
	}

	private void UpdateThreat()
	{
		if (suppressionThreatSpike > 0f)
		{
			suppressionThreatSpike -= Time.deltaTime * 0.15f;
		}
		float num = 0f;
		AIEntity[] array = Object.FindObjectsOfType<AIEntity>();
		if (array != null)
		{
			int num2 = 0;
			int num3 = (((Object)(object)selfAIEntity != (Object)null) ? selfAIEntity.IFFCode : 0);
			foreach (AIEntity val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)selfAIEntity && !val.IsPassiveEntity && val.IFFCode != num3 && IsInSight(val))
				{
					num2++;
				}
			}
			num = Mathf.Clamp01((float)num2 * 0.15f);
		}
		float num4 = Mathf.Clamp01(num + suppressionThreatSpike);
		currentThreat = Mathf.Lerp(currentThreat, num4, Time.deltaTime * 1.5f);
	}

	private void HandleCombatShooting()
	{
		FVRFireArm firstAvailableWeapon = GetFirstAvailableWeapon();
		if ((Object)(object)firstAvailableWeapon == (Object)null)
		{
			return;
		}
		if ((Object)(object)targetEntity == (Object)null || !IsInSight(targetEntity))
		{
			FindCombatTarget();
		}
		if ((Object)(object)targetEntity != (Object)null && Time.time >= nextShootTime && WeaponHasAmmoInChamber(firstAvailableWeapon))
		{
			InjectTriggerPull(firstAvailableWeapon);
			if (enableDebugLogs)
			{
				Debug.Log((object)("[CombatCompanion] Trigger injected on weapon: " + ((Object)((Component)firstAvailableWeapon).gameObject).name + ". Active target: " + ((Object)((Component)targetEntity).gameObject).name));
			}
			float num = Mathf.Lerp(maxShootDelay, minShootDelay, currentThreat);
			nextShootTime = Time.time + num;
		}
	}

	private FVRFireArm GetFirstAvailableWeapon()
	{
		if ((Object)(object)lootComp == (Object)null)
		{
			return null;
		}
		if ((Object)(object)lootComp.mouthSlot != (Object)null && (Object)(object)lootComp.mouthSlot.HeldObject != (Object)null)
		{
			FVRInteractiveObject heldObject = lootComp.mouthSlot.HeldObject;
			FVRFireArm val = (FVRFireArm)(object)((heldObject is FVRFireArm) ? heldObject : null);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		if (lootComp.backpack != null)
		{
			for (int i = 0; i < lootComp.backpack.Length; i++)
			{
				FVRQuickBeltSlot val2 = lootComp.backpack[i];
				if ((Object)(object)val2 != (Object)null && (Object)(object)val2.HeldObject != (Object)null)
				{
					FVRInteractiveObject heldObject2 = val2.HeldObject;
					FVRFireArm val3 = (FVRFireArm)(object)((heldObject2 is FVRFireArm) ? heldObject2 : null);
					if ((Object)(object)val3 != (Object)null)
					{
						return val3;
					}
				}
			}
		}
		return null;
	}

	private FVRQuickBeltSlot GetSlotOfWeapon(FVRFireArm weapon)
	{
		if ((Object)(object)weapon == (Object)null || (Object)(object)lootComp == (Object)null)
		{
			return null;
		}
		if ((Object)(object)lootComp.mouthSlot != (Object)null && (Object)(object)lootComp.mouthSlot.HeldObject == (Object)(object)weapon)
		{
			return lootComp.mouthSlot;
		}
		if (lootComp.backpack != null)
		{
			for (int i = 0; i < lootComp.backpack.Length; i++)
			{
				if ((Object)(object)lootComp.backpack[i] != (Object)null && (Object)(object)lootComp.backpack[i].HeldObject == (Object)(object)weapon)
				{
					return lootComp.backpack[i];
				}
			}
		}
		return null;
	}

	private void FindCombatTarget()
	{
		//IL_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009c: Unknown result type (might be due to invalid IL or missing references)
		AIEntity[] array = Object.FindObjectsOfType<AIEntity>();
		if (array == null)
		{
			return;
		}
		AIEntity val = null;
		float num = maxCombatRange;
		int num2 = (((Object)(object)selfAIEntity != (Object)null) ? selfAIEntity.IFFCode : 0);
		foreach (AIEntity val2 in array)
		{
			if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)selfAIEntity) && !val2.IsPassiveEntity && val2.IFFCode != num2)
			{
				float num3 = Vector3.Distance(((Component)this).transform.position, val2.GetPos());
				if (num3 < num && IsInSight(val2))
				{
					num = num3;
					val = val2;
				}
			}
		}
		if ((Object)(object)val != (Object)(object)targetEntity)
		{
			targetEntity = val;
			if (enableDebugLogs && (Object)(object)targetEntity != (Object)null)
			{
				Debug.Log((object)("[CombatCompanion] Acquired new combat target: " + ((Object)((Component)targetEntity).gameObject).name));
			}
		}
	}

	private bool IsInSight(AIEntity target)
	{
		//IL_0015: 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_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_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Unknown result type (might be due to invalid IL or missing references)
		//IL_007c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0086: Unknown result type (might be due to invalid IL or missing references)
		//IL_008b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0092: Unknown result type (might be due to invalid IL or missing references)
		//IL_009b: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)target == (Object)null)
		{
			return false;
		}
		Vector3 val = target.GetPos() - ((Component)this).transform.position;
		float magnitude = ((Vector3)(ref val)).magnitude;
		if (magnitude > maxCombatRange)
		{
			return false;
		}
		float num = Vector3.Angle(((Component)this).transform.forward, val);
		if (num > maxCombatFOV * 0.5f)
		{
			return false;
		}
		RaycastHit val2 = default(RaycastHit);
		if (Physics.Raycast(((Component)this).transform.position + Vector3.up * 0.5f, ((Vector3)(ref val)).normalized, ref val2, magnitude, LayerMask.op_Implicit(visualOcclusionMask)) && (Object)(object)((RaycastHit)(ref val2)).transform != (Object)(object)((Component)target).transform && !((RaycastHit)(ref val2)).transform.IsChildOf(((Component)target).transform))
		{
			return false;
		}
		return true;
	}

	private void RotateBodyTowards(Vector3 targetPos)
	{
		//IL_0001: 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_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: 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_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: 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)
		Vector3 val = targetPos - ((Component)this).transform.position;
		val.y = 0f;
		if (val != Vector3.zero)
		{
			Quaternion val2 = Quaternion.LookRotation(val);
			((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, val2, Time.deltaTime * bodyRotationSpeed);
		}
	}

	private void AimWeaponAtTarget(FVRFireArm weapon)
	{
		//IL_0036: 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_0063: 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_0068: 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_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0070: 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_0072: 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_00a0: 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_00a7: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cc: 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_00ef: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)targetEntity == (Object)null)
		{
			return;
		}
		FVRQuickBeltSlot slotOfWeapon = GetSlotOfWeapon(weapon);
		if (!((Object)(object)slotOfWeapon == (Object)null))
		{
			Vector3 pos = targetEntity.GetPos();
			Vector3 val = ((!((Object)(object)weapon.MuzzlePos != (Object)null)) ? ((Component)slotOfWeapon).transform.position : weapon.MuzzlePos.position);
			Vector3 val2 = pos - val;
			if (val2 != Vector3.zero)
			{
				float num = Mathf.Lerp(0.5f, 4f, currentThreat);
				Vector3 val3 = Random.insideUnitSphere * num;
				Quaternion val4 = Quaternion.LookRotation(val2) * Quaternion.Euler(val3);
				((Component)slotOfWeapon).transform.rotation = Quaternion.Slerp(((Component)slotOfWeapon).transform.rotation, val4, Time.deltaTime * 10f);
				((Component)weapon).transform.rotation = ((Component)slotOfWeapon).transform.rotation;
			}
		}
	}

	private bool WeaponHasAmmoInChamber(FVRFireArm firearm)
	{
		if ((Object)(object)firearm == (Object)null)
		{
			return false;
		}
		PropertyInfo property = ((object)firearm).GetType().GetProperty("Chamber", BindingFlags.Instance | BindingFlags.Public);
		if ((object)property != null)
		{
			object value = property.GetValue(firearm, null);
			if (value != null)
			{
				PropertyInfo property2 = value.GetType().GetProperty("IsFull", BindingFlags.Instance | BindingFlags.Public);
				PropertyInfo property3 = value.GetType().GetProperty("IsSpent", BindingFlags.Instance | BindingFlags.Public);
				if ((object)property2 != null && (object)property3 != null)
				{
					bool flag = (bool)property2.GetValue(value, null);
					bool flag2 = (bool)property3.GetValue(value, null);
					return flag && !flag2;
				}
			}
		}
		return true;
	}

	private void InjectTriggerPull(FVRFireArm firearm)
	{
		if (!((Object)(object)firearm == (Object)null))
		{
			Type type = ((object)firearm).GetType();
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public);
			if (!TryInvokeNamedMethod(firearm, methods, "DropHammer") && !TryInvokeNamedMethod(firearm, methods, "PullTrigger") && !TryInvokeNamedMethod(firearm, methods, "Fire"))
			{
			}
		}
	}

	private bool TryInvokeNamedMethod(FVRFireArm firearm, MethodInfo[] methods, string name)
	{
		foreach (MethodInfo methodInfo in methods)
		{
			if (!(methodInfo.Name == name))
			{
				continue;
			}
			try
			{
				ParameterInfo[] parameters = methodInfo.GetParameters();
				if (parameters.Length == 0)
				{
					methodInfo.Invoke(firearm, null);
					return true;
				}
				if (parameters.Length == 1 && (object)parameters[0].ParameterType == typeof(bool))
				{
					methodInfo.Invoke(firearm, new object[1] { true });
					return true;
				}
			}
			catch (Exception ex)
			{
				if (enableDebugLogs)
				{
					Debug.LogWarning((object)("[CombatCompanion] Safe invoke failed for " + name + ": " + ex.Message));
				}
			}
		}
		return false;
	}

	private void HandleCombatMovement()
	{
		//IL_0023: 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_0033: 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_0058: 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_00aa: Unknown result type (might be due to invalid IL or missing references)
		//IL_00af: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a2: 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_0160: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)agent == (Object)null)
		{
			return;
		}
		Transform transform = ((Component)GM.CurrentPlayerBody).transform;
		Vector3 val = transform.position + transform.forward;
		float num = Vector3.Distance(((Component)this).transform.position, val);
		if (num >= lootComp.playerDistanceMax)
		{
			NavMeshHit val2 = default(NavMeshHit);
			if (NavMesh.SamplePosition(val, ref val2, 50f, -1))
			{
				agent.Warp(((NavMeshHit)(ref val2)).position);
			}
		}
		else if ((Object)(object)targetEntity != (Object)null)
		{
			Vector3 pos = targetEntity.GetPos();
			float num2 = Vector3.Distance(((Component)this).transform.position, pos);
			if (num2 > combatStandoffDistance)
			{
				if (!((Behaviour)agent).enabled)
				{
					((Behaviour)agent).enabled = true;
				}
				agent.SetDestination(pos);
				PlayCompanionAnimation(GetTargetAnimState(lootComp.animRun, animCombatRun));
			}
			else
			{
				if (((Behaviour)agent).enabled && agent.hasPath)
				{
					agent.ResetPath();
				}
				PlayCompanionAnimation(GetTargetAnimState(lootComp.animWait, animCombatWait));
			}
			RotateBodyTowards(pos);
		}
		else if (num >= lootComp.playerDistanceMin)
		{
			if (!((Behaviour)agent).enabled)
			{
				((Behaviour)agent).enabled = true;
			}
			agent.SetDestination(val);
			PlayCompanionAnimation(GetTargetAnimState(lootComp.animRun, animCombatRun));
		}
		else
		{
			PlayCompanionAnimation(GetTargetAnimState(lootComp.animIdle, animCombatIdle));
		}
	}

	private string GetTargetAnimState(string defaultAnim, string combatAnim)
	{
		if (mode == CompanionModeEnum.CombatHelper && !string.IsNullOrEmpty(combatAnim))
		{
			return combatAnim;
		}
		return defaultAnim;
	}

	private void PlayCompanionAnimation(string animName)
	{
		if ((Object)(object)lootComp != (Object)null && (Object)(object)lootComp.animator != (Object)null && !string.IsNullOrEmpty(animName))
		{
			lootComp.animator.Play(animName);
		}
	}

	private void OnDrawGizmos()
	{
		//IL_0011: 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_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		//IL_003a: 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_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_006d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: 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_0094: 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_00a4: 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_00aa: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b7: 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_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: 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_00c5: 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_00cc: 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)
		//IL_0110: 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_011a: 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)
		//IL_0131: Unknown result type (might be due to invalid IL or missing references)
		if (drawDebugGizmos)
		{
			Gizmos.color = Color.yellow;
			Vector3 val = ((Component)this).transform.position + Vector3.up * 0.5f;
			Vector3 val2 = Quaternion.Euler(0f, (0f - maxCombatFOV) * 0.5f, 0f) * ((Component)this).transform.forward * maxCombatRange;
			Vector3 val3 = Quaternion.Euler(0f, maxCombatFOV * 0.5f, 0f) * ((Component)this).transform.forward * maxCombatRange;
			Gizmos.DrawLine(val, val + val2);
			Gizmos.DrawLine(val, val + val3);
			Gizmos.DrawLine(val + val2, val + val3);
			if (Application.isPlaying && (Object)(object)targetEntity != (Object)null)
			{
				Gizmos.color = ((!IsInSight(targetEntity)) ? Color.red : Color.green);
				Gizmos.DrawLine(val, targetEntity.GetPos());
				Gizmos.DrawWireSphere(targetEntity.GetPos(), 0.5f);
			}
		}
	}
}
namespace Volks.KerfusCompanion;

[BepInPlugin("Volks.KerfusCompanion", "KerfusCompanion", "1.0.0")]
[BepInProcess("h3vr.exe")]
[Description("Built with MeatKit")]
[BepInDependency("h3vr.otherloader", "1.3.0")]
public class KerfusCompanionPlugin : BaseUnityPlugin
{
	private static readonly string BasePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

	internal static ManualLogSource Logger;

	private void Awake()
	{
		Logger = ((BaseUnityPlugin)this).Logger;
		LoadAssets();
	}

	private void LoadAssets()
	{
		Harmony.CreateAndPatchAll(Assembly.GetExecutingAssembly(), "Volks.KerfusCompanion");
		OtherLoader.RegisterDirectLoad(BasePath, "Volks.KerfusCompanion", "", "", "kerfuscompanion", "");
	}
}
public class Semtex : PinnedGrenade
{
	[Header("Semtex Values")]
	public bool isSticky;

	public LayerMask stickyMask;

	[Header("Semtex Extras (Leave Empty If Not Needed)")]
	[Tooltip("If not null, will play audio clip placed inside of source. Used for a stick sound if you want.")]
	public AudioSource StickSource;

	public override void OnCollisionEnter(Collision collision)
	{
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		if (collision.gameObject.layer == LayerMask.op_Implicit(stickyMask) && !((FVRInteractiveObject)this).IsHeld)
		{
			((Component)this).transform.parent = collision.transform;
			((Component)this).GetComponent<Rigidbody>().isKinematic = true;
			if ((Object)(object)StickSource != (Object)null)
			{
				StickSource.Play();
			}
		}
		((PinnedGrenade)this).OnCollisionEnter(collision);
	}
}
public class Semtex_Updated : PinnedGrenade
{
	[Header("Semtex Values")]
	public bool isSticky;

	public LayerMask stickyMask;

	[Header("Semtex Extras (Leave Empty If Not Needed)")]
	[Tooltip("If not null, will play audio clip placed inside of source. Used for a stick sound if you want.")]
	public AudioSource StickSource;

	private float timeBeforeEnableStick = 0.1f;

	private bool canStick = false;

	private Transform fakeParent;

	private Vector3 pos;

	private Vector3 fw;

	private Vector3 up;

	public override void FVRUpdate()
	{
		if (base.m_isLeverReleased && !canStick)
		{
			timeBeforeEnableStick -= Time.deltaTime;
			if (timeBeforeEnableStick <= 0f)
			{
				canStick = true;
			}
		}
		((PinnedGrenade)this).FVRUpdate();
	}

	private void FixedUpdate()
	{
		//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_0029: 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_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_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_0058: 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_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_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)fakeParent != (Object)null)
		{
			Vector3 position = ((Component)fakeParent).transform.TransformPoint(pos);
			Vector3 val = ((Component)fakeParent).transform.TransformDirection(fw);
			Vector3 val2 = ((Component)fakeParent).transform.TransformDirection(up);
			Quaternion rotation = Quaternion.LookRotation(val, val2);
			((Component)this).transform.position = position;
			((Component)this).transform.rotation = rotation;
		}
	}

	public override void OnCollisionEnter(Collision collision)
	{
		//IL_0053: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0074: 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_0095: Unknown result type (might be due to invalid IL or missing references)
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		((PinnedGrenade)this).OnCollisionEnter(collision);
		if (!((FVRInteractiveObject)this).IsHeld && canStick && (Object)(object)fakeParent == (Object)null)
		{
			fakeParent = collision.gameObject.transform;
			((Component)this).transform.position = ((ContactPoint)(ref collision.contacts[0])).point;
			((Component)this).transform.rotation = Quaternion.LookRotation(((ContactPoint)(ref collision.contacts[0])).normal);
			pos = ((Component)fakeParent).transform.InverseTransformPoint(((Component)this).transform.position);
			fw = ((Component)fakeParent).transform.InverseTransformDirection(((Component)this).transform.forward);
			up = ((Component)fakeParent).transform.InverseTransformDirection(((Component)this).transform.up);
			((Component)this).GetComponent<Rigidbody>().isKinematic = true;
			if ((Object)(object)StickSource != (Object)null)
			{
				StickSource.Play();
			}
		}
	}

	public override void BeginInteraction(FVRViveHand hand)
	{
		((PinnedGrenade)this).BeginInteraction(hand);
		fakeParent = null;
	}
}