Decompiled source of FreeGrillerLibs v0.1.2

NGA.FreeGrillerLibs.dll

Decompiled a year ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FistVR;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Sodalite.Api;
using Sodalite.ModPanel;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyCompany("NGA")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Persistent player progression! Raid, stash loot, and deploy with seemless scene/loadout saving.")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("NGA.FreeGrillerLibs")]
[assembly: AssemblyTitle("BepInEx Plugin Title")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string id = null, string name = null, string version = null)
		{
		}
	}
}
namespace NGA
{
	public class ContractEvaluationContext
	{
		public FGContract myContract;

		public List<FGContractEvent> eventsInSession;

		public bool isFinalCheck = false;
	}
	public interface IContractConstraint
	{
		void EvaluateAndUpdateContract(ContractEvaluationContext context);

		string GetDescription();
	}
	public static class ConstraintFactory
	{
		private static Dictionary<string, Func<IContractConstraint>> constraintRegistry = new Dictionary<string, Func<IContractConstraint>>
		{
			{
				"GrillViaProjectile",
				() => new GrillViaProjectileConstraint()
			},
			{
				"GrillAllTargets",
				() => new GrillAllTargetsConstraint()
			}
		};

		public static IContractConstraint GetConstraint(string id)
		{
			return constraintRegistry.ContainsKey(id) ? constraintRegistry[id]() : null;
		}

		public static void AddConstraint(string id, Func<IContractConstraint> constructor)
		{
			if (!constraintRegistry.ContainsKey(id))
			{
				constraintRegistry[id] = constructor;
			}
			else
			{
				Debug.LogWarning((object)("Constraint '" + id + "' is already registered."));
			}
		}

		public static FGContract.ConstraintAndReward CreateConstraintAndReward(FGContract.ConstraintAndReward constraintData, bool isItMet, bool isItFailed)
		{
			FGContract.ConstraintAndReward result = default(FGContract.ConstraintAndReward);
			result.ConstraintID = constraintData.ConstraintID;
			result.optional = constraintData.optional;
			result.constraintSuccess = isItMet;
			result.constraintViolated = isItFailed;
			result.rewardAddedIfSucceed = constraintData.rewardAddedIfSucceed;
			result.rewardSubtractedIfFail = constraintData.rewardSubtractedIfFail;
			return result;
		}

		public static void UpdateConstraintInContract(ContractEvaluationContext context, string constraintID, bool isConstraintMet, bool isConstraintFailed)
		{
			List<FGContract.ConstraintAndReward> list = context.myContract.ConstraintsAndRewards.FindAll((FGContract.ConstraintAndReward x) => x.ConstraintID == constraintID);
			if (list.Count == 0)
			{
				Debug.LogError((object)(constraintID + " constraint not found in contract."));
				return;
			}
			foreach (FGContract.ConstraintAndReward item in list)
			{
				int index = context.myContract.ConstraintsAndRewards.IndexOf(item);
				context.myContract.ConstraintsAndRewards[index] = CreateConstraintAndReward(item, isConstraintMet, isConstraintFailed);
			}
		}

		public static bool IsConstraintInConstract(FGContract contract, string constraintID)
		{
			return contract.ConstraintsAndRewards.Exists((FGContract.ConstraintAndReward x) => x.ConstraintID == constraintID);
		}

		public static bool AreThereTargetsInScene()
		{
			return FG_GM.Instance.mapLoader.TargetPosses.Count > 0;
		}

		public static bool IsContractInAnyPosse(FGContract contract)
		{
			foreach (FGTargetPosse targetPoss in FG_GM.Instance.mapLoader.TargetPosses)
			{
				if ((Object)(object)targetPoss == (Object)null || targetPoss.contract == null || targetPoss.contract.uniqueID != contract.uniqueID)
				{
					continue;
				}
				return true;
			}
			return false;
		}
	}
	public class GrillViaProjectileConstraint : IContractConstraint
	{
		public string constraintKey = "GrillViaProjectile";

		public void EvaluateAndUpdateContract(ContractEvaluationContext context)
		{
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_0187: Invalid comparison between Unknown and I4
			if (!ConstraintFactory.IsConstraintInConstract(context.myContract, constraintKey) || !ConstraintFactory.AreThereTargetsInScene() || !ConstraintFactory.IsContractInAnyPosse(context.myContract))
			{
				return;
			}
			FGTargetPosse fGTargetPosse = FG_GM.Instance.mapLoader.TargetPosses.Find((FGTargetPosse x) => x.contract.uniqueID == context.myContract.uniqueID);
			List<FGContractEvent> list = context.eventsInSession.FindAll((FGContractEvent x) => x.EventKey == "OnSosigKill");
			int num = 0;
			HashSet<Sosig> hashSet = new HashSet<Sosig>();
			foreach (FGContractEvent item in list)
			{
				if (item.OnSosigKill == null)
				{
					continue;
				}
				Sosig sosig = item.OnSosigKill.Sosig;
				if ((Object)(object)sosig == (Object)null)
				{
					Debug.LogError((object)"Unexpected sosig null OnSosigKill.");
					continue;
				}
				if (hashSet.Contains(sosig))
				{
					Debug.LogError((object)"Sosig already killed by projectile - unexpected event again.");
					continue;
				}
				FGTrackedSosig fGTrackedSosig = fGTargetPosse.FindSosig(sosig);
				if (fGTrackedSosig != null && fGTrackedSosig.Manifest?.IsTarget == true)
				{
					num++;
					DamageClass diedFromClass = sosig.GetDiedFromClass();
					if ((int)diedFromClass == 1)
					{
						hashSet.Add(sosig);
					}
				}
			}
			bool isConstraintMet = num > 0 && num == hashSet.Count;
			bool isConstraintFailed = false;
			if (context.isFinalCheck)
			{
				isConstraintFailed = num > 0 && num != hashSet.Count;
			}
			ConstraintFactory.UpdateConstraintInContract(context, constraintKey, isConstraintMet, isConstraintFailed);
		}

		public string GetDescription()
		{
			return "Eliminate all targets with a projectile.";
		}
	}
	public class GrillAllTargetsConstraint : IContractConstraint
	{
		public string constraintKey = "GrillAllTargets";

		public void EvaluateAndUpdateContract(ContractEvaluationContext context)
		{
			if (!ConstraintFactory.IsConstraintInConstract(context.myContract, constraintKey) || !ConstraintFactory.AreThereTargetsInScene() || !ConstraintFactory.IsContractInAnyPosse(context.myContract))
			{
				return;
			}
			FGTargetPosse fGTargetPosse = FG_GM.Instance.mapLoader.TargetPosses.Find((FGTargetPosse x) => x.contract.uniqueID == context.myContract.uniqueID);
			int count = fGTargetPosse.trackedTargets.Count;
			List<FGContractEvent> list = context.eventsInSession.FindAll((FGContractEvent x) => x.EventKey == "OnSosigKill");
			HashSet<Sosig> hashSet = new HashSet<Sosig>();
			foreach (FGContractEvent item in list)
			{
				if (item.OnSosigKill == null)
				{
					continue;
				}
				Sosig sosig = item.OnSosigKill.Sosig;
				if ((Object)(object)sosig == (Object)null)
				{
					Debug.LogError((object)"Unexpected sosig null OnSosigKill.");
					continue;
				}
				if (hashSet.Contains(sosig))
				{
					Debug.LogWarning((object)"Sosig already killed - unexpected event again.");
					continue;
				}
				FGTrackedSosig fGTrackedSosig = fGTargetPosse.FindSosig(sosig);
				if (fGTrackedSosig != null && fGTrackedSosig.Manifest?.IsTarget == true)
				{
					hashSet.Add(sosig);
				}
			}
			bool isConstraintMet = count == hashSet.Count;
			bool isConstraintFailed = false;
			if (context.isFinalCheck)
			{
				isConstraintFailed = count != hashSet.Count;
			}
			ConstraintFactory.UpdateConstraintInContract(context, constraintKey, isConstraintMet, isConstraintFailed);
		}

		public string GetDescription()
		{
			return "Eliminate all targets.";
		}
	}
	[Serializable]
	public class FGContract
	{
		[Serializable]
		public class SerializableKeyValuePair
		{
			public string Key;

			public string Value;

			public SerializableKeyValuePair()
			{
			}

			public SerializableKeyValuePair(string key, string value)
			{
				Key = key;
				Value = value;
			}
		}

		[Serializable]
		public struct ReputationReward
		{
			public string FactionID;

			public float Rep;
		}

		[Serializable]
		public struct ReputationRequirement
		{
			public string FactionID;

			public float MinimumRep;

			public float MaximumRep;
		}

		[Serializable]
		public struct ConstraintAndReward
		{
			public string ConstraintID;

			public bool optional;

			public bool constraintSuccess;

			public bool constraintViolated;

			public int rewardSubtractedIfFail;

			public int rewardAddedIfSucceed;
		}

		public int uniqueID;

		public string DisplayName;

		public string HiringFactionID;

		public string TargetFirstName;

		public string TargetLastName;

		public string Infraction;

		[SerializeField]
		private List<SerializableKeyValuePair> TargetIDs = new List<SerializableKeyValuePair>();

		[SerializeField]
		private List<SerializableKeyValuePair> GuardIDs = new List<SerializableKeyValuePair>();

		[SerializeField]
		private List<SerializableKeyValuePair> ExtrasIDs = new List<SerializableKeyValuePair>();

		[NonSerialized]
		public Dictionary<string, List<SosigEnemyID>> _TargetIDs = new Dictionary<string, List<SosigEnemyID>>();

		[NonSerialized]
		public Dictionary<string, List<SosigEnemyID>> _GuardIDs = new Dictionary<string, List<SosigEnemyID>>();

		[NonSerialized]
		public Dictionary<string, List<SosigEnemyID>> _ExtrasIDs = new Dictionary<string, List<SosigEnemyID>>();

		[SerializeField]
		private List<SerializableKeyValuePair> Faction_Target = new List<SerializableKeyValuePair>();

		[SerializeField]
		private List<SerializableKeyValuePair> Faction_Guards = new List<SerializableKeyValuePair>();

		[SerializeField]
		private List<SerializableKeyValuePair> Faction_Extras = new List<SerializableKeyValuePair>();

		[NonSerialized]
		public Dictionary<string, string> _Faction_Target = new Dictionary<string, string>();

		[NonSerialized]
		public Dictionary<string, string> _Faction_Guards = new Dictionary<string, string>();

		[NonSerialized]
		public Dictionary<string, string> _Faction_Extras = new Dictionary<string, string>();

		public string SceneName;

		public string SceneCivConfigName;

		public string SceneEnemyConfigName;

		public List<ReputationRequirement> ReputationRequirements;

		public List<ConstraintAndReward> ConstraintsAndRewards = new List<ConstraintAndReward>();

		public string expirationTime;

		public int Compensation;

		public List<ReputationReward> ReputationRewards;

		public bool hasEnded;

		public bool isAccepted;

		public bool hasSucceeded;

		public bool hasFailed;

		public DateTime ExpirationDateTime => DateTime.Parse(expirationTime);

		public string PrintContract()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.AppendLine("Contract: " + DisplayName);
			stringBuilder.AppendLine("Hiring Faction: " + HiringFactionID);
			stringBuilder.AppendLine("Target: " + TargetFirstName + " " + TargetLastName);
			stringBuilder.AppendLine("Infraction: " + Infraction);
			stringBuilder.AppendLine("Scene: " + SceneName);
			DateTime currentTime = FGTimeSystem.Instance.CurrentTime;
			if (ExpirationDateTime > currentTime)
			{
				TimeSpan timeSpan = FGTimeSystem.Instance.CalculateRealTimeUntil(currentTime, ExpirationDateTime);
				stringBuilder.AppendLine($"Time until expiration: {timeSpan.Hours}h {timeSpan.Minutes}m {timeSpan.Seconds}s");
			}
			stringBuilder.AppendLine($"Compensation: ${Compensation:N0}");
			if (ReputationRequirements != null && ReputationRequirements.Count > 0)
			{
				stringBuilder.AppendLine("Reputation Requirements:");
				foreach (ReputationRequirement reputationRequirement in ReputationRequirements)
				{
					stringBuilder.AppendLine($"  - {reputationRequirement.FactionID}: {reputationRequirement.MinimumRep} to {reputationRequirement.MaximumRep}");
				}
			}
			if (ReputationRewards != null && ReputationRewards.Count > 0)
			{
				stringBuilder.AppendLine("Reputation Rewards:");
				foreach (ReputationReward reputationReward in ReputationRewards)
				{
					stringBuilder.AppendLine($"  - {reputationReward.FactionID}: {reputationReward.Rep:+0.0;-0.0}");
				}
			}
			if (ConstraintsAndRewards != null && ConstraintsAndRewards.Count > 0)
			{
				List<ConstraintAndReward> list = ConstraintsAndRewards.Where((ConstraintAndReward c) => !c.optional).ToList();
				List<ConstraintAndReward> list2 = ConstraintsAndRewards.Where((ConstraintAndReward c) => c.optional).ToList();
				if (list.Count > 0)
				{
					stringBuilder.AppendLine("Required Conditions:");
					foreach (ConstraintAndReward item in list)
					{
						string text = (item.constraintSuccess ? "✔ Completed" : (item.constraintViolated ? "✖ Failed" : "Pending"));
						string text2 = ((item.rewardSubtractedIfFail > 0) ? $" -${item.rewardSubtractedIfFail}" : "");
						stringBuilder.AppendLine("  - " + item.ConstraintID + " (" + text + ")" + text2);
					}
				}
				if (list2.Count > 0)
				{
					stringBuilder.AppendLine("Optional Bonuses:");
					foreach (ConstraintAndReward item2 in list2)
					{
						string text3 = (item2.constraintSuccess ? "✔ Completed" : (item2.constraintViolated ? "✖ Failed" : "Pending"));
						string text4 = ((item2.rewardAddedIfSucceed > 0) ? $" +${item2.rewardAddedIfSucceed}" : "");
						stringBuilder.AppendLine("  - " + item2.ConstraintID + " (" + text3 + ")" + text4);
					}
				}
			}
			return stringBuilder.ToString();
		}

