Decompiled source of SODRelationsPlus v1.0.1

SOD.RelationsPlus.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using System.Text.Json.Serialization;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.BepInEx;
using SOD.Common.BepInEx.Configuration;
using SOD.Common.Extensions;
using SOD.Common.Helpers;
using SOD.RelationsPlus.Objects;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SOD.RelationsPlus")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+105368c6fd0dd8757a25de203851c1af249c7651")]
[assembly: AssemblyProduct("SOD.RelationsPlus")]
[assembly: AssemblyTitle("SOD.RelationsPlus")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace SOD.RelationsPlus
{
	public interface IPluginBindings : IRelationGateBindings, IDecayModifierBindings, ISeenModifierBindings, IKnowModifierBindings, ILikeModifierBindings
	{
		[Binding(false, "Debug mode shows extra logging to track relational changes between citizens and the player.", null)]
		bool DebugMode { get; set; }
	}
	public interface IRelationGateBindings
	{
		[Binding(0.2f, "The first gate, (0 -> GateOneValue): The player is a stranger to the citizen.", "Relation.Gates.KnowGateOne")]
		float KnowGateOne { get; set; }

		[Binding(0.4f, "The second gate, (GateOneValue -> GateTwoValue): The citizen becomes aware of the player.", "Relation.Gates.KnowGateTwo")]
		float KnowGateTwo { get; set; }

		[Binding(0.6f, "The third gate, (GateTwoValue -> GateThreeValue): The citizen becomes familiar with the player.", "Relation.Gates.KnowGateThree")]
		float KnowGateThree { get; set; }

		[Binding(0.8f, "The fourth gate, (GateThreeValue -> GateFourValue): The citizen knows the player.", "Relation.Gates.KnowGateFour")]
		float KnowGateFour { get; set; }

		[Binding(1f, "The fifth gate, (GateFourValue -> GateFiveValue): The citizen knows the player very well. (CANNOT BE MODIFIED)", "Relation.Gates.KnowGateFive")]
		float KnowGateFive { get; set; }

		[Binding(0.2f, "The first gate, (0 -> GateOneValue): The citizen hates the player.", "Relation.Gates.LikeGateOne")]
		float LikeGateOne { get; set; }

		[Binding(0.4f, "The second gate, (GateOneValue -> GateTwoValue): The citizen dislikes the player", "Relation.Gates.LikeGateTwo")]
		float LikeGateTwo { get; set; }

		[Binding(0.6f, "The third gate, (GateTwoValue -> GateThreeValue): The citizen is neutral towards the player.", "Relation.Gates.LikeGateThree")]
		float LikeGateThree { get; set; }

		[Binding(0.8f, "The fourth gate, (GateThreeValue -> GateFourValue): The citizen likes the player.", "Relation.Gates.LikeGateFour")]
		float LikeGateFour { get; set; }

		[Binding(1f, "The fifth gate, (GateFourValue -> GateFiveValue): The citizen loves the player. (CANNOT BE MODIFIED)", "Relation.Gates.LikeGateFive")]
		float LikeGateFive { get; set; }
	}
	public interface IDecayModifierBindings
	{
		[Binding(60, "After how many in-game minutes is the decay check executed each time?", "Modifiers.Decay.DecayTimeMinutesCheck")]
		int DecayTimeMinutesCheck { get; set; }

		[Binding(120, "After how many in-game minutes that the citizen hasn't seen the player should decay start? (both 'Know' and 'Like' if enabled)", "Modifiers.Decay.DecayKnowAfterUnseenMinutes")]
		int DecayKnowAfterUnseenMinutes { get; set; }

		[Binding(-0.005f, "How much does 'Know' decay automatically? (cannot decay past certain stages of 'Know')", "Modifiers.Decay.DecayKnowAmount")]
		float DecayKnowAmount { get; set; }

		[Binding(false, "Can the automatic decay of 'Know' go past the relation stages once reached.", "Modifiers.Decay.AllowDecayPastRelationGates")]
		bool AllowDecayPastKnowGates { get; set; }

		[Binding(false, "Can 'Like' automatically decay back to neutral?", "Modifiers.Decay.AllowDecayLikeToNeutral")]
		bool AllowDecayLikeToNeutral { get; set; }

		[Binding(-0.0025f, "How much does 'Like' decay automatically? (cannot decay past neutral)", "Modifiers.Decay.DecayLikeAmount")]
		float DecayLikeAmount { get; set; }

		[Binding(0.0035f, "How much does 'Like' improve automatically back to neutral (0.5)?", "Modifiers.Decay.ImproveLikeAmount")]
		float ImproveLikeAmount { get; set; }

		[Binding(true, "Can 'Like' automatically improve back to neutral (0.5) when it is under neutral?", "Modifiers.Decay.AutoImproveLike")]
		bool AllowAutoImproveLikeToNeutral { get; set; }
	}
	public interface ISeenModifierBindings
	{
		[Binding(10, "How often a check is executed per citizen in in-game minutes if they see the player.", "Modifiers.Seen.SeenTimeMinutesCheck")]
		int SeenTimeMinutesCheck { get; set; }
	}
	public interface IKnowModifierBindings
	{
		[Binding(0.01f, "How much the \"Know\" property changes for the citizen and player when seen passing by on the street.", "Modifiers.Know.SeenOnStreetModifier")]
		float SeenOnStreetModifier { get; set; }

		[Binding(0.02f, "How much the \"Know\" property changes for the citizen and player when seen at their workplace.", "Modifiers.Know.SeenAtWorkplaceModifier")]
		float SeenAtWorkplaceModifier { get; set; }

		[Binding(0.035f, "How much the \"Know\" property changes for the citizen and player when seen inside their home.", "Modifiers.Know.SeenInHome")]
		float SeenInHomeModifier { get; set; }

		[Binding(0.025f, "How much the \"Know\" property changes for the citizen and player when seen inside their home's building/apartement.", "Modifiers.Know.SeenInHomeBuilding")]
		float SeenInHomeBuildingModifier { get; set; }

		[Binding(0.035f, "How much the \"Know\" property changes for the citizen when the player accepts a job for them.", "Modifiers.Know.AcceptedJobKnowModifier")]
		float AcceptedJobKnowModifier { get; set; }

		[Binding(0.015f, "How much the \"Know\" property changes for the citizen and player when they talk to eachother.", "Modifiers.Know.SpeakingToCitizenModifier")]
		float SpeakingToCitizenModifier { get; set; }
	}
	public interface ILikeModifierBindings
	{
		[Binding(-0.05f, "How much the \"Like\" property changes for the citizen and player when seen trespassing.", "Modifiers.Like.SeenTrespassingModifier")]
		float SeenTrespassingModifier { get; set; }

		[Binding(-0.05f, "How much the \"Like\" property changes for the citizen when they see the player doing something illegal.", "Modifiers.Like.SeenDoingIllegalModifier")]
		float SeenDoingIllegalModifier { get; set; }

		[Binding(0.125f, "How much the \"Like\" property changes for the citizen when the player solves a job from them.", "Modifiers.Like.SolvedJobModifier")]
		float SolvedJobModifier { get; set; }

		[Binding(-0.065f, "How much the \"Like\" property changes for the citizen when the player fails a job from them.", "Modifiers.Like.FailedJobModifier")]
		float FailedJobModifier { get; set; }

		[Binding(-0.1f, "How much the \"Like\" property changes for the citizen when the player fails a job from them.", "Modifiers.Like.OnAttackCitizenModifier")]
		float OnAttackCitizenModifier { get; set; }

		[Binding(0.025f, "How much the \"Know\" property changes for the citizen when the player accepts a job for them.", "Modifiers.Know.AcceptedJobLikeModifier")]
		float AcceptedJobLikeModifier { get; set; }
	}
	[BepInPlugin("Venomaus.SOD.RelationsPlus", "RelationsPlus", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : PluginController<Plugin, IPluginBindings>
	{
		public const string PLUGIN_GUID = "Venomaus.SOD.RelationsPlus";

		public const string PLUGIN_NAME = "RelationsPlus";

		public const string PLUGIN_VERSION = "1.0.1";

		public override void Load()
		{
			base.Harmony.PatchAll(Assembly.GetExecutingAssembly());
			PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Plugin is patched.");
			Lib.SaveGame.OnBeforeNewGame += delegate
			{
				RelationManager.Instance.Clear();
			};
			Lib.SaveGame.OnBeforeLoad += delegate(object? sender, SaveGameArgs e)
			{
				RelationManager.Instance.Load(Lib.SaveGame.GetUniqueString(e.FilePath));
			};
			Lib.SaveGame.OnBeforeSave += delegate(object? sender, SaveGameArgs e)
			{
				RelationManager.Instance.Save(Lib.SaveGame.GetUniqueString(e.FilePath));
			};
			Lib.SaveGame.OnBeforeDelete += delegate(object? sender, SaveGameArgs e)
			{
				RelationManager.Delete(Lib.SaveGame.GetUniqueString(e.FilePath));
			};
			Lib.Time.OnMinuteChanged += RelationManager.Instance.Timed_DecayLogic;
		}

		public override void OnConfigureBindings()
		{
			base.OnConfigureBindings();
			base.UpdateConfigFileLayout();
			base.Config.LikeGateFive = 1f;
			base.Config.KnowGateFive = 1f;
		}
	}
	public sealed class RelationManager : IEnumerable<CitizenRelation>, IEnumerable
	{
		internal enum EventName
		{
			KnowChange,
			LikeChange,
			Seen
		}

		private static RelationManager _instance;

		private readonly Dictionary<int, CitizenRelation> _relationMatrixes = new Dictionary<int, CitizenRelation>();

		private int _lastDecayCheckMinute;

		public static RelationManager Instance => _instance ?? (_instance = new RelationManager());

		public CitizenRelation this[int citizenId] => GetOrCreate(citizenId);

		internal bool IsLoading { get; private set; }

		public event EventHandler<RelationChangeArgs> OnKnowChanged;

		public event EventHandler<RelationChangeArgs> OnLikeChanged;

		public event EventHandler<SeenPlayerArgs> OnPlayerSeen;

		private RelationManager()
		{
		}

		public bool TryGetValue(int citizenId, out CitizenRelation relation)
		{
			return _relationMatrixes.TryGetValue(citizenId, out relation);
		}

		public bool ContainsKey(int citizenId)
		{
			return _relationMatrixes.ContainsKey(citizenId);
		}

		public void Remove(int citizenId)
		{
			_relationMatrixes.Remove(citizenId);
		}

		public CitizenRelation GetOrCreate(int citizenId)
		{
			if (!_relationMatrixes.TryGetValue(citizenId, out var value))
			{
				value = (_relationMatrixes[citizenId] = new CitizenRelation(citizenId));
			}
			return value;
		}

		public void Clear()
		{
			_lastDecayCheckMinute = 0;
			_relationMatrixes.Clear();
		}

		public IEnumerator<CitizenRelation> GetEnumerator()
		{
			return _relationMatrixes.Values.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		internal void AddOrReplace(CitizenRelation relation)
		{
			_relationMatrixes[relation.CitizenId] = relation;
		}

		internal void RaiseEvent(EventName eventName, EventArgs args)
		{
			switch (eventName)
			{
			case EventName.KnowChange:
				this.OnKnowChanged?.Invoke(this, args as RelationChangeArgs);
				return;
			case EventName.LikeChange:
				this.OnLikeChanged?.Invoke(this, args as RelationChangeArgs);
				return;
			case EventName.Seen:
				this.OnPlayerSeen?.Invoke(this, args as SeenPlayerArgs);
				return;
			}
			throw new NotSupportedException($"Event ({eventName}) \"{eventName}\" not supported.");
		}

		internal void Load(string hash)
		{
			IsLoading = true;
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "RelationsPlusData_" + hash + ".json");
			Clear();
			if (File.Exists(savestoreDirectoryPath))
			{
				CitizenSaveData citizenSaveData = JsonSerializer.Deserialize<CitizenSaveData>(File.ReadAllText(savestoreDirectoryPath));
				_lastDecayCheckMinute = citizenSaveData.LastDecayCheckMinute;
				foreach (KeyValuePair<int, CitizenRelation> item in citizenSaveData.RelationMatrix)
				{
					_relationMatrixes.Add(item.Key, item.Value);
				}
				PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Loaded citizen relations.");
			}
			IsLoading = false;
		}

		internal void Save(string hash)
		{
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "RelationsPlusData_" + hash + ".json");
			if (!_relationMatrixes.Any())
			{
				if (File.Exists(savestoreDirectoryPath))
				{
					File.Delete(savestoreDirectoryPath);
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Deleted citizen relations.");
				}
			}
			else
			{
				string contents = JsonSerializer.Serialize(new CitizenSaveData
				{
					RelationMatrix = _relationMatrixes,
					LastDecayCheckMinute = _lastDecayCheckMinute
				}, new JsonSerializerOptions
				{
					WriteIndented = false
				});
				File.WriteAllText(savestoreDirectoryPath, contents);
				PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Saved citizen relations.");
			}
		}

		internal static void Delete(string hash)
		{
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "RelationsPlusData_" + hash + ".json");
			if (File.Exists(savestoreDirectoryPath))
			{
				File.Delete(savestoreDirectoryPath);
				PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Deleted citizen relations.");
			}
		}

		internal void Timed_DecayLogic(object sender, TimeChangedArgs e)
		{
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			if (_lastDecayCheckMinute >= ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DecayTimeMinutesCheck)
			{
				_lastDecayCheckMinute = 0;
				float decayKnowAmount = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DecayKnowAmount;
				int decayKnowAfterUnseenMinutes = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DecayKnowAfterUnseenMinutes;
				bool allowAutoImproveLikeToNeutral = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.AllowAutoImproveLikeToNeutral;
				float improveLikeAmount = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ImproveLikeAmount;
				float decayLikeAmount = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DecayLikeAmount;
				bool allowDecayLikeToNeutral = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.AllowDecayLikeToNeutral;
				bool debugMode = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DebugMode;
				if (debugMode)
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"[Debug]: Start decay process.");
				}
				foreach (CitizenRelation value2 in _relationMatrixes.Values)
				{
					if (!value2.LastSeenGameTime.HasValue)
					{
						continue;
					}
					TimeData value = value2.LastSeenGameTime.Value;
					if (((TimeData)(ref value)).AddMinutes(decayKnowAfterUnseenMinutes) <= Lib.Time.CurrentDateTime)
					{
						float currentKnowGate = GetCurrentKnowGate(value2);
						value2.Know = Mathf.Clamp(value2.Know + decayKnowAmount, currentKnowGate, 1f);
						if (allowDecayLikeToNeutral && value2.Like > 0.5f)
						{
							value2.Like = Mathf.Clamp(value2.Like + decayLikeAmount, 0.5f, 1f);
						}
					}
					if (allowAutoImproveLikeToNeutral && value2.Like < 0.5f)
					{
						value2.Like = Mathf.Clamp(value2.Like + improveLikeAmount, 0f, 0.5f);
					}
				}
				if (debugMode)
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"[Debug]: Finalized decay process.");
				}
			}
			else
			{
				_lastDecayCheckMinute++;
			}
		}

		private static float GetCurrentKnowGate(CitizenRelation citizenRelation)
		{
			if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.AllowDecayPastKnowGates)
			{
				return 0f;
			}
			float know = citizenRelation.Know;
			if (know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateOne)
			{
				return 0f;
			}
			if (know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateTwo)
			{
				return ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateOne;
			}
			if (know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateThree)
			{
				return ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateTwo;
			}
			if (know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateFour)
			{
				return ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateThree;
			}
			return ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateFour;
		}
	}
}
namespace SOD.RelationsPlus.Patches
{
	internal class ActorPatches
	{
		[HarmonyPatch(typeof(Actor), "RecieveDamage")]
		internal static class Actor_RecieveDamage
		{
			[HarmonyPostfix]
			internal static void Prefix(Actor __instance, ref float __state)
			{
				__state = __instance.currentHealth;
			}

