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+10efc3839fe9f5f88e17cd1942686b35caddd3fe")] [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 attacks 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", "SOD.RelationsPlus", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : PluginController { public const string PLUGIN_GUID = "Venomaus.SOD.RelationsPlus"; public const string PLUGIN_NAME = "SOD.RelationsPlus"; public const string PLUGIN_VERSION = "1.0.3"; public override void Load() { base.Harmony.PatchAll(Assembly.GetExecutingAssembly()); PluginController.Log.LogInfo((object)"Plugin is patched."); Lib.SaveGame.OnBeforeNewGame += delegate { RelationManager.Instance.Clear(); }; Lib.SaveGame.OnBeforeLoad += delegate(object? sender, SaveGameArgs e) { RelationManager.Instance.Load(e); }; Lib.SaveGame.OnBeforeSave += delegate(object? sender, SaveGameArgs e) { RelationManager.Instance.Save(e); }; Lib.SaveGame.OnBeforeDelete += delegate(object? sender, SaveGameArgs e) { RelationManager.Delete(e); }; 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, IEnumerable { internal enum EventName { KnowChange, LikeChange, Seen } private static RelationManager _instance; private readonly Dictionary _relationMatrixes = new Dictionary(); 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 OnKnowChanged; public event EventHandler OnLikeChanged; public event EventHandler 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 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(SaveGameArgs e) { IsLoading = true; string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath); string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "RelationsPlusData_" + uniqueString + ".json"); string path = Lib.SaveGame.MigrateOldSaveStructure(savestoreDirectoryPath, e, "sod_relationsplus_RelationsPlusData.json"); Clear(); if (File.Exists(path)) { CitizenSaveData citizenSaveData = JsonSerializer.Deserialize(File.ReadAllText(path)); _lastDecayCheckMinute = citizenSaveData.LastDecayCheckMinute; foreach (KeyValuePair item in citizenSaveData.RelationMatrix) { _relationMatrixes.Add(item.Key, item.Value); } PluginController.Log.LogInfo((object)"Loaded citizen relations."); } IsLoading = false; } internal void Save(SaveGameArgs e) { string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath); string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "RelationsPlusData_" + uniqueString + ".json"); string path = Lib.SaveGame.MigrateOldSaveStructure(savestoreDirectoryPath, e, "sod_relationsplus_RelationsPlusData.json"); if (!_relationMatrixes.Any()) { if (File.Exists(path)) { File.Delete(path); PluginController.Log.LogInfo((object)"Deleted citizen relations."); } } else { string contents = JsonSerializer.Serialize(new CitizenSaveData { RelationMatrix = _relationMatrixes, LastDecayCheckMinute = _lastDecayCheckMinute }, new JsonSerializerOptions { WriteIndented = false }); File.WriteAllText(path, contents); PluginController.Log.LogInfo((object)"Saved citizen relations."); } } internal static void Delete(SaveGameArgs e) { string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath); string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "RelationsPlusData_" + uniqueString + ".json"); Lib.SaveGame.MigrateOldSaveStructure(savestoreDirectoryPath, e, "sod_relationsplus_RelationsPlusData.json"); } 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)PluginController.Instance).Config.DecayTimeMinutesCheck) { _lastDecayCheckMinute = 0; float decayKnowAmount = ((PluginController)PluginController.Instance).Config.DecayKnowAmount; int decayKnowAfterUnseenMinutes = ((PluginController)PluginController.Instance).Config.DecayKnowAfterUnseenMinutes; bool allowAutoImproveLikeToNeutral = ((PluginController)PluginController.Instance).Config.AllowAutoImproveLikeToNeutral; float improveLikeAmount = ((PluginController)PluginController.Instance).Config.ImproveLikeAmount; float decayLikeAmount = ((PluginController)PluginController.Instance).Config.DecayLikeAmount; bool allowDecayLikeToNeutral = ((PluginController)PluginController.Instance).Config.AllowDecayLikeToNeutral; bool debugMode = ((PluginController)PluginController.Instance).Config.DebugMode; if (debugMode) { PluginController.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.Log.LogInfo((object)"[Debug]: Finalized decay process."); } } else { _lastDecayCheckMinute++; } } private static float GetCurrentKnowGate(CitizenRelation citizenRelation) { if (((PluginController)PluginController.Instance).Config.AllowDecayPastKnowGates) { return 0f; } float know = citizenRelation.Know; if (know < ((PluginController)PluginController.Instance).Config.KnowGateOne) { return 0f; } if (know < ((PluginController)PluginController.Instance).Config.KnowGateTwo) { return ((PluginController)PluginController.Instance).Config.KnowGateOne; } if (know < ((PluginController)PluginController.Instance).Config.KnowGateThree) { return ((PluginController)PluginController.Instance).Config.KnowGateTwo; } if (know < ((PluginController)PluginController.Instance).Config.KnowGateFour) { return ((PluginController)PluginController.Instance).Config.KnowGateThree; } return ((PluginController)PluginController.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(); } catch (InvalidCastException) { } if ((Object)(object)val == (Object)null) { return; } if (((PluginController)PluginController.Instance).Config.DebugMode) { ManualLogSource log = PluginController.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[Debug]: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted(val.GetCitizenName()); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" was attacked by player!"); } log.LogInfo(val2); } RelationManager.Instance[val.humanID].Like += ((PluginController)PluginController.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)PluginController.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)PluginController.Instance).Config.SeenAtWorkplaceModifier; seenLocation = SeenPlayerArgs.SeenLocation.Workplace; } else if (((Actor)__instance).isHome && flag2) { relation.Know += ((PluginController)PluginController.Instance).Config.SeenInHomeModifier; seenLocation = SeenPlayerArgs.SeenLocation.Home; } else if (flag4) { relation.Know += ((PluginController)PluginController.Instance).Config.SeenInHomeBuildingModifier; seenLocation = SeenPlayerArgs.SeenLocation.HomeBuilding; } else if ((((Actor)__instance).isOnStreet && ((Actor)citizen).isOnStreet) || flag2 || flag3) { relation.Know += ((PluginController)PluginController.Instance).Config.SeenOnStreetModifier; seenLocation = SeenPlayerArgs.SeenLocation.Street; } if (seenLocation != (SeenPlayerArgs.SeenLocation)(-1)) { if (((Actor)citizen).isTrespassing) { relation.Like += ((PluginController)PluginController.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 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(); } catch (InvalidCastException) { } if ((Object)(object)val2 == (Object)null) { continue; } if (((PluginController)PluginController.Instance).Config.DebugMode) { ManualLogSource log = PluginController.Log; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(35, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[Debug]: Illegal activity seen by "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted(val2.GetCitizenName()); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("!"); } log.LogInfo(val3); } RelationManager.Instance[val2.humanID].Like += ((PluginController)PluginController.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)PluginController.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)PluginController.Instance).Config.AcceptedJobKnowModifier; RelationManager.Instance[__instance.posterID].Like += ((PluginController)PluginController.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)PluginController.Instance).Config.SolvedJobModifier; } else { RelationManager.Instance[__instance.job.posterID].Like += ((PluginController)PluginController.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)PluginController.Instance).Config.DebugMode) { ManualLogSource log = PluginController.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(75, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Debug]: Citizen("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CitizenId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|"); Human citizen = GetCitizen(); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((citizen != null) ? citizen.GetCitizenName() : null) ?? "Unknown"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): Changed 'Know' value from \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(know); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" to \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" | KnowRelation: \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(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)PluginController.Instance).Config.DebugMode) { ManualLogSource log = PluginController.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(75, 5, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Debug]: Citizen("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CitizenId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|"); Human citizen = GetCitizen(); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((citizen != null) ? citizen.GetCitizenName() : null) ?? "Unknown"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): Changed 'Like' value from \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(like); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" to \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(num); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" | LikeRelation: \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(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 OnKnowChanged; public event EventHandler OnLikeChanged; public event EventHandler OnPlayerSeen; public KnowStage GetKnowRelation() { if (Know < ((PluginController)PluginController.Instance).Config.KnowGateOne) { return KnowStage.Stranger; } if (Know < ((PluginController)PluginController.Instance).Config.KnowGateTwo) { return KnowStage.Aware; } if (Know < ((PluginController)PluginController.Instance).Config.KnowGateThree) { return KnowStage.Familiar; } if (Know < ((PluginController)PluginController.Instance).Config.KnowGateFour) { return KnowStage.Known; } return KnowStage.WellKnown; } public LikeStage GetLikeRelation() { if (Like < ((PluginController)PluginController.Instance).Config.LikeGateOne) { return LikeStage.Hated; } if (Like < ((PluginController)PluginController.Instance).Config.LikeGateTwo) { return LikeStage.Disliked; } if (Like < ((PluginController)PluginController.Instance).Config.LikeGateThree) { return LikeStage.Neutral; } if (Like < ((PluginController)PluginController.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)PluginController.Instance).Config.DebugMode) { ManualLogSource log = PluginController.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(44, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Debug]: Citizen("); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(CitizenId); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("|"); Human citizen = GetCitizen(); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(((citizen != null) ? citizen.GetCitizenName() : null) ?? "Unknown"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("): saw player at \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(location); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" on \""); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted(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 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; } } }