		public List<IContractConstraint> GetConstraints()
		{
			List<IContractConstraint> list = new List<IContractConstraint>();
			foreach (ConstraintAndReward constraintsAndReward in ConstraintsAndRewards)
			{
				IContractConstraint constraint = ConstraintFactory.GetConstraint(constraintsAndReward.ConstraintID);
				if (constraint != null)
				{
					list.Add(constraint);
				}
			}
			return list;
		}

		public void PrepareForSave()
		{
			ConvertToSerializable();
		}

		public void PrepareFromLoad()
		{
			ConvertToDictionary();
		}

		public void ConvertToSerializable()
		{
			GuardIDs.Clear();
			foreach (KeyValuePair<string, List<SosigEnemyID>> guardID in _GuardIDs)
			{
				GuardIDs.Add(new SerializableKeyValuePair(guardID.Key, string.Join(",", guardID.Value.Select((SosigEnemyID id) => ((int)id).ToString()).ToArray())));
			}
			TargetIDs.Clear();
			foreach (KeyValuePair<string, List<SosigEnemyID>> targetID in _TargetIDs)
			{
				TargetIDs.Add(new SerializableKeyValuePair(targetID.Key, string.Join(",", targetID.Value.Select((SosigEnemyID id) => ((int)id).ToString()).ToArray())));
			}
			ExtrasIDs.Clear();
			foreach (KeyValuePair<string, List<SosigEnemyID>> extrasID in _ExtrasIDs)
			{
				ExtrasIDs.Add(new SerializableKeyValuePair(extrasID.Key, string.Join(",", extrasID.Value.Select((SosigEnemyID id) => ((int)id).ToString()).ToArray())));
			}
			Faction_Target.Clear();
			foreach (KeyValuePair<string, string> item in _Faction_Target)
			{
				Faction_Target.Add(new SerializableKeyValuePair(item.Key, item.Value));
			}
			Faction_Guards.Clear();
			foreach (KeyValuePair<string, string> faction_Guard in _Faction_Guards)
			{
				Faction_Guards.Add(new SerializableKeyValuePair(faction_Guard.Key, faction_Guard.Value));
			}
			Faction_Extras.Clear();
			foreach (KeyValuePair<string, string> faction_Extra in _Faction_Extras)
			{
				Faction_Extras.Add(new SerializableKeyValuePair(faction_Extra.Key, faction_Extra.Value));
			}
		}