			internal static void Postfix(Actor __instance, float amount, Actor fromWho, ref float __state)
			{
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Expected O, but got Unknown
				if (amount == 0f || __instance.currentHealth <= 0f || __instance.isStunned || __instance.currentHealth == __state || __instance.isPlayer || (Object)(object)fromWho == (Object)null || !fromWho.isPlayer)
				{
					return;
				}
				Human val = null;
				try
				{
					val = ((Il2CppObjectBase)__instance).TryCast<Human>();
				}
				catch (InvalidCastException)
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DebugMode)
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Debug]: ");
						((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(val.GetCitizenName());
						((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" was attacked by player!");
					}
					log.LogInfo(val2);
				}
				RelationManager.Instance[val.humanID].Like += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.OnAttackCitizenModifier;
			}
		}
	}
	internal class HumanPatches
	{
		[HarmonyPatch(typeof(Human), "UpdateLastSighting")]
		internal static class Human_UpdateLastSighting
		{
			[HarmonyPrefix]
			internal static void Prefix(Human __instance, Human citizen)
			{
				//IL_0092: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e9: 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_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Unknown result type (might be due to invalid IL or missing references)
				if ((Object)(object)citizen == (Object)null || ((Actor)__instance).isMachine || !((Actor)citizen).isPlayer)
				{
					return;
				}
				CitizenRelation relation;
				bool flag = RelationManager.Instance.TryGetValue(__instance.humanID, out relation);
				if (flag && (relation.WasTrespassingLastTimeSeen || !((Actor)citizen).isTrespassing) && relation.LastSeenGameTime.HasValue)
				{
					TimeData value = relation.LastSeenGameTime.Value;
					if (!(((TimeData)(ref value)).AddMinutes(((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SeenTimeMinutesCheck) <= Lib.Time.CurrentDateTime))
					{
						return;
					}
				}
				float num = Vector3.Distance(((Actor)__instance).lookAtThisTransform.position, ((Actor)citizen).lookAtThisTransform.position);
				float num2 = Mathf.Min(GameplayControls.Instance.citizenSightRange, ((Actor)__instance).stealthDistance);
				RaycastHit val = default(RaycastHit);
				if (!(num <= num2) || (!(num < GameplayControls.Instance.minimumStealthDetectionRange) && !((Actor)__instance).ActorRaycastCheck((Actor)(object)citizen, num + 3f, ref val, false, Color.green, Color.red, Color.white, 1f)))
				{
					return;
				}
				if (relation == null)
				{
					relation = new CitizenRelation(__instance.humanID);
				}
				relation.WasTrespassingLastTimeSeen = ((Actor)citizen).isTrespassing;
				bool flag2 = (Object)(object)((Actor)__instance).currentRoom != (Object)null && (Object)(object)((Actor)citizen).currentRoom != (Object)null && ((Actor)__instance).currentRoom.roomID == ((Actor)citizen).currentRoom.roomID;
				bool flag3 = (Object)(object)((Actor)__instance).currentBuilding != (Object)null && (Object)(object)((Actor)citizen).currentBuilding != (Object)null && ((Actor)__instance).currentBuilding.buildingID == ((Actor)citizen).currentBuilding.buildingID;
				bool flag4 = (Object)(object)__instance.home != (Object)null && (Object)(object)((Actor)citizen).currentGameLocation != (Object)null && (Object)(object)((Actor)citizen).currentGameLocation.thisAsAddress != (Object)null && (Object)(object)((Actor)citizen).currentGameLocation.thisAsAddress == (Object)(object)__instance.home;
				float know = relation.Know;
				float like = relation.Like;
				SeenPlayerArgs.SeenLocation seenLocation = (SeenPlayerArgs.SeenLocation)(-1);
				if (((Actor)__instance).isAtWork && flag2)
				{
					relation.Know += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SeenAtWorkplaceModifier;
					seenLocation = SeenPlayerArgs.SeenLocation.Workplace;
				}
				else if (((Actor)__instance).isHome && flag2)
				{
					relation.Know += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SeenInHomeModifier;
					seenLocation = SeenPlayerArgs.SeenLocation.Home;
				}
				else if (flag4)
				{
					relation.Know += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SeenInHomeBuildingModifier;
					seenLocation = SeenPlayerArgs.SeenLocation.HomeBuilding;
				}
				else if ((((Actor)__instance).isOnStreet && ((Actor)citizen).isOnStreet) || flag2 || flag3)
				{
					relation.Know += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SeenOnStreetModifier;
					seenLocation = SeenPlayerArgs.SeenLocation.Street;
				}
				if (seenLocation != (SeenPlayerArgs.SeenLocation)(-1))
				{
					if (((Actor)citizen).isTrespassing)
					{
						relation.Like += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SeenTrespassingModifier;
					}
					if (!flag)
					{
						RelationManager.Instance.AddOrReplace(relation);
					}
					relation.RaiseSeenEvent(seenLocation, know - relation.Know, like - relation.Like);
				}
			}
		}
	}
	internal class InteractionControllerPatches
	{
		[HarmonyPatch(typeof(InteractionController), "SetIllegalActionActive")]
		internal static class InteractionController_SetIllegalActionActive
		{
			[HarmonyPostfix]
			internal static void Prefix(bool val)
			{
				//IL_010f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0115: Expected O, but got Unknown
				if (!val)
				{
					return;
				}
				Enumerator<Actor> enumerator = CityData.Instance.visibleActors.GetEnumerator();
				bool flag = default(bool);
				while (enumerator.MoveNext())
				{
					Actor current = enumerator.Current;
					if (current.isMachine || current.isPlayer || !GameExtensions.Sees(current, (Actor)(object)Player.Instance))
					{
						continue;
					}
					Human val2 = null;
					try
					{
						val2 = (Human)((dynamic)current).Cast<Human>();
					}
					catch (InvalidCastException)
					{
					}
					if ((Object)(object)val2 == (Object)null)
					{
						continue;
					}
					if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DebugMode)
					{
						ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
						BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(35, 1, ref flag);
						if (flag)
						{
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[Debug]: Illegal activity seen by ");
							((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(val2.GetCitizenName());
							((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("!");
						}
						log.LogInfo(val3);
					}
					RelationManager.Instance[val2.humanID].Like += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SeenDoingIllegalModifier;
				}
			}
		}
	}
	internal class NewAIControllerPatches
	{
		[HarmonyPatch(typeof(NewAIController), "TalkTo")]
		internal static class NewAIController_TalkTo
		{
			[HarmonyPrefix]
			internal static void Prefix(ref Interactable __state)
			{
				__state = ((Actor)Player.Instance).interactingWith;
			}

			[HarmonyPostfix]
			internal static void Postfix(NewAIController __instance, ref Interactable __state)
			{
				if (((Actor)Player.Instance).interactingWith != null && (__state == null || ((Actor)Player.Instance).interactingWith.id != __state.id))
				{
					RelationManager.Instance[__instance.human.humanID].Know += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SpeakingToCitizenModifier;
				}
			}
		}
	}
	internal class SideJobPatches
	{
		[HarmonyPatch(typeof(SideJob), "AcceptJob")]
		internal static class SideJob_AcceptJob
		{
			[HarmonyPrefix]
			internal static void Prefix(SideJob __instance, ref bool __state)
			{
				__state = __instance.accepted;
			}

			[HarmonyPostfix]
			internal static void Postfix(SideJob __instance, ref bool __state)
			{
				if (!__state && __instance.accepted && (Object)(object)__instance.poster != (Object)null && __instance.posterID > 0)
				{
					RelationManager.Instance[__instance.posterID].Know += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.AcceptedJobKnowModifier;
					RelationManager.Instance[__instance.posterID].Like += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.AcceptedJobLikeModifier;
				}
			}
		}

		[HarmonyPatch(typeof(Case), "Resolve")]
		internal static class Case_Resolve
		{
			[HarmonyPostfix]
			internal static void Postfix(Case __instance)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0007: Invalid comparison between Unknown and I4
				if ((int)__instance.caseType == 2 && __instance.job != null && !((Object)(object)__instance.job.poster == (Object)null))
				{
					if (__instance.isSolved)
					{
						RelationManager.Instance[__instance.job.posterID].Like += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SolvedJobModifier;
					}
					else
					{
						RelationManager.Instance[__instance.job.posterID].Like += ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.FailedJobModifier;
					}
				}
			}
		}
	}
}
namespace SOD.RelationsPlus.Objects
{
	public sealed class CitizenRelation
	{
		public enum KnowStage
		{
			Stranger,
			Aware,
			Familiar,
			Known,
			WellKnown
		}

		public enum LikeStage
		{
			Neutral,
			Hated,
			Disliked,
			Liked,
			Loved
		}

		private float _know;

		private float _like = 0.5f;

		public int CitizenId { get; }

		public DateTime? LastSeenRealTime { get; private set; }

		public TimeData? LastSeenGameTime { get; private set; }

		public bool WasTrespassingLastTimeSeen { get; internal set; }

		public float Know
		{
			get
			{
				return _know;
			}
			set
			{
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Expected O, but got Unknown
				float know = _know;
				float num = Mathf.Clamp01(value);
				if (_know == num)
				{
					return;
				}
				_know = num;
				if (RelationManager.Instance.IsLoading)
				{
					return;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DebugMode)
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(75, 5, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Debug]: Citizen(");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(CitizenId);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|");
						Human citizen = GetCitizen();
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((citizen != null) ? citizen.GetCitizenName() : null) ?? "Unknown");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): Changed 'Know' value from \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(know);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" to \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" | KnowRelation: \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<KnowStage>(GetKnowRelation());
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
					}
					log.LogInfo(val);
				}
				RelationChangeArgs relationChangeArgs = null;
				this.OnKnowChanged?.Invoke(this, relationChangeArgs ?? (relationChangeArgs = new RelationChangeArgs(CitizenId, know, num)));
				RelationManager.Instance.RaiseEvent(RelationManager.EventName.KnowChange, relationChangeArgs ?? new RelationChangeArgs(CitizenId, know, num));
			}
		}

		public float Like
		{
			get
			{
				return _like;
			}
			set
			{
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Expected O, but got Unknown
				float like = _like;
				float num = Mathf.Clamp01(value);
				if (_like == num)
				{
					return;
				}
				_like = num;
				if (RelationManager.Instance.IsLoading)
				{
					return;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DebugMode)
				{
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(75, 5, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Debug]: Citizen(");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(CitizenId);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|");
						Human citizen = GetCitizen();
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((citizen != null) ? citizen.GetCitizenName() : null) ?? "Unknown");
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): Changed 'Like' value from \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(like);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" to \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(num);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" | LikeRelation: \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<LikeStage>(GetLikeRelation());
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
					}
					log.LogInfo(val);
				}
				RelationChangeArgs relationChangeArgs = null;
				this.OnLikeChanged?.Invoke(this, relationChangeArgs ?? (relationChangeArgs = new RelationChangeArgs(CitizenId, like, num)));
				RelationManager.Instance.RaiseEvent(RelationManager.EventName.LikeChange, relationChangeArgs ?? new RelationChangeArgs(CitizenId, like, num));
			}
		}

		public event EventHandler<RelationChangeArgs> OnKnowChanged;

		public event EventHandler<RelationChangeArgs> OnLikeChanged;

		public event EventHandler<SeenPlayerArgs> OnPlayerSeen;

		public KnowStage GetKnowRelation()
		{
			if (Know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateOne)
			{
				return KnowStage.Stranger;
			}
			if (Know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateTwo)
			{
				return KnowStage.Aware;
			}
			if (Know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateThree)
			{
				return KnowStage.Familiar;
			}
			if (Know < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.KnowGateFour)
			{
				return KnowStage.Known;
			}
			return KnowStage.WellKnown;
		}

		public LikeStage GetLikeRelation()
		{
			if (Like < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LikeGateOne)
			{
				return LikeStage.Hated;
			}
			if (Like < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LikeGateTwo)
			{
				return LikeStage.Disliked;
			}
			if (Like < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LikeGateThree)
			{
				return LikeStage.Neutral;
			}
			if (Like < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LikeGateFour)
			{
				return LikeStage.Liked;
			}
			return LikeStage.Loved;
		}

		[JsonConstructor]
		public CitizenRelation(int citizenId)
		{
			CitizenId = citizenId;
		}

		public Human GetCitizen()
		{
			Human result = default(Human);
			if (!CityData.Instance.citizenDictionary.TryGetValue(CitizenId, ref result))
			{
				return null;
			}
			return result;
		}

		internal void RaiseSeenEvent(SeenPlayerArgs.SeenLocation location, float knowChange, float likeChange)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			LastSeenRealTime = DateTime.Now;
			LastSeenGameTime = Lib.Time.CurrentDateTime;
			if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DebugMode)
			{
				ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(44, 4, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Debug]: Citizen(");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(CitizenId);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|");
					Human citizen = GetCitizen();
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((citizen != null) ? citizen.GetCitizenName() : null) ?? "Unknown");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): saw player at \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<SeenPlayerArgs.SeenLocation>(location);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" on \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<TimeData?>(LastSeenGameTime);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\".");
				}
				log.LogInfo(val);
			}
			SeenPlayerArgs seenPlayerArgs = null;
			this.OnPlayerSeen?.Invoke(this, seenPlayerArgs ?? (seenPlayerArgs = new SeenPlayerArgs(CitizenId, location, knowChange, likeChange)));
			RelationManager.Instance.RaiseEvent(RelationManager.EventName.Seen, seenPlayerArgs ?? new SeenPlayerArgs(CitizenId, location, knowChange, likeChange));
		}
	}
	public class CitizenSaveData
	{
		public int LastDecayCheckMinute { get; set; }

		public Dictionary<int, CitizenRelation> RelationMatrix { get; set; }
	}
	public sealed class RelationChangeArgs : EventArgs
	{
		public int CitizenId { get; }

		public float OldValue { get; }

		public float NewValue { get; }

		internal RelationChangeArgs(int citizenId, float oldValue, float newValue)
		{
			CitizenId = citizenId;
			OldValue = oldValue;
			NewValue = newValue;
		}
	}
	public sealed class SeenPlayerArgs : EventArgs
	{
		public enum SeenLocation
		{
			Street,
			Workplace,
			Home,
			HomeBuilding
		}

		public int CitizenId { get; }

		public float KnowChange { get; }

		public float LikeChange { get; }

		public SeenLocation Location { get; }

		public DateTime SeenRealTime { get; }

		public TimeData SeenGameTime { get; }

		internal SeenPlayerArgs(int citizenId, SeenLocation location, float knowChange, float likeChange)
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			CitizenId = citizenId;
			KnowChange = knowChange;
			LikeChange = likeChange;
			Location = location;
			SeenRealTime = DateTime.Now;
			SeenGameTime = Lib.Time.CurrentDateTime;
		}
	}
}