		public void ConvertToDictionary()
		{
			_GuardIDs.Clear();
			foreach (SerializableKeyValuePair guardID in GuardIDs)
			{
				_GuardIDs.Add(guardID.Key, (from id in guardID.Value.Split(new char[1] { ',' })
					select (SosigEnemyID)int.Parse(id)).ToList());
			}
			_TargetIDs.Clear();
			foreach (SerializableKeyValuePair targetID in TargetIDs)
			{
				_TargetIDs.Add(targetID.Key, (from id in targetID.Value.Split(new char[1] { ',' })
					select (SosigEnemyID)int.Parse(id)).ToList());
			}
			_ExtrasIDs.Clear();
			foreach (SerializableKeyValuePair extrasID in ExtrasIDs)
			{
				_ExtrasIDs.Add(extrasID.Key, (from id in extrasID.Value.Split(new char[1] { ',' })
					select (SosigEnemyID)int.Parse(id)).ToList());
			}
			_Faction_Target.Clear();
			foreach (SerializableKeyValuePair item in Faction_Target)
			{
				_Faction_Target.Add(item.Key, item.Value);
			}
			_Faction_Guards.Clear();
			foreach (SerializableKeyValuePair faction_Guard in Faction_Guards)
			{
				_Faction_Guards.Add(faction_Guard.Key, faction_Guard.Value);
			}
			_Faction_Extras.Clear();
			foreach (SerializableKeyValuePair faction_Extra in Faction_Extras)
			{
				_Faction_Extras.Add(faction_Extra.Key, faction_Extra.Value);
			}
		}
	}
	public class FGContractEvent
	{
		public class OnSosigKillEvent
		{
			public Sosig Sosig { get; set; }
		}

		public class OnSosigMadeEnemyWithEvent
		{
			public Sosig Sosig { get; set; }

			public int IFF { get; set; }
		}

		public class OnSosigAlertEvent
		{
			public Sosig Sosig { get; set; }

			public Vector3 Position { get; set; }
		}

		public class OnShotFiredEvent
		{
			public FVRFireArm Firearm { get; set; }
		}

		public class OnSosiggunFiredEvent
		{
			public SosigWeapon Weapon { get; set; }
		}

		public string EventKey { get; set; }

		public OnSosigKillEvent OnSosigKill { get; set; }

		public OnSosigMadeEnemyWithEvent OnSosigMadeEnemyWith { get; set; }

		public OnSosigAlertEvent OnSosigAlert { get; set; }

		public OnShotFiredEvent OnShotFired { get; set; }

		public OnSosiggunFiredEvent OnSosiggunFired { get; set; }

		public string GenericEventContents { get; set; }
	}
	public class FGContractEventsRecorder
	{
		private bool sessionActive = false;

		public Action<FGContractEvent> OnEventHappened { get; set; }

		public Action<FGContractEvent> OnEventRegistered { get; set; }

		public List<FGContractEvent> CurrentSessionEvents { get; private set; } = new List<FGContractEvent>();


		public FGContractEventsRecorder()
		{
			OnEventHappened = (Action<FGContractEvent>)Delegate.Combine(OnEventHappened, new Action<FGContractEvent>(AppendEventToSession));
		}

		public void AppendEventToSession(FGContractEvent contractEvent)
		{
			if (!sessionActive)
			{
				Debug.LogWarning((object)("FGContractEventsRecorder: Attempted to append event " + contractEvent.EventKey + " to session, but session is not active."));
				return;
			}
			Debug.LogWarning((object)("FGContractEventsRecorder: Appending event " + contractEvent.EventKey + " to session."));
			CurrentSessionEvents.Add(contractEvent);
			OnEventRegistered?.Invoke(contractEvent);
		}

		public void StartSession()
		{
			Debug.Log((object)"FGContractEventsRecorder: Starting session.");
			sessionActive = true;
			CurrentSessionEvents.Clear();
			ListenToClassicH3Events();
		}

		public void WipeSession()
		{
			Debug.Log((object)"FGContractEventsRecorder: Wiping session.");
			sessionActive = false;
			CurrentSessionEvents.Clear();
			StopListeningToClassicH3Events();
		}

		private void ListenToClassicH3Events()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			GM.CurrentSceneSettings.SosigKillEvent += new SosigKill(OnSosigKill);
			GM.CurrentSceneSettings.SosigMadeEnemyWithEvent += new SosigMadeEnemyWith(OnSosigMadeEnemyWith);
			GM.CurrentSceneSettings.SosigAlertEvent += new SosigAlert(OnSosigAlert);
			GM.CurrentSceneSettings.ShotFiredEvent += new ShotFired(OnShotFired);
			GM.CurrentSceneSettings.SosiggunFiredEvent += new SosiggunFired(OnSosiggunFired);
			GM.CurrentSceneSettings.SosigFleeFromEvent += new SosigFleeFrom(OnSosigFleeFrom);
		}

		private void OnSosigKill(Sosig s)
		{
			FGContractEvent fGContractEvent = new FGContractEvent();
			fGContractEvent.EventKey = "OnSosigKill";
			fGContractEvent.OnSosigKill = new FGContractEvent.OnSosigKillEvent
			{
				Sosig = s
			};
			OnEventHappened?.Invoke(fGContractEvent);
		}

		private void OnSosigMadeEnemyWith(Sosig S, int iff)
		{
			FGContractEvent fGContractEvent = new FGContractEvent();
			fGContractEvent.EventKey = "OnSosigMadeEnemyWith";
			fGContractEvent.OnSosigMadeEnemyWith = new FGContractEvent.OnSosigMadeEnemyWithEvent
			{
				Sosig = S,
				IFF = iff
			};
			OnEventHappened?.Invoke(fGContractEvent);
		}

		private void OnSosigAlert(Sosig s, Vector3 p)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			FGContractEvent fGContractEvent = new FGContractEvent();
			fGContractEvent.EventKey = "OnSosigAlert";
			fGContractEvent.OnSosigAlert = new FGContractEvent.OnSosigAlertEvent
			{
				Sosig = s,
				Position = p
			};
			OnEventHappened?.Invoke(fGContractEvent);
		}

		private void OnShotFired(FVRFireArm firearm)
		{
			FGContractEvent fGContractEvent = new FGContractEvent();
			fGContractEvent.EventKey = "OnShotFired";
			fGContractEvent.OnShotFired = new FGContractEvent.OnShotFiredEvent
			{
				Firearm = firearm
			};
			OnEventHappened?.Invoke(fGContractEvent);
		}

		private void OnSosiggunFired(SosigWeapon weapon)
		{
			FGContractEvent fGContractEvent = new FGContractEvent();
			fGContractEvent.EventKey = "OnSosiggunFired";
			fGContractEvent.OnSosiggunFired = new FGContractEvent.OnSosiggunFiredEvent
			{
				Weapon = weapon
			};
			OnEventHappened?.Invoke(fGContractEvent);
		}

		private void OnSosigFleeFrom(Sosig S, int iff)
		{
			FGContractEvent fGContractEvent = new FGContractEvent();
			fGContractEvent.EventKey = "OnSosigFleeFrom";
			fGContractEvent.OnSosigMadeEnemyWith = new FGContractEvent.OnSosigMadeEnemyWithEvent
			{
				Sosig = S,
				IFF = iff
			};
			OnEventHappened?.Invoke(fGContractEvent);
		}

		private void StopListeningToClassicH3Events()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Expected O, but got Unknown
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			GM.CurrentSceneSettings.SosigKillEvent -= new SosigKill(OnSosigKill);
			GM.CurrentSceneSettings.SosigMadeEnemyWithEvent -= new SosigMadeEnemyWith(OnSosigMadeEnemyWith);
			GM.CurrentSceneSettings.SosigAlertEvent -= new SosigAlert(OnSosigAlert);
			GM.CurrentSceneSettings.ShotFiredEvent -= new ShotFired(OnShotFired);
			GM.CurrentSceneSettings.SosiggunFiredEvent -= new SosiggunFired(OnSosiggunFired);
			GM.CurrentSceneSettings.SosigFleeFromEvent -= new SosigFleeFrom(OnSosigFleeFrom);
		}
	}
	public class FGContractTemplateFactory
	{
		private static List<FGContractTemplate> contractTemplates = new List<FGContractTemplate>();

		public static void RegisterTemplate(FGContractTemplate template)
		{
			FGContractTemplate fGContractTemplate = contractTemplates.FirstOrDefault((FGContractTemplate t) => t.TemplateID == template.TemplateID);
			if (fGContractTemplate != null)
			{
				contractTemplates.Remove(fGContractTemplate);
			}
			contractTemplates.Add(template);
		}

		public static FGContractTemplate GetTemplateForFactionAndReputation(string factionID, float reputation)
		{
			List<FGContractTemplate> list = new List<FGContractTemplate>();
			for (int i = 0; i < contractTemplates.Count; i++)
			{
				FGContractTemplate fGContractTemplate = contractTemplates[i];
				if (fGContractTemplate.HiringFactionID != factionID)
				{
					continue;
				}
				bool flag = fGContractTemplate.ReputationRequirements.Count == 0;
				for (int j = 0; j < fGContractTemplate.ReputationRequirements.Count; j++)
				{
					FGContract.ReputationRequirement reputationRequirement = fGContractTemplate.ReputationRequirements[j];
					if (reputationRequirement.FactionID == factionID && reputation >= reputationRequirement.MinimumRep && reputation <= reputationRequirement.MaximumRep)
					{
						flag = true;
						break;
					}
				}
				if (flag)
				{
					list.Add(fGContractTemplate);
				}
			}
			return (list.Count > 0) ? list[Random.Range(0, list.Count)] : null;
		}
	}
	[Serializable]
	public class FGContractTemplate
	{
		public string TemplateID;

		public string HiringFactionID;

		public string Infraction;

		public int MinGuards;

		public int MaxGuards;

		public List<SosigEnemyID> PossibleGuardTypes;

		public List<string> PossibleGuardFactionIDs;

		public int MinTargets = 1;

		public int MaxTargets;

		public List<SosigEnemyID> PossibleTargetTypes;

		public List<string> PossibleTargetFactionIDs;

		public int MinExtras;

		public int MaxExtras;

		public List<SosigEnemyID> PossibleExtraTypes;

		public List<string> PossibleExtrasFactionIDs;

		public List<string> PossibleScenes;

		public List<string> PossibleSceneCivConfigs;

		public List<string> PossibleSceneEnemConfigs;

		public int MaxConstraints = 3;

		public List<FGContract.ConstraintAndReward> PossibleConstraints = new List<FGContract.ConstraintAndReward>();

		public int MinCompensation;

		public int MaxCompensation;

		public int MinHoursLimit = 3;

		public int MaxHoursLimit = 8;

		public List<FGContract.ReputationReward> RepRewards = new List<FGContract.ReputationReward>();

		public List<FGContract.ReputationRequirement> ReputationRequirements = new List<FGContract.ReputationRequirement>();

		public FGContract GenerateContract()
		{
			if (!ValidateContract())
			{
				Debug.LogError((object)"You made a mistake Bucko! Contract invalid.");
				return null;
			}
			int num = Random.Range(MinCompensation, MaxCompensation);
			FGContract fGContract = new FGContract
			{
				uniqueID = Random.Range(0, 10000000),
				DisplayName = $"{HiringFactionID}: ${num}",
				TargetFirstName = "First",
				TargetLastName = "Last",
				Infraction = Infraction,
				HiringFactionID = HiringFactionID,
				Compensation = num,
				SceneName = PossibleScenes[Random.Range(0, PossibleScenes.Count)],
				SceneCivConfigName = GetRandomFromListOrEmpty(PossibleSceneCivConfigs),
				SceneEnemyConfigName = GetRandomFromListOrEmpty(PossibleSceneEnemConfigs),
				ConstraintsAndRewards = GenerateConstraints(MaxConstraints),
				expirationTime = FGTimeSystem.Instance.GetInGameTimeAfterRealDuration(TimeSpan.FromHours(Random.Range(MinHoursLimit, MaxHoursLimit))).ToString("o"),
				ReputationRequirements = ReputationRequirements,
				hasEnded = false,
				isAccepted = false,
				hasSucceeded = false,
				hasFailed = false,
				ReputationRewards = RepRewards
			};
			AssignTargetsGuardsExtras(fGContract);
			AssignFactionsTargetsGuardsExtras(fGContract);
			fGContract.ConvertToSerializable();
			return fGContract;
		}

		private bool ValidateContract()
		{
			bool result = PossibleScenes.Count > 0;
			if (MinTargets < 1)
			{
				Debug.LogError((object)"I expected MinTargets must be at least 1.");
			}
			return result;
		}

		private void AssignTargetsGuardsExtras(FGContract contract)
		{
			int num = Random.Range(MinTargets, MaxTargets + 1);
			int num2 = Random.Range(MinGuards, MaxGuards + 1);
			int num3 = Random.Range(MinExtras, MaxExtras + 1);
			Debug.Log((object)$"Assigning {num} targets, {num2} guards, {num3} extras.");
			Debug.Log((object)("PossibleTargetTypes: " + string.Join(", ", PossibleTargetTypes.Select((SosigEnemyID type) => ((object)(SosigEnemyID)(ref type)).ToString()).ToArray())));
			Debug.Log((object)("PossibleGuardTypes: " + string.Join(", ", PossibleGuardTypes.Select((SosigEnemyID type) => ((object)(SosigEnemyID)(ref type)).ToString()).ToArray())));
			contract._TargetIDs["targets"] = SelectRandomSubset(PossibleTargetTypes, num);
			contract._GuardIDs["guards"] = SelectRandomSubset(PossibleGuardTypes, num2);
			contract._ExtrasIDs["extras"] = SelectRandomSubset(PossibleExtraTypes, num3);
		}

		private void AssignFactionsTargetsGuardsExtras(FGContract contract)
		{
			Debug.Log((object)("PossibleTargetFactionIDs: " + string.Join(", ", PossibleTargetFactionIDs.ToArray())));
			Debug.Log((object)("PossibleGuardFactionIDs: " + string.Join(", ", PossibleGuardFactionIDs.ToArray())));
			contract._Faction_Target["targets"] = GetRandomFromListOrEmpty(PossibleTargetFactionIDs);
			contract._Faction_Guards["guards"] = GetRandomFromListOrEmpty(PossibleGuardFactionIDs);
			contract._Faction_Extras["extras"] = GetRandomFromListOrEmpty(PossibleExtrasFactionIDs);
		}

		private string GetRandomFromListOrEmpty(List<string> list)
		{
			return (list != null && list.Count > 0) ? list[Random.Range(0, list.Count)] : "";
		}

		private List<SosigEnemyID> SelectRandomSubset(List<SosigEnemyID> source, int count)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			List<SosigEnemyID> list = new List<SosigEnemyID>();
			if (source.Count == 0)
			{
				return list;
			}
			for (int i = 0; i < count; i++)
			{
				list.Add(source[Random.Range(0, source.Count)]);
			}
			return list;
		}

		private List<FGContract.ConstraintAndReward> GenerateConstraints(int maxConstraints)
		{
			List<FGContract.ConstraintAndReward> list = new List<FGContract.ConstraintAndReward>();
			if (PossibleConstraints.Count > 0)
			{
				list.AddRange(PossibleConstraints.OrderBy((FGContract.ConstraintAndReward _) => Random.value).Take(Mathf.Min(maxConstraints, PossibleConstraints.Count)));
			}
			return list;
		}
	}
	public class FGContractManager : MonoBehaviour
	{
		public struct Config
		{
			public List<FGContract> activeContracts;

			public List<FGContract> availableContracts;

			public List<FGContract> completedContracts;
		}

		public static FGContractManager Instance;

		private List<FGContract> activeContracts = new List<FGContract>();

		private List<FGContract> availableContracts = new List<FGContract>();

		private List<FGContract> completedContracts = new List<FGContract>();

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		public void InitFromConfig(Config config)
		{
			if (config.activeContracts == null)
			{
				Debug.LogWarning((object)"activeContracts is null, initializing as empty list.");
				config.activeContracts = new List<FGContract>();
			}
			if (config.availableContracts == null)
			{
				Debug.LogWarning((object)"availableContracts is null, initializing as empty list.");
				config.availableContracts = new List<FGContract>();
			}
			if (config.completedContracts == null)
			{
				Debug.LogWarning((object)"completedContracts is null, initializing as empty list.");
				config.completedContracts = new List<FGContract>();
			}
			activeContracts = config.activeContracts;
			availableContracts = config.availableContracts;
			completedContracts = config.completedContracts;
			foreach (FGContract activeContract in activeContracts)
			{
				if (activeContract != null)
				{
					activeContract.PrepareFromLoad();
				}
				else
				{
					Debug.LogWarning((object)"Found null contract in activeContracts list.");
				}
			}
			foreach (FGContract availableContract in availableContracts)
			{
				if (availableContract != null)
				{
					availableContract.PrepareFromLoad();
				}
				else
				{
					Debug.LogWarning((object)"Found null contract in availableContracts list.");
				}
			}
			foreach (FGContract completedContract in completedContracts)
			{
				if (completedContract != null)
				{
					completedContract.PrepareFromLoad();
				}
				else
				{
					Debug.LogWarning((object)"Found null contract in completedContracts list.");
				}
			}
		}

		public Config GetConfig()
		{
			foreach (FGContract activeContract in activeContracts)
			{
				activeContract.PrepareForSave();
			}
			foreach (FGContract availableContract in availableContracts)
			{
				availableContract.PrepareForSave();
			}
			foreach (FGContract completedContract in completedContracts)
			{
				completedContract.PrepareForSave();
			}
			Config result = default(Config);
			result.activeContracts = activeContracts;
			result.availableContracts = availableContracts;
			result.completedContracts = completedContracts;
			return result;
		}

		public List<FGContract> GetActiveContracts()
		{
			return activeContracts;
		}

		public List<FGContract> GetAvailableContracts()
		{
			return availableContracts;
		}

		public List<FGContract> GetCompletedContracts()
		{
			return completedContracts;
		}

		private void Start()
		{
		}

		private void OnEnable()
		{
			FGTimeSystem.Instance.OnTimeAdvanced += CheckContractExpirations;
			FGTimeSystem.Instance.OnTimeAdvanced += MaybeAddNewContract;
		}

		private void OnDisable()
		{
			FGTimeSystem.Instance.OnTimeAdvanced -= CheckContractExpirations;
			FGTimeSystem.Instance.OnTimeAdvanced -= MaybeAddNewContract;
		}

		private void GenerateContract(string factionID, float forPlayerReputation)
		{
			FGContractTemplate templateForFactionAndReputation = FGContractTemplateFactory.GetTemplateForFactionAndReputation(factionID, forPlayerReputation);
			if (templateForFactionAndReputation == null)
			{
				Debug.LogWarning((object)$"No contract template found for faction {factionID} with reputation {forPlayerReputation}");
				return;
			}
			FGContract fGContract = templateForFactionAndReputation.GenerateContract();
			if (fGContract == null)
			{
				Debug.LogError((object)("Failed to generate contract from template " + templateForFactionAndReputation.TemplateID + " for faction " + factionID));
				return;
			}
			availableContracts.Add(fGContract);
			Debug.Log((object)("Generated contract from template: " + fGContract.DisplayName + " for faction " + fGContract.HiringFactionID));
		}

		public void AcceptContract(int uniqueID)
		{
			FGContract fGContract = availableContracts.FirstOrDefault((FGContract c) => c.uniqueID == uniqueID);
			if (fGContract != null)
			{
				activeContracts.Add(fGContract);
				availableContracts.Remove(fGContract);
				Debug.Log((object)$"Contract with ID {uniqueID} has been accepted.");
			}
			else
			{
				Debug.LogWarning((object)$"No contract found with uniqueID {uniqueID}.");
			}
		}

		public void RejectContract(int uniqueID)
		{
			FGContract fGContract = activeContracts.FirstOrDefault((FGContract c) => c.uniqueID == uniqueID);
			if (fGContract != null)
			{
				activeContracts.Remove(fGContract);
				Debug.Log((object)$"Contract with ID {uniqueID} has been rejected.");
			}
			else
			{
				Debug.LogWarning((object)$"No contract found with uniqueID {uniqueID}.");
			}
		}

		private void CheckContractExpirations(DateTime currentTime)
		{
			for (int num = activeContracts.Count - 1; num >= 0; num--)
			{
				if (IsContractExpired(activeContracts[num]))
				{
					Debug.Log((object)("Contract expired: " + activeContracts[num].DisplayName));
					AddToCompletedContracts(activeContracts[num]);
					activeContracts.RemoveAt(num);
				}
			}
			for (int num2 = availableContracts.Count - 1; num2 >= 0; num2--)
			{
				if (IsContractExpired(availableContracts[num2]))
				{
					Debug.Log((object)("Contract expired: " + availableContracts[num2].DisplayName));
					availableContracts.RemoveAt(num2);
				}
			}
		}

		private void MaybeAddNewContract(DateTime currentTime)
		{
			if (availableContracts.Count < 3)
			{
				GenerateNewContract();
			}
		}

		private void AddToCompletedContracts(FGContract contract)
		{
			completedContracts.Insert(0, contract);
			int num = 10;
			while (completedContracts.Count > num)
			{
				completedContracts.RemoveAt(num);
			}
		}

		private bool IsContractExpired(FGContract contract)
		{
			DateTime currentTime = FGTimeSystem.Instance.CurrentTime;
			DateTime expirationDateTime = contract.ExpirationDateTime;
			return currentTime >= expirationDateTime;
		}

		private void GenerateNewContract()
		{
			GenerateContract("Hollys", 0f);
		}

		public void EvaluateAndUpdateActiveContractsOnEvent(FGContractEvent contractEvent)
		{
			Debug.LogWarning((object)("Evaluating contracts on event " + contractEvent.EventKey));
			ContractEvaluationContext contractEvaluationContext = new ContractEvaluationContext();
			contractEvaluationContext.eventsInSession = FG_GM.Instance.eventsRecorder.CurrentSessionEvents;
			for (int num = activeContracts.Count - 1; num >= 0; num--)
			{
				FGContract fGContract = (contractEvaluationContext.myContract = activeContracts[num]);
				for (int i = 0; i < fGContract.ConstraintsAndRewards.Count; i++)
				{
					FGContract.ConstraintAndReward constraintAndReward = fGContract.ConstraintsAndRewards[i];
					IContractConstraint constraint = ConstraintFactory.GetConstraint(constraintAndReward.ConstraintID);
					if (constraint == null)
					{
						Debug.LogWarning((object)("Constraint " + constraintAndReward.ConstraintID + " not found."));
					}
					else
					{
						constraint.EvaluateAndUpdateContract(contractEvaluationContext);
					}
				}
			}
		}

		public void CheckContractCompletionOnAreaExit()
		{
			ContractEvaluationContext contractEvaluationContext = new ContractEvaluationContext();
			contractEvaluationContext.eventsInSession = FG_GM.Instance.eventsRecorder.CurrentSessionEvents;
			for (int num = activeContracts.Count - 1; num >= 0; num--)
			{
				FGContract fGContract = (contractEvaluationContext.myContract = activeContracts[num]);
				contractEvaluationContext.isFinalCheck = true;
				bool flag = false;
				bool flag2 = false;
				int num2 = fGContract.ConstraintsAndRewards.Count((FGContract.ConstraintAndReward c) => !c.optional);
				int num3 = 0;
				int num4 = 0;
				for (int i = 0; i < fGContract.ConstraintsAndRewards.Count; i++)
				{
					FGContract.ConstraintAndReward constraintAndReward = fGContract.ConstraintsAndRewards[i];
					IContractConstraint constraint = ConstraintFactory.GetConstraint(constraintAndReward.ConstraintID);
					if (constraint == null)
					{
						Debug.LogWarning((object)("Constraint " + constraintAndReward.ConstraintID + " not found."));
						continue;
					}
					constraint.EvaluateAndUpdateContract(contractEvaluationContext);
					FGContract.ConstraintAndReward constraintAndReward2 = fGContract.ConstraintsAndRewards[i];
					if (constraintAndReward2.constraintSuccess)
					{
						num4 += constraintAndReward.rewardAddedIfSucceed;
						if (!constraintAndReward.optional)
						{
							num3++;
						}
					}
					else if (constraintAndReward2.constraintViolated)
					{
						num4 -= constraintAndReward.rewardSubtractedIfFail;
						if (!constraintAndReward2.optional)
						{
							Debug.LogWarning((object)("Contract '" + fGContract.DisplayName + "' failed due to constraint " + constraintAndReward.ConstraintID));
							flag2 = true;
							break;
						}
					}
					else if (ConstraintFactory.IsContractInAnyPosse(fGContract) && !constraintAndReward2.optional)
					{
						flag2 = true;
						break;
					}
				}
				if (ConstraintFactory.IsContractInAnyPosse(fGContract) && num3 < num2)
				{
					flag2 = true;
				}
				else if (num3 >= num2)
				{
					flag = true;
					num4 += fGContract.Compensation;
				}
				if (num4 < 0)
				{
					num4 = 0;
				}
				if (flag)
				{
					FGBank.TransactionRecord transaction = new FGBank.TransactionRecord(num4, fGContract.DisplayName);
					FG_GM.Instance.bank.ProcessTransaction(transaction, forceDecrement: false);
					foreach (FGContract.ReputationReward reputationReward in fGContract.ReputationRewards)
					{
						FG_GM.Instance.factionStance.TryAdjustReputation(reputationReward.FactionID, reputationReward.Rep);
					}
					Debug.LogWarning((object)$"Contract '{fGContract.uniqueID}' completed! Total reward: {num4}");
					AddToCompletedContracts(fGContract);
					activeContracts.RemoveAt(num);
				}
				else if (flag2)
				{
					Debug.LogWarning((object)$"Contract '{fGContract.uniqueID}' failed!");
					AddToCompletedContracts(fGContract);
					activeContracts.RemoveAt(num);
				}
			}
		}
	}
	[Serializable]
	public class FGLoadManifest
	{
		public List<FGMap> maps;

		public List<FGFaction> factions;

		public List<FGContractTemplate> contractTemplates;
	}
	public class FGExternalLoader
	{
		public static void LoadManifestsFromBepinex()
		{
			try
			{
				string pluginPath = Paths.PluginPath;
				if (!Directory.Exists(pluginPath))
				{
					return;
				}
				string[] directories = Directory.GetDirectories(pluginPath);
				foreach (string text in directories)
				{
					string text2 = Path.Combine(text, "fgLoadManifest.json");
					if (!File.Exists(text2))
					{
						continue;
					}
					FGLoadManifest fGLoadManifest = ExtractManifestFromFile(text2);
					if (fGLoadManifest == null)
					{
						continue;
					}
					if (fGLoadManifest.maps != null)
					{
						foreach (FGMap map in fGLoadManifest.maps)
						{
							FG_GM.Instance.MapContainer?.RegisterMap(map, text);
						}
					}
					else
					{
						Debug.LogError((object)("No maps found in manifest: " + text2));
					}
					if (fGLoadManifest.factions != null)
					{
						foreach (FGFaction faction in fGLoadManifest.factions)
						{
							FG_GM.Instance.factionStance?.RegisterFaction(faction);
						}
					}
					else
					{
						Debug.LogError((object)("No factions found in manifest: " + text2));
					}
					if (fGLoadManifest.contractTemplates != null)
					{
						foreach (FGContractTemplate contractTemplate in fGLoadManifest.contractTemplates)
						{
							FGContractTemplateFactory.RegisterTemplate(contractTemplate);
						}
					}
					else
					{
						Debug.LogError((object)("No contract templates found in manifest: " + text2));
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to load manifests from Bepinex: " + ex.Message));
			}
		}

		public static FGLoadManifest ExtractManifestFromFile(string fullFileName)
		{
			try
			{
				string text = File.ReadAllText(fullFileName);
				return JsonUtility.FromJson<FGLoadManifest>(text);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to load manifest from " + fullFileName + ": " + ex.Message));
				return null;
			}
		}
	}
	[Serializable]
	public class FGState
	{
		[SerializeField]
		private List<string> valid_homes = new List<string>();

		[SerializeField]
		private List<string> valid_areas = new List<string>();

		public string timeSysConfig;

		public string contractManConfig;

		public string bankConfig;

		public string factionStanceConfig;

		public static FGState GetDefaultSave()
		{
			FGState fGState = new FGState();
			fGState.AddValidHome("IndoorRange_Updated");
			fGState.AddValidArea("Grillhouse_2Story");
			return fGState;
		}

		public void AddValidArea(string sceneName)
		{
			if (!valid_areas.Contains(sceneName))
			{
				valid_areas.Add(sceneName);
			}
		}

		public bool IsValidArea(string sceneName)
		{
			return valid_areas.Contains(sceneName);
		}

		public bool IsValidHome(string sceneName)
		{
			return valid_homes.Contains(sceneName);
		}

		public void AddValidHome(string sceneName)
		{
			if (!valid_homes.Contains(sceneName))
			{
				valid_homes.Add(sceneName);
			}
		}
	}
	public class FG_GM : MonoBehaviour
	{
		public FGSceneManip mapLoader;

		public FGContractManager contractMan;

		public FGTimeSystem timeSys;

		public FGBank bank;

		public FGFactionStance factionStance;

		public FGContractEventsRecorder eventsRecorder;

		public bool causedInTransitioningLevels = false;

		public string lastTransitionedToSceneName = "";

		private string saveSlotName = "SaveSlot0";

		public string wristUiSpawnId = "NGA_FgWristUi";

		private FGContract contractForTransition;

		public static FG_GM Instance { get; private set; }

		public FGState saveState { get; private set; }

		public FGMapsContainer MapContainer { get; private set; }

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
				Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject);
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void Start()
		{
			timeSys = ((Component)this).gameObject.AddComponent<FGTimeSystem>();
			mapLoader = ((Component)this).gameObject.AddComponent<FGSceneManip>();
			contractMan = ((Component)this).gameObject.AddComponent<FGContractManager>();
			MapContainer = new FGMapsContainer();
			bank = new FGBank();
			factionStance = new FGFactionStance();
			eventsRecorder = new FGContractEventsRecorder();
			SceneManager.sceneLoaded += OnSceneLoaded;
			if (!GM.CurrentSceneSettings.QuitReceivers.Contains(((Component)this).gameObject))
			{
				GM.CurrentSceneSettings.QuitReceivers.Add(((Component)this).gameObject);
			}
			Init();
			FGExternalLoader.LoadManifestsFromBepinex();
		}

		private void Init()
		{
			((MonoBehaviour)this).StartCoroutine(SpawnWristMenuWithRetries(40, 3f));
			InitSaveState();
		}

		private void InitSaveState()
		{
			try
			{
				if (saveState == null)
				{
					FGFileIoHandler.LoadFGState(saveSlotName, out var state);
					if (state != null)
					{
						saveState = state;
						InitTimeSysFromSave();
						InitContractManFromSave();
						InitBankFromSave();
						InitFactionStanceFromSave();
					}
					else
					{
						saveState = FGState.GetDefaultSave();
						SaveGameState();
					}
				}
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Exception in InitSaveState: " + ex.Message + "\n" + ex.StackTrace));
			}
		}

		private void InitTimeSysFromSave()
		{
			if (saveState == null || string.IsNullOrEmpty(saveState.timeSysConfig))
			{
				Debug.LogError((object)"Save state or time system config is null. Cannot initialize time system.");
				return;
			}
			FGTimeSystem.Config config = JsonUtility.FromJson<FGTimeSystem.Config>(saveState.timeSysConfig);
			timeSys.InitFromConfig(config);
		}

		private void InitContractManFromSave()
		{
			if (saveState == null || string.IsNullOrEmpty(saveState.contractManConfig))
			{
				Debug.LogError((object)"Save state or contract manager config is null. Cannot initialize contract manager.");
				return;
			}
			FGContractManager.Config config = JsonUtility.FromJson<FGContractManager.Config>(saveState.contractManConfig);
			contractMan.InitFromConfig(config);
		}

		private void InitBankFromSave()
		{
			if (saveState == null || string.IsNullOrEmpty(saveState.bankConfig))
			{
				Debug.LogError((object)"Save state or bank config is null. Cannot initialize bank.");
				return;
			}
			FGBank.Config config = JsonUtility.FromJson<FGBank.Config>(saveState.bankConfig);
			bank.InitFromConfig(config);
		}

		private void InitFactionStanceFromSave()
		{
			if (saveState == null || string.IsNullOrEmpty(saveState.factionStanceConfig))
			{
				Debug.LogError((object)"Save state or faction stance config is null. Cannot initialize faction stance.");
				return;
			}
			FGFactionStance.Config config = JsonUtility.FromJson<FGFactionStance.Config>(saveState.factionStanceConfig);
			factionStance.InitFromConfig(config);
		}

		private void SaveGameState()
		{
			saveState.timeSysConfig = JsonUtility.ToJson((object)timeSys.GetConfig());
			saveState.contractManConfig = JsonUtility.ToJson((object)contractMan.GetConfig());
			saveState.bankConfig = JsonUtility.ToJson((object)bank.GetConfig());
			saveState.factionStanceConfig = JsonUtility.ToJson((object)factionStance.GetConfig());
			FGFileIoHandler.SaveFGState(saveSlotName, saveState);
		}

		private bool VerifyTransitionOk(string goto_scene)
		{
			if (causedInTransitioningLevels)
			{
				return false;
			}
			if (!Application.CanStreamedLevelBeLoaded(goto_scene))
			{
				Debug.LogError((object)"Scene name requested does not exist.");
				return false;
			}
			if (!saveState.IsValidHome(goto_scene) && !saveState.IsValidArea(goto_scene))
			{
				Debug.LogError((object)"Character not allowed to travel to that area.");
				return false;
			}
			return true;
		}

		private void HandleContractCompletion()
		{
			contractMan.CheckContractCompletionOnAreaExit();
			eventsRecorder.WipeSession();
			FGContractEventsRecorder fGContractEventsRecorder = eventsRecorder;
			fGContractEventsRecorder.OnEventRegistered = (Action<FGContractEvent>)Delegate.Remove(fGContractEventsRecorder.OnEventRegistered, new Action<FGContractEvent>(contractMan.EvaluateAndUpdateActiveContractsOnEvent));
		}

		public void TransitionToLevel(string goto_scene)
		{
			if (VerifyTransitionOk(goto_scene))
			{
				VaultSaveBeforeTransition(goto_scene);
				HandleContractCompletion();
				causedInTransitioningLevels = true;
				SteamVR_LoadLevel.Begin(goto_scene, false, 0.5f, 0f, 0f, 0f, 1f);
			}
		}

		public void TransitionToLevelFromContract(FGContract contract)
		{
			if (!causedInTransitioningLevels)
			{
				string sceneName = contract.SceneName;
				TransitionToLevel(sceneName);
				if (causedInTransitioningLevels)
				{
					contractForTransition = contract;
				}
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			Debug.LogWarning((object)"-------> OnSceneLoaded");
			if (!GM.CurrentSceneSettings.QuitReceivers.Contains(((Component)this).gameObject))
			{
				GM.CurrentSceneSettings.QuitReceivers.Add(((Component)this).gameObject);
			}
			((MonoBehaviour)this).StartCoroutine(SpawnWristMenuWithRetries(60, 1f));
			SaveGameState();
			if (causedInTransitioningLevels)
			{
				eventsRecorder.StartSession();
				FGContractEventsRecorder fGContractEventsRecorder = eventsRecorder;
				fGContractEventsRecorder.OnEventRegistered = (Action<FGContractEvent>)Delegate.Combine(fGContractEventsRecorder.OnEventRegistered, new Action<FGContractEvent>(contractMan.EvaluateAndUpdateActiveContractsOnEvent));
				if (saveState.IsValidArea(((Scene)(ref scene)).name))
				{
					if (contractForTransition == null)
					{
						((MonoBehaviour)this).StartCoroutine(TryWithRetries(() => mapLoader.InitArea(saveSlotName, ((Scene)(ref scene)).name), 10, 1f));
					}
					else
					{
						((MonoBehaviour)this).StartCoroutine(TryWithRetries(() => mapLoader.InitAreaFromContract(saveSlotName, contractForTransition), 10, 1f));
						contractForTransition = null;
					}
				}
				else if (saveState.IsValidHome(((Scene)(ref scene)).name))
				{
					((MonoBehaviour)this).StartCoroutine(TryWithRetries(() => mapLoader.InitHome(saveSlotName, ((Scene)(ref scene)).name), 10, 1f));
				}
				causedInTransitioningLevels = false;
				lastTransitionedToSceneName = ((Scene)(ref scene)).name;
			}
			else
			{
				lastTransitionedToSceneName = "";
			}
		}

		private void VaultSaveBeforeTransition(string goto_scene)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (lastTransitionedToSceneName != name)
			{
				Debug.LogWarning((object)("Scene we're traveling from was not arrived at through FG_GM - FG_GM last took us to " + lastTransitionedToSceneName));
			}
			if (lastTransitionedToSceneName == name)
			{
				if (saveState.IsValidHome(lastTransitionedToSceneName))
				{
					SaveHomeSceneConfigToFile(name);
					SavePlayerQuickbetToFile();
				}
				else if (saveState.IsValidArea(lastTransitionedToSceneName))
				{
					SavePlayerQuickbetToFile();
				}
				else
				{
					Debug.LogError((object)("We're transitioning from an FG traveled-to scene that's neither area nor home: " + name));
				}
			}
			else
			{
				Debug.LogWarning((object)("We're not transitioning from an FG traveled-to scene: " + name));
			}
		}

		private void QUIT()
		{
			if (saveState.IsValidHome(lastTransitionedToSceneName))
			{
				SaveHomeSceneConfigToFile(lastTransitionedToSceneName);
				SavePlayerQuickbetToFile();
			}
			SaveGameState();
		}

		public void SaveHomeSceneConfigToFile(string currSceneName)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			VaultFile val = new VaultFile();
			if (!VaultSystem.FindAndScanObjectsInScene(val) || !FGFileIoHandler.SaveHomeVaultFile(saveSlotName, currSceneName, val))
			{
				Debug.LogError((object)"Failed to scan or write player QB durin level transition.");
			}
			else
			{
				Debug.LogWarning((object)("Succeeded saving home name: " + currSceneName));
			}
		}

		public void SavePlayerQuickbetToFile()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			VaultFile val = new VaultFile();
			if (!VaultSystem.FindAndScanObjectsInQuickbelt(val))
			{
				Debug.LogWarning((object)"Empty quickbelt!");
			}
			if (!FGFileIoHandler.SavePlayerQuickbelt(saveSlotName, val))
			{
				Debug.LogError((object)"Failed to write player QB.");
			}
			else
			{
				Debug.LogWarning((object)"Succeeded saving player QB.");
			}
		}

		public static IEnumerator TryWithRetries(Func<bool> retryMethod, int maxRetries, float delay)
		{
			int attempts = 0;
			while (attempts < maxRetries)
			{
				if (retryMethod())
				{
					Debug.Log((object)$"Operation succeeded on attempt {attempts + 1}.");
					yield break;
				}
				attempts++;
				Debug.LogWarning((object)$"Operation failed. Retrying {attempts}/{maxRetries} in {delay} seconds...");
				yield return (object)new WaitForSeconds(delay);
			}
			Debug.LogError((object)$"Operation failed after {maxRetries} attempts.");
		}

		private bool SpawnWristMenu()
		{
			//IL_003d: 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)
			if (!IM.OD.TryGetValue(wristUiSpawnId, out var value))
			{
				Debug.LogError((object)(wristUiSpawnId + " not found in IM.OD!"));
				return false;
			}
			try
			{
				GameObject val = Object.Instantiate<GameObject>(((AnvilAsset)value).GetGameObject(), Vector3.zero, Quaternion.identity);
			}
			catch (Exception ex)
			{
				Debug.LogError((object)("Failed to spawn wrist menu: " + ex.Message));
				return false;
			}
			Debug.LogWarning((object)(wristUiSpawnId + " supposedly spawned"));
			return true;
		}

		private IEnumerator SpawnWristMenuWithRetries(int maxRetries, float delay)
		{
			int attempts = 0;
			bool finalCheck = false;
			while (attempts < maxRetries)
			{
				if (finalCheck)
				{
					FGWristUi2[] wristUIs = Object.FindObjectsOfType<FGWristUi2>();
					if (wristUIs.Length != 0)
					{
						for (int i = 1; i < wristUIs.Length; i++)
						{
							Object.Destroy((Object)(object)((Component)wristUIs[i]).gameObject);
						}
						Debug.Log((object)$"Wrist menu spawned successfully for sure on attempt {attempts + 1}.");
						yield break;
					}
					finalCheck = false;
				}
				if (SpawnWristMenu())
				{
					Debug.Log((object)$"Wrist menu spawned successfully on attempt {attempts + 1}. Checking...");
					finalCheck = true;
					yield return (object)new WaitForSeconds(delay);
				}
				attempts++;
				Debug.LogWarning((object)$"Wrist menu spawn failed. Retrying {attempts}/{maxRetries} in {delay} seconds...");
				yield return (object)new WaitForSeconds(delay);
			}
			Debug.LogError((object)$"Wrist menu failed to spawn after {maxRetries} attempts.");
		}
	}
	public class FGMapFactionAssigner
	{
		private Dictionary<string, int> factionToIFF;

		private int nextIFF;

		public FGMapFactionAssigner()
		{
			factionToIFF = new Dictionary<string, int>();
			nextIFF = 1;
			factionToIFF["player"] = 0;
		}

		public int AssignIFF(string factionId)
		{
			if (factionToIFF.ContainsKey(factionId))
			{
				return factionToIFF[factionId];
			}
			if (nextIFF > 32)
			{
				Debug.LogError((object)"Exceeded maximum number of IFFs - seting to -3");
				return -3;
			}
			factionToIFF[factionId] = nextIFF;
			return nextIFF++;
		}

		public void SetSosigFriendlyToFaction(Sosig s, string factionId, bool isFriendly)
		{
			int num = AssignIFF(factionId);
			s.Priority.IFFChart[num] = isFriendly;
		}

		public void SetSosigThreatableToFaction(Sosig s, string factionId, bool isThreatable)
		{
			int num = AssignIFF(factionId);
			s.Priority.ThreatableChart[num] = isThreatable;
		}

		public static void MakeSosigThreatenableToAll(Sosig s)
		{
			for (int i = 0; i < s.Priority.ThreatableChart.Length; i++)
			{
				s.Priority.ThreatableChart[i] = true;
			}
		}
	}
	[Serializable]
	public class FGPaths
	{
		public List<Transform> Path;
	}
	[Serializable]
	public class FGSosigMandate
	{
		public Transform SpawnPoint;

		public FGPaths Path;

		public FGSosigManifest Manifest;
	}
	public class FGTrackedSosig
	{
		public Sosig SosigInstance;

		public FGPaths Path;

		public FGSosigManifest Manifest;
	}
	[Serializable]
	public class FGMap
	{
		public string sceneName;

		public string DisplayName;

		public int price = 0;

		public int mapType;

		public string defaultCivSceneConfigFileName;

		public string defaultEnemySceneConfigFileName;

		public List<string> otherSceneConfigFileNames = new List<string>();

		public FGMap(FGMap other)
		{
			sceneName = other.sceneName;
			DisplayName = other.DisplayName;
			price = other.price;
			mapType = other.mapType;
			defaultCivSceneConfigFileName = other.defaultCivSceneConfigFileName;
			defaultEnemySceneConfigFileName = other.defaultEnemySceneConfigFileName;
			IEnumerable<string> enumerable = other.otherSceneConfigFileNames;
			otherSceneConfigFileNames = new List<string>(enumerable ?? Enumerable.Empty<string>());
		}
	}
	public class FGMapsContainer
	{
		public List<FGMap> maps = new List<FGMap>();

		public bool IsHomeRegistered(string sceneName)
		{
			return maps.Exists((FGMap map) => map.sceneName == sceneName && map.mapType == 0);
		}

		public bool IsSceneRegistered(string sceneName)
		{
			return maps.Exists((FGMap map) => map.sceneName == sceneName);
		}

		public bool IsAreaRegistered(string sceneName)
		{
			return maps.Exists((FGMap map) => map.sceneName == sceneName && map.mapType == 1);
		}

		public int GetHomePrice(string sceneName)
		{
			return maps.Find((FGMap map) => map.sceneName == sceneName).price;
		}

		public void RegisterMap(FGMap map, string sourceFolderName)
		{
			if (map == null)
			{
				Debug.LogError((object)("Cannot register null map: " + sourceFolderName));
				return;
			}
			FGMap fGMap = maps.Find((FGMap m) => m.sceneName == map.sceneName);
			if (fGMap == null)
			{
				FGMap fGMap2 = new FGMap(map);
				maps.Add(fGMap2);
				fGMap2.defaultCivSceneConfigFileName = (string.IsNullOrEmpty(map.defaultCivSceneConfigFileName) ? string.Empty : Path.Combine(sourceFolderName, map.defaultCivSceneConfigFileName));
				fGMap2.defaultEnemySceneConfigFileName = (string.IsNullOrEmpty(map.defaultEnemySceneConfigFileName) ? string.Empty : Path.Combine(sourceFolderName, map.defaultEnemySceneConfigFileName));
			}
			else
			{
				fGMap.DisplayName = map.DisplayName;
				fGMap.price = map.price;
				fGMap.mapType = map.mapType;
				fGMap.defaultCivSceneConfigFileName = (string.IsNullOrEmpty(map.defaultCivSceneConfigFileName) ? string.Empty : Path.Combine(sourceFolderName, map.defaultCivSceneConfigFileName));
				fGMap.defaultEnemySceneConfigFileName = (string.IsNullOrEmpty(map.defaultEnemySceneConfigFileName) ? string.Empty : Path.Combine(sourceFolderName, map.defaultEnemySceneConfigFileName));
				fGMap.otherSceneConfigFileNames.AddRange(map.otherSceneConfigFileNames?.Select((string fileName) => string.IsNullOrEmpty(fileName) ? string.Empty : Path.Combine(sourceFolderName, fileName)) ?? Enumerable.Empty<string>());
			}
			FGMap fGMap3 = maps.Find((FGMap m) => m.sceneName == map.sceneName);
			if (!string.IsNullOrEmpty(fGMap3.defaultCivSceneConfigFileName))
			{
				FGFileIoHandler.CopyDefaultAreaConfigFile(fGMap3.sceneName, fGMap3.defaultCivSceneConfigFileName, isEnemy: false);
			}
			if (!string.IsNullOrEmpty(map.defaultEnemySceneConfigFileName))
			{
				FGFileIoHandler.CopyDefaultAreaConfigFile(fGMap3.sceneName, fGMap3.defaultEnemySceneConfigFileName, isEnemy: true);
			}
			IEnumerable<string> otherSceneConfigFileNames = fGMap3.otherSceneConfigFileNames;
			foreach (string item in otherSceneConfigFileNames ?? Enumerable.Empty<string>())
			{
				FGFileIoHandler.CopyAreaConfigFile(fGMap3.sceneName, item);
			}
			if (map.mapType == 1)
			{
				FG_GM.Instance.saveState.AddValidArea(fGMap3.sceneName);
			}
		}
	}
	public class FGSceneManip : MonoBehaviour
	{
		public List<FGTargetPosse> TargetPosses { get; private set; } = new List<FGTargetPosse>();


		private void Start()
		{
		}

		private void Update()
		{
		}

		public void ResetFGSceneManip()
		{
			TargetPosses.Clear();
		}

		public bool InitHome(string saveSlotName, string sceneName)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			ResetFGSceneManip();
			if (GM.IsAsyncLoading)
			{
				Debug.LogWarning((object)"Waiting InitHome, IsAsyncLoading aka vault loading.");
				return false;
			}
			string text = "";
			VaultSystem.ClearExistingSaveableObjects(true);
			if (!FGFileIoHandler.LoadHomeVaultFile(saveSlotName, sceneName, out var vf))
			{
				Debug.LogError((object)"Loading CGriller Home Scene file failed");
			}
			else if (VaultSystem.SpawnVaultFile(vf, ((Component)this).transform, false, false, true, ref text, Vector3.zero, (ReturnObjectListDelegate)null, true))
			{
				Debug.LogWarning((object)"Scene config loaded for home.");
			}
			else
			{
				Debug.LogError((object)("Failed to load scene with error: " + text + "\n on " + (object)vf));
			}
			GM.CurrentMovementManager.TeleportToPoint(GM.CurrentSceneSettings.DeathResetPoint.position, false);
			SpawnPlayerQbWithRetry(saveSlotName);
			return true;
		}

		public bool InitArea(string saveSlotName, string sceneName)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			ResetFGSceneManip();
			if (GM.IsAsyncLoading)
			{
				Debug.LogWarning((object)"Waiting InitArea, IsAsyncLoading aka vault loading.");
				return false;
			}
			VaultSystem.ClearExistingSaveableObjects(true);
			if (FGFileIoHandler.DoesAreaVaultFileExists(sceneName, FGFileIoHandler.default_civ_vault_name))
			{
				SpawnAreaVaultFile(sceneName, FGFileIoHandler.default_civ_vault_name);
			}
			((MonoBehaviour)this).StartCoroutine(FG_GM.TryWithRetries(delegate
			{
				if (PLtoFG.TransformPLtoFG())
				{
					ScanAndProcessModeObjects(null);
					return true;
				}
				return false;
			}, 15, 1f));
			GM.CurrentMovementManager.TeleportToPoint(GM.CurrentSceneSettings.DeathResetPoint.position, false);
			SpawnPlayerQbWithRetry(saveSlotName);
			return true;
		}

		public bool InitAreaFromContract(string saveSlotName, FGContract contract)
		{
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			ResetFGSceneManip();
			if (GM.IsAsyncLoading)
			{
				Debug.LogWarning((object)"Waiting InitArea, IsAsyncLoading aka vault loading.");
				return false;
			}
			string sceneName = contract.SceneName;
			string sceneCivConfigName = contract.SceneCivConfigName;
			VaultSystem.ClearExistingSaveableObjects(true);
			if (FGFileIoHandler.DoesAreaVaultFileExists(sceneName, sceneCivConfigName))
			{
				SpawnAreaVaultFile(sceneName, sceneCivConfigName);
			}
			string text = ((contract.SceneEnemyConfigName == "") ? FGFileIoHandler.default_enemy_vault_name : contract.SceneEnemyConfigName);
			if (FGFileIoHandler.DoesAreaVaultFileExists(sceneName, text))
			{
				SpawnAreaVaultFile(sceneName, text);
			}
			((MonoBehaviour)this).StartCoroutine(FG_GM.TryWithRetries(delegate
			{
				if (PLtoFG.TransformPLtoFG())
				{
					ScanAndProcessModeObjects(contract);
					return true;
				}
				return false;
			}, 15, 1f));
			GM.CurrentMovementManager.TeleportToPoint(GM.CurrentSceneSettings.DeathResetPoint.position, false);
			SpawnPlayerQbWithRetry(saveSlotName);
			return true;
		}

		private void SpawnAreaVaultFile(string sceneName, string vault_file)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			string text = "";
			if (!FGFileIoHandler.LoadAreaVaultFile(sceneName, vault_file, out var vf))
			{
				Debug.LogError((object)("Loading CGriller Area Scene file failed " + sceneName + vault_file));
				return;
			}
			if (VaultSystem.SpawnVaultFile(vf, ((Component)this).transform, false, false, false, ref text, Vector3.zero, (ReturnObjectListDelegate)null, true))
			{
				Debug.LogWarning((object)("Scene config loaded for area " + sceneName + vault_file));
				return;
			}
			Debug.LogError((object)("Failed to load scene with error: " + text + "\n on " + ((object)vf)?.ToString() + " " + vault_file));
		}

		public void SpawnPlayerQbWithRetry(string saveSlotName)
		{
			((MonoBehaviour)this).StartCoroutine(FG_GM.TryWithRetries(() => SpawnPlayerQb(saveSlotName), 15, 1f));
		}

		public bool SpawnPlayerQb(string saveSlotName)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (GM.IsAsyncLoading)
			{
				Debug.LogWarning((object)"Waiting SpawnPlayerQb, IsAsyncLoading aka vault loading.");
				return false;
			}
			if (!FGFileIoHandler.LoadPlayerQuickbelt(saveSlotName, out var vaultFile))
			{
				Debug.LogError((object)"Loading CGriller Quickbelt file failed");
				return true;
			}
			string text = "";
			if (!GM.IsAsyncLoading && VaultSystem.SpawnVaultFile(vaultFile, ((Component)this).transform, false, true, false, ref text, Vector3.zero, (ReturnObjectListDelegate)null, true))
			{
				Debug.LogWarning((object)"Succeeded loading player loady");
				return true;
			}
			Debug.LogError((object)("Failed to spawn player loadout for reason:" + text));
			return true;
		}

		private void ScanAndProcessModeObjects(FGContract contract)
		{
			FGTargetPosse[] array = Object.FindObjectsOfType<FGTargetPosse>();
			if (array.Length == 0)
			{
				Debug.LogWarning((object)"No FGTargetPosse objects found in the scene.");
				return;
			}
			int num = Random.Range(0, array.Length);
			FGTargetPosse fGTargetPosse = array[num];
			if (contract != null)
			{
				fGTargetPosse.SetContract(contract);
			}
			fGTargetPosse.SelectAndSpawnPosseConfig();
			TargetPosses.Add(fGTargetPosse);
		}
	}
	[Serializable]
	public class FGSosigManifest
	{
		[HideInInspector]
		public string Faction;

		[HideInInspector]
		public string FirstName;

		[HideInInspector]
		public string LastName;

		public string UniqueId;

		public int IFF = -3;

		public int SosigOrder;

		public int EnemyId;

		public bool IsTarget;

		public bool IsGuard;

		public bool IsExtra;
	}
	public static class FGSosigSpawner
	{
		public static Sosig SpawnMySosig(FGSosigMandate mandate)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: 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_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			if (mandate == null || mandate.Manifest == null || (Object)(object)mandate.SpawnPoint == (Object)null)
			{
				Debug.LogError((object)"Invalid SosigMandate! Ensure Mandate, Manifest, and SpawnPoint are assigned.");
				return null;
			}
			FGSosigManifest manifest = mandate.Manifest;
			Vector3 position = mandate.SpawnPoint.position;
			Quaternion rotation = mandate.SpawnPoint.rotation;
			Sosig val = SosigAPI.Spawn(ManagerSingleton<IM>.Instance.odicSosigObjsByID[(SosigEnemyID)manifest.EnemyId], new SpawnOptions(), position, rotation);
			if ((Object)(object)val == (Object)null)
			{
				Debug.LogError((object)"Sosig spawn failed!");
				return null;
			}
			int iFF = ((manifest.IFF == -1) ? Random.Range(8, 32) : manifest.IFF);
			val.SetIFF(iFF);
			val.CurrentOrder = (SosigOrder)manifest.SosigOrder;
			val.FallbackOrder = (SosigOrder)manifest.SosigOrder;
			val.SetDominantGuardDirection(rotation * Vector3.forward);
			val.UpdateGuardPoint(position);
			val.UpdateAssaultPoint(position);
			val.SetGuardInvestigateDistanceThreshold(3f);
			val.UpdateIdlePoint(position);
			val.SetDominantGuardDirection(((Component)val).transform.forward);
			val.CanBeThreatened = true;
			FGMapFactionAssigner.MakeSosigThreatenableToAll(val);
			val.FallbackOrder = (SosigOrder)manifest.SosigOrder;
			if (mandate.Path != null && mandate.Path.Path.Count > 0)
			{
				val.CommandPathTo(mandate.Path.Path, 0.2f, new Vector2(1f, 10f), 1.2f, (SosigMoveSpeed)3, (PathLoopType)3, (List<Sosig>)null, 0.3f, 10f, false, 20f);
			}
			return val;
		}
	}
	public class FGTargetPosse : MonoBehaviour
	{
		[Serializable]
		public class PosseConfig
		{
			public List<FGSosigMandate> Targets = new List<FGSosigMandate>();

			public List<FGSosigMandate> Guards = new List<FGSosigMandate>();

			public List<FGSosigMandate> Extras = new List<FGSosigMandate>();
		}

		public List<PosseConfig> TargetConfigs = new List<PosseConfig>();

		public FGContract contract { get; private set; }

		public PosseConfig selectedPosseConfig { get; private set; }

		public List<FGTrackedSosig> trackedTargets { get; private set; } = new List<FGTrackedSosig>();


		public List<FGTrackedSosig> trackedGuards { get; private set; } = new List<FGTrackedSosig>();


		public List<FGTrackedSosig> trackedExtras { get; private set; } = new List<FGTrackedSosig>();


		public FGMapFactionAssigner factionAssigner { get; private set; }

		private void Awake()
		{
			factionAssigner = new FGMapFactionAssigner();
		}

		public void SetContract(FGContract newContract)
		{
			DestroyAll();
			contract = newContract;
		}

		public void DestroyAll()
		{
			foreach (FGTrackedSosig trackedTarget in trackedTargets)
			{
				Object.Destroy((Object)(object)((Component)trackedTarget.SosigInstance).gameObject);
			}
			foreach (FGTrackedSosig trackedGuard in trackedGuards)
			{
				Object.Destroy((Object)(object)((Component)trackedGuard.SosigInstance).gameObject);
			}
			foreach (FGTrackedSosig trackedExtra in trackedExtras)
			{
				Object.Destroy((Object)(object)((Component)trackedExtra.SosigInstance).gameObject);
			}
			trackedTargets.Clear();
			trackedGuards.Clear();
			trackedExtras.Clear();
			selectedPosseConfig = null;
		}

		public void SelectAndSpawnPosseConfig()
		{
			if (TargetConfigs.Count != 0)
			{
				selectedPosseConfig = TargetConfigs[Random.Range(0, TargetConfigs.Count)];
				SpawnSelectedConfig();
			}
		}

		public void AddPosseConfig(PosseConfig config)
		{
			TargetConfigs.Add(config);
		}

		public FGTrackedSosig FindSosig(Sosig sosig)
		{
			foreach (FGTrackedSosig trackedTarget in trackedTargets)
			{
				if ((Object)(object)trackedTarget.SosigInstance == (Object)(object)sosig)
				{
					return trackedTarget;
				}
			}
			foreach (FGTrackedSosig trackedGuard in trackedGuards)
			{
				if ((Object)(object)trackedGuard.SosigInstance == (Object)(object)sosig)
				{
					return trackedGuard;
				}
			}
			foreach (FGTrackedSosig trackedExtra in trackedExtras)
			{
				if ((Object)(object)trackedExtra.SosigInstance == (Object)(object)sosig)
				{
					return trackedExtra;
				}
			}
			return null;
		}

		private void SpawnSelectedConfig()
		{
			if (selectedPosseConfig == null || contract == null)
			{
				Debug.LogError((object)"No selected posse config or contract.");
				return;
			}
			trackedTargets.Clear();
			trackedGuards.Clear();
			trackedExtras.Clear();
			SpawnEntities(contract._TargetIDs, isTarget: true, isGuard: false, isExtra: false, selectedPosseConfig.Targets, trackedTargets);
			SpawnEntities(contract._GuardIDs, isTarget: false, isGuard: true, isExtra: false, selectedPosseConfig.Guards, trackedGuards);
			SpawnEntities(contract._ExtrasIDs, isTarget: false, isGuard: false, isExtra: true, selectedPosseConfig.Extras, trackedExtras);
		}

		private void SpawnEntities(Dictionary<string, List<SosigEnemyID>> entityList, bool isTarget, bool isGuard, bool isExtra, List<FGSosigMandate> mandateList, List<FGTrackedSosig> trackedList)
		{
			//IL_0070: 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_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Expected I4, but got Unknown
			HashSet<int> pickedIndexes = new HashSet<int>();
			foreach (KeyValuePair<string, List<SosigEnemyID>> entity in entityList)
			{
				string key = entity.Key;
				List<SosigEnemyID> value = entity.Value;
				if (value != null && value.Count != 0)
				{
					SosigEnemyID val = (SosigEnemyID)((value != null && value.Count > 0) ? ((int)value[Random.Range(0, value.Count)]) : 0);
					FGSosigMandate fGSosigMandate = PickUnpickedMandate(key, pickedIndexes, mandateList);
					if (fGSosigMandate == null)
					{
						break;
					}
					fGSosigMandate.Manifest.EnemyId = (int)val;
					if (isTarget)
					{
						fGSosigMandate.Manifest.Faction = (contract._Faction_Target.TryGetValue(key, out var value2) ? value2 : "");
						fGSosigMandate.Manifest.FirstName = contract.TargetFirstName;
						fGSosigMandate.Manifest.LastName = contract.TargetLastName;
						fGSosigMandate.Manifest.IsTarget = true;
					}
					else if (isGuard)
					{
						fGSosigMandate.Manifest.Faction = (contract._Faction_Guards.TryGetValue(key, out var value3) ? value3 : "");
						fGSosigMandate.Manifest.IsGuard = true;
					}
					else
					{
						fGSosigMandate.Manifest.Faction = (contract._Faction_Extras.TryGetValue(key, out var value4) ? value4 : "");
						fGSosigMandate.Manifest.IsExtra = true;
					}
					if (string.IsNullOrEmpty(fGSosigMandate.Manifest.UniqueId))
					{
						fGSosigMandate.Manifest.UniqueId = Random.Range(0, 99999).ToString();
					}
					FGTrackedSosig fGTrackedSosig = SpawnNpcFromMandate(fGSosigMandate);
					if (fGTrackedSosig != null)
					{
						trackedList.Add(fGTrackedSosig);
						ConfigureSosigFaction(fGTrackedSosig, fGSosigMandate.Manifest.Faction);
					}
				}
			}
		}

		private FGSosigMandate PickUnpickedMandate(string uniqueId, HashSet<int> pickedIndexes, List<FGSosigMandate> mandates)
		{
			for (int i = 0; i < mandates.Count; i++)
			{
				FGSosigMandate fGSosigMandate = mandates[i];
				if (!pickedIndexes.Contains(i) && fGSosigMandate.Manifest.UniqueId == uniqueId)
				{
					pickedIndexes.Add(i);
					return fGSosigMandate;
				}
			}
			for (int j = 0; j < mandates.Count; j++)
			{
				if (!pickedIndexes.Contains(j))
				{
					pickedIndexes.Add(j);
					return mandates[j];
				}
			}
			return null;
		}

		private FGTrackedSosig SpawnNpcFromMandate(FGSosigMandate mandate)
		{
			if (mandate == null || (Object)(object)mandate.SpawnPoint == (Object)null || mandate.Manifest == null)
			{
				Debug.LogError((object)"Either spawn point or manifest null");
				return null;
			}
			Sosig val = FGSosigSpawner.SpawnMySosig(mandate);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			return new FGTrackedSosig
			{
				SosigInstance = val,
				Path = mandate.Path,
				Manifest = mandate.Manifest
			};
		}

		private void ConfigureSosigFaction(FGTrackedSosig trackedSosig, string faction)
		{
			Sosig sosigInstance = trackedSosig.SosigInstance;
			FGFactionStance factionStance = FG_GM.Instance.factionStance;
			factionStance.GetFactionEnemies(faction, out var enemies);
			sosigInstance.SetIFF(factionAssigner.AssignIFF(faction));
			sosigInstance.CanBeThreatened = true;
			sosigInstance.Priority.SetAllFriendly();
			FGMapFactionAssigner.MakeSosigThreatenableToAll(sosigInstance);
			foreach (string item in enemies)
			{
				factionAssigner.SetSosigFriendlyToFaction(sosigInstance, item, isFriendly: false);
			}
			if (!trackedSosig.Manifest.IsTarget && !trackedSosig.Manifest.IsGuard)
			{
				return;
			}
			IEnumerable<string> enumerable = contract._Faction_Target.Values.Concat(contract._Faction_Guards.Values).Distinct();
			foreach (string item2 in enumerable)
			{
				factionAssigner.SetSosigFriendlyToFaction(sosigInstance, item2, isFriendly: true);
				factionAssigner.SetSosigThreatableToFaction(sosigInstance, item2, isThreatable: false);
			}
		}
	}
	[BepInPlugin("NGA.FreeGrillerPatchy", "FreeGrillerPatchy", "0.0.1")]
	[BepInDependency("nrgill28.Sodalite", "1.4.1")]
	[BepInProcess("h3vr.exe")]
	public class FreeGrillerPatchy : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(GM))]
		[HarmonyPatch("Awake")]
		public class FG_GM_Initializer
		{
			private static void Postfix(GM __instance)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Expected O, but got Unknown
				if ((Object)(object)FG_GM.Instance == (Object)null)
				{
					GameObject val = new GameObject("FG_GM");
					val.AddComponent<FG_GM>();
					Object.DontDestroyOnLoad((Object)(object)val);
				}
			}
		}

		[HarmonyPatch(typeof(FVRSceneSettings))]
		[HarmonyPatch("LoadDefaultSceneRoutine")]
		private class FVRSceneSettingsLoadDefaultSceneRoutineHook
		{
			private static bool Prefix(FVRSceneSettings __instance)
			{
				//IL_0017: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				if (!FG_GM.Instance.causedInTransitioningLevels)
				{
					string lastTransitionedToSceneName = FG_GM.Instance.lastTransitionedToSceneName;
					Scene activeScene = SceneManager.GetActiveScene();
					if (!(lastTransitionedToSceneName == ((Scene)(ref activeScene)).name))
					{
						return true;
					}
				}
				return false;
			}
		}

		private static ConfigEntry<bool> GameEnabled;

		private static ConfigEntry<float> SprintSpeedCap;

		internal static ManualLogSource Logger { get; private set; }

		private void Awake()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			Logger = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("NGA.FreeGrillerPatchy");
			Logger.LogMessage((object)"New harmony");
			SetUpConfigFields();
			Logger.LogMessage((object)"Setted the fields");
			val.PatchAll();
			Logger.LogMessage((object)"Hello, world! Sent from NGA.FreeGrillerPatchy");
		}

		private void SetUpConfigFields()
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Expected O, but got Unknown
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			GameEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Overall", "ON/OFF", true, "Completely enable/disable mod");
			SprintSpeedCap = ((BaseUnityPlugin)this).Config.Bind<float>("TwinStickArmSwing", "Sprint Added speed v2", 2f, new ConfigDescription("Sprint speed soft-cap on armswing. Bigger than jog.", (AcceptableValueBase)new AcceptableValueFloatRangeStep(0f, 20f, 0.05f), new object[0]));
		}

		private static bool CheckSkip()
		{
			return !GameEnabled.Value;
		}
	}
	public class FGBank
	{
		public struct Config
		{
			public int playerBalance;

			public List<TransactionRecord> transactions;
		}

		[Serializable]
		public class TransactionRecord
		{
			public int amount;

			public string description;

			public TransactionRecord(int amount, string description)
			{
				this.amount = amount;
				this.description = description;
			}
		}

		public int playerBalance { get; private set; }

		public List<TransactionRecord> transactions { get; private set; }

		public FGBank()
		{
			playerBalance = 0;
			transactions = new List<TransactionRecord>();
		}

		public void InitFromConfig(Config config)
		{
			playerBalance = config.playerBalance;
			transactions = config.transactions ?? new List<TransactionRecord>();
		}

		public Config GetConfig()
		{
			Config result = default(Config);
			result.playerBalance = playerBalance;
			result.transactions = new List<TransactionRecord>(transactions);
			return result;
		}

		public bool TryDecrementPlyBalance(int amount)
		{
			if (playerBalance >= amount)
			{
				playerBalance -= amount;
				return true;
			}
			return false;
		}

		public void ForceDecrementPlyBalance(int amount)
		{
			playerBalance -= amount;
		}

		public void IncrementPlyBalance(int amount)
		{
			playerBalance += amount;
		}

		public void ProcessTransaction(TransactionRecord transaction, bool forceDecrement)
		{
			if (transaction.amount < 0)
			{
				if (forceDecrement)
				{
					ForceDecrementPlyBalance(-transaction.amount);
				}
				else if (!TryDecrementPlyBalance(-transaction.amount))
				{
					return;
				}
			}
			else
			{
				IncrementPlyBalance(transaction.amount);
			}
			transactions.Insert(0, transaction);
		}

		public string PrintPlyBankInfo(int maxTransactions = 10)
		{
			string text = $"<b>Current balance:</b> ${playerBalance:N0}\n\n";
			text += "<b>Recent transactions:</b>\n";
			int num = 0;
			foreach (TransactionRecord transaction in transactions)
			{
				if (num++ >= maxTransactions)
				{
					break;
				}
				text += $"${transaction.amount:N0} {transaction.description}\n";
			}
			return text;
		}
	}
	[Serializable]
	public class FGFaction
	{
		public string FactionId;

		public float currentReputation;

		public float startingReputation;

		public float maxPossibleReputation;

		public float minPossibleReputation;

		public List<string> AlwaysHostileTowardsFactionIds;
	}
	public class FGFactionStance
	{
		[Serializable]
		public struct Config
		{
			public List<FGFaction> Factions;
		}

		public List<FGFaction> factions = new List<FGFaction>();

		public FGFactionStance()
		{
			factions = new List<FGFaction>();
		}

		public void InitFromConfig(Config config)
		{
			factions = config.Factions;
		}

		public Config GetConfig()
		{
			Config result = default(Config);
			result.Factions = factions;
			return result;
		}

		public void RegisterFaction(FGFaction faction)
		{
			FGFaction fGFaction = factions.FirstOrDefault((FGFaction f) => f.FactionId == faction.FactionId);
			if (fGFaction != null)
			{
				fGFaction.startingReputation = faction.startingReputation;
				fGFaction.maxPossibleReputation = faction.maxPossibleReputation;
				fGFaction.minPossibleReputation = faction.minPossibleReputation;
				{
					foreach (string alwaysHostileTowardsFactionId in faction.AlwaysHostileTowardsFactionIds)
					{
						if (!fGFaction.AlwaysHostileTowardsFactionIds.Contains(alwaysHostileTowardsFactionId))
						{
							fGFaction.AlwaysHostileTowardsFactionIds.Add(alwaysHostileTowardsFactionId);
						}
					}
					return;
				}
			}
			factions.Add(faction);
		}

		public bool TryAdjustReputation(string factionId, float adjustment)
		{
			FGFaction fGFaction = factions.FirstOrDefault((FGFaction f) => f.FactionId == factionId);
			if (fGFaction == null)
			{
				return false;
			}
			fGFaction.currentReputation = Mathf.Clamp(fGFaction.currentReputation + adjustment, fGFaction.minPossibleReputation, fGFaction.maxPossibleReputation);
			return true;
		}

		public float GetReputationWithFaction(string factionId)
		{
			return factions.FirstOrDefault((FGFaction f) => f.FactionId == factionId)?.currentReputation ?? 0f;
		}

		public bool IsFactionHostileTowards(string sourceFaction, string toFaction)
		{
			return factions.FirstOrDefault((FGFaction f) => f.FactionId == sourceFaction)?.AlwaysHostileTowardsFactionIds.Contains(toFaction) ?? false;
		}

		public bool GetFactionEnemies(string factionId, out List<string> enemies)
		{
			FGFaction fGFaction = factions.FirstOrDefault((FGFaction f) => f.FactionId == factionId);
			if (fGFaction == null)
			{
				enemies = new List<string>();
				return false;
			}
			enemies = fGFaction.AlwaysHostileTowardsFactionIds;
			return true;
		}

		public string PrintFactionStance()
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (FGFaction faction in factions)
			{
				stringBuilder.AppendLine("<b>Faction ID:</b> " + faction.FactionId);
				stringBuilder.AppendLine($"<b>Current Reputation:</b> {faction.currentReputation}");
				stringBuilder.AppendLine($"<b>Max Reputation:</b> {faction.maxPossibleReputation}");
				stringBuilder.AppendLine($"<b>Min Reputation:</b> {faction.minPossibleReputation}");
				stringBuilder.AppendLine("<b>Always Hostile Towards:</b> " + string.Join(", ", faction.AlwaysHostileTowardsFactionIds.ToArray()));
				stringBuilder.AppendLine("---------------------------");
			}
			return stringBuilder.ToString();
		}
	}
	public class FGTimeSystem : MonoBehaviour
	{
		public struct Config
		{
			public string CurrTime;

			public float timeMult;
		}

		public static FGTimeSystem Instance;

		private float realTimeElapsed = 0f;

		private int lastReportedHour;

		public float timeMultiplier { get; set; } = 24f;


		public DateTime CurrentTime { get; private set; } = DateTime.Now;


		public event Action<DateTime> OnTimeAdvanced;

		public event Action<DateTime> OnHourPassed;

		private void Awake()
		{
			if ((Object)(object)Instance == (Object)null)
			{
				Instance = this;
			}
			else
			{
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private void Start()
		{
			lastReportedHour = CurrentTime.Hour;
		}

		private void Update()
		{
			realTimeElapsed += Time.deltaTime * timeMultiplier;
			if (realTimeElapsed >= 1f)
			{
				int num = Mathf.FloorToInt(realTimeElapsed);
				realTimeElapsed -= num;
				CurrentTime = CurrentTime.AddSeconds(num);
				if (CurrentTime.Hour != lastReportedHour)
				{
					lastReportedHour = CurrentTime.Hour;
					this.OnHourPassed?.Invoke(CurrentTime);
				}
			}
		}

		public void AdvanceTime(int seconds)
		{
			CurrentTime = CurrentTime.AddSeconds(seconds);
			this.OnTimeAdvanced?.Invoke(CurrentTime);
		}

		public DateTime GetInGameTimeAfterRealDuration(TimeSpan realDuration)
		{
			DateTime currentTime = CurrentTime;
			double totalSeconds = realDuration.TotalSeconds;
			double value = totalSeconds * (double)timeMultiplier;
			return currentTime.AddSeconds(value);
		}

		public TimeSpan CalculateRealTimeUntil(DateTime startTime, DateTime targetTime)
		{
			if (targetTime <= startTime)
			{
				return TimeSpan.Zero;
			}
			double totalSeconds = (targetTime - startTime).TotalSeconds;
			double value = totalSeconds / (double)timeMultiplier;
			return TimeSpan.FromSeconds(value);
		}

		public void InitFromConfig(Config config)
		{
			CurrentTime = LoadGameTime(config.CurrTime);
			timeMultiplier = config.timeMult;
			lastReportedHour = CurrentTime.Hour;
		}

		public Config GetConfig()
		{
			Config result = default(Config);
			result.CurrTime = SaveGameTime();
			result.timeMult = timeMultiplier;
			return result;
		}

		public string SaveGameTime()
		{
			return CurrentTime.ToString("o");
		}

		private DateTime LoadGameTime(string dateTimeString)
		{
			if (string.IsNullOrEmpty(dateTimeString))
			{
				return DateTime.Now;
			}
			DateTime result = DateTime.Parse(dateTimeString, null, DateTimeStyles.RoundtripKind);
			bool flag = false;
			return result;
		}
	}
	public class FGTimeUi2 : MonoBehaviour
	{
		[SerializeField]
		public Text timeText;

		private void Start()
		{
			((MonoBehaviour)this).InvokeRepeating("UpdateTimeDisplay", 1f, 1f);
		}

		private void UpdateTimeDisplay()
		{
			if ((Object)(object)FGTimeSystem.Instance != (Object)null && (Object)(object)timeText != (Object)null)
			{
				DateTime dateTime = FGTimeSystem.Instance.CurrentTime.ToLocalTime();
				timeText.text = dateTime.ToString("MM/dd/yy HH:mm:ss");
			}
		}

		private void OnDisable()
		{
			((MonoBehaviour)this).CancelInvoke("UpdateTimeDisplay");
		}
	}
	public class FGWristUi2 : MonoBehaviour
	{
		private int selectedTabIx = 0;

		private int currQuestTabType = 0;

		private int selectedQuestIndex = -1;

		[Header("UI References")]
		private Transform Canvas;

		private Transform TimeText;

		private Transform TravelTab;

		private Transform ContractsTab;

		private Transform ContractsVertList;

		private Transform ContractStickerTempl;

		private Transform TimeTab;

		private Transform BankTab;

		private Transform RepTab;

		public Transform Face;

		public FVRViveHand[] Hands = (FVRViveHand[])(object)new FVRViveHand[2];

		private FVRViveHand m_currentHand;

		private bool m_hasHands = false;

		private bool m_isActive = false;

		private float m_wristPointRange = 60f;

		private float m_faceAngleRange = 45f;

		public void Start()
		{
			SetHandsAndFace(((Component)GM.CurrentPlayerBody.RightHand).GetComponent<FVRViveHand>(), ((Component)GM.CurrentPlayerBody.LeftHand).GetComponent<FVRViveHand>(), ((Component)GM.CurrentPlayerBody.EyeCam).transform);
			FindUiVariables();
			AddTimeUiRunner();
			CloseTabs();
		}

		public void Update()
		{
			UpdateWristMenu();
		}

		private void FindUiVariables()
		{
			Canvas = ((Component)this).transform.Find("Canvas");
			TravelTab = Canvas.Find("TravelTab");
			ContractsTab = Canvas.Find("ContractsTab");
			TimeTab = Canvas.Find("TimeTab");
			BankTab = Canvas.Find("BankTab");
			RepTab = Canvas.Find("RepTab");
			TimeText = Canvas.Find("QuickMenu").Find("Time");
			ContractsVertList = ContractsTab.Find("ContractsList").Find("ViewPort").Find("Content");
			ContractStickerTempl = ContractsTab.Find("ContractsList").Find("ContractStickerTmpl");
		}

		public void CloseTabs()
		{
			((Component)TravelTab).gameObject.SetActive(false);
			((Component)ContractsTab).gameObject.SetActive(false);
			((Component)TimeTab).gameObject.SetActive(false);
			((Component)BankTab).gameObject.SetActive(false);
			((Component)RepTab).gameObject.SetActive(false);
		}

		public void BTN_DisplayQuests(int i)
		{
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Expected O, but got Unknown
			currQuestTabType = i;
			selectedQuestIndex = -1;
			for (int j = 0; j < ContractsVertList.childCount; j++)
			{
				Object.Destroy((Object)(object)((Component)ContractsVertList.GetChild(j)).gameObject);
			}
			List<FGContract> currentContractList = GetCurrentContractList();
			string text = i switch
			{
				0 => "[Available]", 
				1 => "[Active]", 
				2 => "[Finished]", 
				_ => "", 
			};
			for (int k = 0; k < currentContractList.Count; k++)
			{
				FGContract fGContract = currentContractList[k];
				Transform transform = Object.Instantiate<GameObject>(((Component)ContractStickerTempl).gameObject, ContractsVertList).transform;
				Text componentInChildren = ((Component)transform.Find("Description")).GetComponentInChildren<Text>();
				componentInChildren.text = fGContract.DisplayName + "\n" + fGContract.TargetFirstName + " " + fGContract.TargetLastName + "\n" + fGContract.Infraction + "\n" + text;
				int index = k;
				Button component = ((Component)transform.Find("Btn_MoreDetails").Find("BTN_MoreDetails")).GetComponent<Button>();
				((UnityEvent)component.onClick).AddListener((UnityAction)delegate
				{
					BTN_DisplayQuestDetail(index);
				});
				((Component)transform).gameObject.SetActive(true);
			}
			selectedQuestIndex = ((currentContractList.Count == 0) ? (-1) : 0);
			BTN_DisplayQuestDetail(selectedQuestIndex);
		}

		public void BTN_DisplayQuestDetail(int i = -1)
		{
			selectedQuestIndex = i;
			Text componentInChildren = ((Component)ContractsTab.Find("ContractDescription").Find("DescriptionScroll").Find("ViewPort")
				.Find("Description")).GetComponentInChildren<Text>();
			if (selectedQuestIndex < 0)
			{
				componentInChildren.text = "";
				return;
			}
			List<FGContract> currentContractList = GetCurrentContractList();
			if (selectedQuestIndex >= currentContractList.Count)
			{
				componentInChildren.text = "Selected index is invalid " + selectedQuestIndex + " compared to available contracts list " + currentContractList.Count;
				return;
			}
			FGContract fGContract = currentContractList[selectedQuestIndex];
			componentInChildren.text = fGContract.PrintContract();
		}

		private List<FGContract> GetCurrentContractList()
		{
			return currQuestTabType switch
			{
				0 => FG_GM.Instance.contractMan.GetAvailableContracts(), 
				1 => FG_GM.Instance.contractMan.GetActiveContracts(), 
				2 => FG_GM.Instance.contractMan.GetCompletedContracts(), 
				_ => new List<FGContract>(), 
			};
		}

		public void BTN_AcceptContract()
		{
			if (selectedQuestIndex < 0 || currQuestTabType != 0)
			{
				Debug.LogWarning((object)("Selected index is invalid " + selectedQuestIndex + " or you didn't select Available tab " + currQuestTabType));
				return;
			}
			List<FGContract> currentContractList = GetCurrentContractList();
			if (selectedQuestIndex >= currentContractList.Count)
			{
				Debug.LogWarning((object)("Selected index is invalid too big " + selectedQuestIndex + " compared to available contracts list " + currentContractList.Count));
				return;
			}
			FG_GM.Instance.contractMan.AcceptContract(currentContractList[selectedQuestIndex].uniqueID);
			BTN_DisplayQuests(currQuestTabType);
			Debug.LogWarning((object)"Allegedly accepted quest.");
		}

		public void BTN_RejectContract()
		{
			if (selectedQuestIndex < 0 || currQuestTabType != 1)
			{
				Debug.LogWarning((object)("Selected index is invalid " + selectedQuestIndex + " or you didn't select Active tab " + currQuestTabType));
				return;
			}
			List<FGContract> currentContractList = GetCurrentContractList();
			if (selectedQuestIndex >= currentContractList.Count)
			{
				Debug.LogWarning((object)("Selected index is invalid too big " + selectedQuestIndex + " compared to active contracts list " + currentContractList.Count));
				return;
			}
			FG_GM.Instance.contractMan.RejectContract(currentContractList[selectedQuestIndex].uniqueID);
			BTN_DisplayQuests(currQuestTabType);
			Debug.LogWarning((object)"Allegedly rejected quest.");
		}

		public void BTN_TravelToContractLevel()
		{
			if (selectedQuestIndex < 0 || currQuestTabType != 1)
			{
				Debug.LogWarning((object)("Selected index is invalid " + selectedQuestIndex + " or you didn't select Active tab " + currQuestTabType));
				return;
			}
			List<FGContract> currentContractList = GetCurrentContractList();
			if (selectedQuestIndex >= currentContractList.Count)
			{
				Debug.LogWarning((object)("Selected index is invalid too big " + selectedQuestIndex + " compared to active contracts list " + currentContractList.Count));
			}
			else
			{
				FG_GM.Instance.TransitionToLevelFromContract(currentContractList[selectedQuestIndex]);
			}
		}

		public void BTN_RefreshBankInfo()
		{
			((Component)BankTab.Find("Description")).GetComponentInChildren<Text>().text = FG_GM.Instance.bank.PrintPlyBankInfo();
		}

		public void BTN_RefreshRepInfo()
		{
			((Component)RepTab.Find("Description")).GetComponentInChildren<Text>().text = FG_GM.Instance.factionStance.PrintFactionStance();
		}

		public void BTN_OpenTab(int index)
		{
			CloseTabs();
			switch (index)
			{
			case 0:
				((Component)TravelTab).gameObject.SetActive(true);
				break;
			case 1:
				((Component)ContractsTab).gameObject.SetActive(true);
				BTN_DisplayQuests(currQuestTabType);
				break;
			case 2:
				((Component)TimeTab).gameObject.SetActive(true);
				break;
			case 3:
				((Component)BankTab).gameObject.SetActive(true);
				BTN_RefreshBankInfo();
				break;
			case 4:
				((Component)RepTab).gameObject.SetActive(true);
				BTN_RefreshRepInfo();
				break;
			default:
				Debug.LogError((object)("Selected tab not supported: " + index));
				return;
			}
			selectedTabIx = index;
		}

		public void BTN_TravelHome()
		{
			FG_GM.Instance.TransitionToLevel("IndoorRange_Updated");
		}

		public void BTN_TravelArea()
		{
			FG_GM.Instance.TransitionToLevel("Grillhouse_2Story");
		}

		public void BTN_AdvanceHour()
		{
			FGTimeSystem.Instance.AdvanceTime(3600);
		}

		public void AddTimeUiRunner()
		{
			FGTimeUi2 fGTimeUi = ((Component)this).gameObject.AddComponent<FGTimeUi2>();
			Text componentInChildren = ((Component)TimeText).GetComponentInChildren<Text>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				fGTimeUi.timeText = componentInChildren;
			}
		}

		private void UpdateWristMenu()
		{
			//IL_0047: 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_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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)
			//IL_00a7: 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_00b1: 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_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Invalid comparison between Unknown and I4
			//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Invalid comparison between Unknown and I4
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			if (!m_hasHands)
			{
				return;
			}
			if (m_isActive)
			{
				PositionWristMenu();
				if ((Object)(object)m_currentHand.CurrentInteractable != (Object)null || Vector3.Angle(m_currentHand.G