using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("SoDPinObjectiveLeads")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("SoDPinObjectiveLeads")]
[assembly: AssemblyTitle("SoDPinObjectiveLeads")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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]
[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;
}
}
[CompilerGenerated]
[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 SoDPinObjectiveLeads
{
[BepInPlugin("sm3gm.sod.pinobjectiveleads", "Pin Objective Leads", "1.0.0")]
public class Plugin : BasePlugin
{
public const string GUID = "sm3gm.sod.pinobjectiveleads";
public const string VER = "1.0.0";
internal static ManualLogSource L;
internal static ConfigEntry<bool> PinAddresses;
internal static ConfigEntry<bool> PinPhones;
internal static ConfigEntry<bool> IncludeMurder;
internal static ConfigEntry<bool> IncludeSideJobs;
internal static ConfigEntry<bool> PinSightings;
public override void Load()
{
L = ((BasePlugin)this).Log;
PinAddresses = ((BasePlugin)this).Config.Bind<bool>("Pin", "Addresses", true, "When a HUD objective names a place (Fry Boulevard, an apartment), pin it on that case board so it is clickable and you can autotravel.");
PinPhones = ((BasePlugin)this).Config.Bind<bool>("Pin", "Phones", true, "When a HUD objective is a call or a phone at a place, pin that number on the case board.");
PinSightings = ((BasePlugin)this).Config.Bind<bool>("Pin", "Sightings", true, "When you ask someone \"Have you seen...\" and they name a place (where they saw the person, or where the person lives or works), pin it on the case board.");
IncludeMurder = ((BasePlugin)this).Config.Bind<bool>("Cases", "Murder", true, "Also pin from murder-case objectives.");
IncludeSideJobs = ((BasePlugin)this).Config.Bind<bool>("Cases", "SideJobs", true, "Also pin from sidejob objectives.");
Harmony.CreateAndPatchAll(typeof(AddObjectivePatch), (string)null);
Harmony.CreateAndPatchAll(typeof(CleanUpWords), (string)null);
Harmony.CreateAndPatchAll(typeof(SightingProbe), (string)null);
((BasePlugin)this).AddComponent<ScanBehaviour>();
L.LogInfo((object)("=== SoDPinObjectiveLeads 1.0.0 starting addr=" + PinAddresses.Value + " phone=" + PinPhones.Value + " murder=" + IncludeMurder.Value + " sidejob=" + IncludeSideJobs.Value + " ==="));
}
}
public class ScanBehaviour : MonoBehaviour
{
private float _acc;
public ScanBehaviour(IntPtr ptr)
: base(ptr)
{
}
private void Update()
{
_acc += Time.unscaledDeltaTime;
if (!(_acc < 1f))
{
_acc = 0f;
Pinner.ScanActiveCases();
}
}
}
[HarmonyPatch(typeof(Strings), "GetContainedValue")]
public static class CleanUpWords
{
internal static NewGameLocation? Heard;
private static float armedUntil = -1f;
private static void Postfix(string withinScope, string newValue, Object inputObject)
{
try
{
string text = (withinScope ?? "").ToLowerInvariant();
string text2 = (newValue ?? "").ToLowerInvariant();
if (text == "killer" && text2 == "cleanupreward")
{
armedUntil = Time.unscaledTime + 30f;
}
else if (!(Time.unscaledTime > armedUntil) && inputObject != null && !(text2 != "name"))
{
NewAddress val = ((Il2CppObjectBase)inputObject).TryCast<NewAddress>();
if (!((Object)(object)val == (Object)null))
{
armedUntil = -1f;
Heard = (NewGameLocation?)(object)val;
Plugin.L.LogInfo((object)("[PIN] clean-up call names " + ((Object)val).name));
}
}
}
catch
{
}
}
}
[HarmonyPatch(typeof(Case), "AddObjective")]
public static class AddObjectivePatch
{
private static void Postfix(Case __instance)
{
try
{
Pinner.PinFromCase(__instance);
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("[PIN] AddObjective: " + ex.Message));
}
}
}
internal static class Pinner
{
private static readonly HashSet<string> Once = new HashSet<string>();
private static readonly Dictionary<string, string> LastSig = new Dictionary<string, string>();
private static int _lastActive = -1;
private static string? _toldCleanUp;
private static void LogSig(Case c, string sig, string msg)
{
string key = ((c.name != null) ? c.name : "?");
if (!LastSig.TryGetValue(key, out var value) || !(value == sig))
{
LastSig[key] = sig;
Plugin.L.LogInfo((object)("[PIN] " + msg));
}
}
internal static void ScanActiveCases()
{
try
{
CasePanelController instance = CasePanelController.Instance;
if (!((Object)(object)instance == (Object)null) && instance.activeCases != null)
{
List<Case> activeCases = instance.activeCases;
if (activeCases.Count != _lastActive)
{
_lastActive = activeCases.Count;
Plugin.L.LogInfo((object)("[PIN] active cases=" + activeCases.Count));
}
for (int i = 0; i < activeCases.Count; i++)
{
PinFromCase(activeCases[i]);
}
CleanUpCall(instance);
Sightings(instance);
}
}
catch
{
}
}
private static void CleanUpCall(CasePanelController panel)
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Invalid comparison between Unknown and I4
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Invalid comparison between Unknown and I4
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_0082: Invalid comparison between Unknown and I4
MurderController instance = MurderController.Instance;
if ((Object)(object)instance == (Object)null || !Plugin.IncludeMurder.Value)
{
return;
}
PhoneCall coverUpCall = instance.coverUpCall;
if (coverUpCall == null)
{
return;
}
CallState state = coverUpCall.state;
if ((int)state != 3 && (int)state != 4)
{
return;
}
NewGameLocation heard = CleanUpWords.Heard;
if ((Object)(object)heard == (Object)null)
{
return;
}
Case val = instance.currentActiveCase;
if (val == null && panel.activeCases != null)
{
for (int i = 0; i < panel.activeCases.Count; i++)
{
if (panel.activeCases[i] != null && (int)panel.activeCases[i].caseType == 1)
{
val = panel.activeCases[i];
break;
}
}
}
if ((Object)(object)heard == (Object)null || val == null)
{
return;
}
if (Once.Contains(val.name + ":loc:" + ((Object)heard).name))
{
if (_toldCleanUp != ((Object)heard).name)
{
_toldCleanUp = ((Object)heard).name;
Plugin.L.LogInfo((object)("[PIN] clean-up call place " + ((Object)heard).name + " was already pinned to " + val.name));
}
}
else
{
PinNamedLocation(panel, val, heard, "clean-up call");
}
}
private static void Sightings(CasePanelController panel)
{
if (SightingProbe.Heard.Count == 0)
{
return;
}
try
{
if ((Object)(object)InteractionController.Instance != (Object)null && InteractionController.Instance.dialogMode)
{
return;
}
}
catch
{
}
Case activeCase = panel.activeCase;
if (activeCase == null)
{
return;
}
List<NewGameLocation> list;
lock (SightingProbe.Heard)
{
list = new List<NewGameLocation>(SightingProbe.Heard);
SightingProbe.Heard.Clear();
}
foreach (NewGameLocation item in list)
{
PinNamedLocation(panel, activeCase, item, "sighting");
}
}
internal static void PinFromCase(Case c)
{
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
if (c == null)
{
return;
}
string text = "?";
try
{
text = ((object)c.caseType/*cast due to .constrained prefix*/).ToString();
}
catch
{
}
if (!CaseWanted(c))
{
LogSig(c, "unwanted:" + text, "case=" + c.name + " type=" + text + " skipped: type not wanted or disabled in config");
return;
}
CasePanelController instance = CasePanelController.Instance;
if ((Object)(object)instance == (Object)null)
{
return;
}
List<Objective> currentActiveObjectives = c.currentActiveObjectives;
if (currentActiveObjectives == null)
{
LogSig(c, "nullobjs", "case=" + c.name + " type=" + text + " currentActiveObjectives is null");
return;
}
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
int num5 = 0;
for (int i = 0; i < currentActiveObjectives.Count; i++)
{
Objective val = currentActiveObjectives[i];
if (val == null || val.isComplete || val.isCancelled)
{
continue;
}
List<ObjectiveTrigger> list = new List<ObjectiveTrigger>();
try
{
if (val.queueElement != null && val.queueElement.triggers != null)
{
Enumerator<ObjectiveTrigger> enumerator = val.queueElement.triggers.GetEnumerator();
while (enumerator.MoveNext())
{
ObjectiveTrigger current = enumerator.Current;
list.Add(current);
}
}
}
catch
{
}
try
{
if (val.appliedProgress != null)
{
Enumerator<ObjectiveTrigger> enumerator = val.appliedProgress.GetEnumerator();
while (enumerator.MoveNext())
{
ObjectiveTrigger current2 = enumerator.Current;
list.Add(current2);
}
}
}
catch
{
}
try
{
if (val.objectiveAddOn != null)
{
list.Add(val.objectiveAddOn);
}
}
catch
{
}
for (int j = 0; j < list.Count; j++)
{
ObjectiveTrigger val2 = list[j];
if (val2 != null)
{
num2++;
NewGameLocation val3 = LocationFromTrigger(val2);
if ((Object)(object)val3 != (Object)null)
{
num3++;
}
if (IsNamed(val3))
{
num4++;
}
bool flag = IsPhoneTrigger(val2);
if (flag)
{
num5++;
}
if (Plugin.PinAddresses.Value && PinNamedLocation(instance, c, val3, "obj"))
{
num++;
}
if (Plugin.PinPhones.Value && flag && PinPhonesAt(instance, c, val3, val2))
{
num++;
}
}
}
}
LogSig(c, currentActiveObjectives.Count + "/" + num2 + "/" + num3 + "/" + num4 + "/" + num5, "case=" + c.name + " type=" + text + " objs=" + currentActiveObjectives.Count + " triggers=" + num2 + " withLocation=" + num3 + " named=" + num4 + " phoneTriggers=" + num5);
if (num <= 0)
{
return;
}
Plugin.L.LogInfo((object)("[PIN] relock after " + num + " pins case=" + c.name));
try
{
Cursor.lockState = (CursorLockMode)1;
Cursor.visible = false;
}
catch
{
}
}
private static bool AlreadyPinned(Evidence ev, DataKey key)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
try
{
List<DataKey> val = new List<DataKey>();
val.Add(key);
return (Object)(object)ev.GetPinned(val) != (Object)null;
}
catch
{
return false;
}
}
private static bool CaseWanted(Case c)
{
//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)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Invalid comparison between Unknown and I4
try
{
CaseType caseType = c.caseType;
if ((int)caseType == 1)
{
return Plugin.IncludeMurder.Value;
}
if ((int)caseType == 2)
{
return Plugin.IncludeSideJobs.Value;
}
return true;
}
catch
{
return true;
}
}
private static bool IsPhoneTrigger(ObjectiveTrigger t)
{
//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)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Invalid comparison between Unknown and I4
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Invalid comparison between Unknown and I4
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Invalid comparison between Unknown and I4
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
try
{
ObjectiveTriggerType triggerType = t.triggerType;
return (int)triggerType == 14 || (int)triggerType == 20 || (int)triggerType == 31 || (int)triggerType == 52;
}
catch
{
return false;
}
}
private static NewGameLocation LocationFromTrigger(ObjectiveTrigger t)
{
try
{
if ((Object)(object)t.gameLocation != (Object)null)
{
return t.gameLocation;
}
}
catch
{
}
try
{
if ((Object)(object)t.room != (Object)null && (Object)(object)t.room.gameLocation != (Object)null)
{
return t.room.gameLocation;
}
}
catch
{
}
try
{
if ((Object)(object)t.door != (Object)null && t.door.wall != null && t.door.wall.node != null)
{
return t.door.wall.node.gameLocation;
}
}
catch
{
}
try
{
if (t.node != null && (Object)(object)t.node.gameLocation != (Object)null)
{
return t.node.gameLocation;
}
}
catch
{
}
try
{
if (t.interactable != null && t.interactable.node != null)
{
return t.interactable.node.gameLocation;
}
}
catch
{
}
try
{
if (t.addressID > 0)
{
CityData instance = CityData.Instance;
NewAddress result = default(NewAddress);
if ((Object)(object)instance != (Object)null && instance.addressDictionary != null && instance.addressDictionary.TryGetValue(t.addressID, ref result))
{
return (NewGameLocation)(object)result;
}
}
}
catch
{
}
try
{
if (t.streetID > 0)
{
List<StreetController> val = (((Object)(object)CityData.Instance != (Object)null) ? CityData.Instance.streetDirectory : null);
if (val != null)
{
for (int i = 0; i < val.Count; i++)
{
StreetController val2 = val[i];
if ((Object)(object)val2 != (Object)null && val2.streetID == t.streetID)
{
return (NewGameLocation)(object)val2;
}
}
}
}
}
catch
{
}
return null;
}
private static bool IsNamed(NewGameLocation loc)
{
if ((Object)(object)loc == (Object)null)
{
return false;
}
try
{
string name = ((Object)loc).name;
if (string.IsNullOrEmpty(name))
{
return false;
}
string text = name.ToLowerInvariant();
return text != "unknown" && !text.Contains("unknown");
}
catch
{
return false;
}
}
private static bool PinNamedLocation(CasePanelController panel, Case c, NewGameLocation loc, string why)
{
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
if (!IsNamed(loc))
{
return false;
}
string text = c.name + ":loc:" + ((Object)loc).name;
if (IsAnswer(c, loc))
{
if (Once.Add(text + ":answer"))
{
Plugin.L.LogInfo((object)("[PIN] not pinned, it is an answer: " + ((Object)loc).name + " (" + why + ") case=" + c.name));
}
return false;
}
if (Once.Contains(text))
{
return false;
}
try
{
EvidenceLocation evidenceEntry = loc.evidenceEntry;
if (evidenceEntry == null)
{
return false;
}
try
{
((Evidence)evidenceEntry).AddDiscovery((Discovery)7);
}
catch
{
}
try
{
((Evidence)evidenceEntry).AddDiscovery((Discovery)0);
}
catch
{
}
try
{
((Evidence)evidenceEntry).AddOrSetCustomName((DataKey)0, ((Object)loc).name);
}
catch
{
}
try
{
((Evidence)evidenceEntry).AddOrSetCustomName((DataKey)14, ((Object)loc).name);
}
catch
{
}
List<DataKey> val = new List<DataKey>();
val.Add((DataKey)14);
val.Add((DataKey)0);
val.Add((DataKey)36);
bool flag = false;
try
{
flag = (Object)(object)((Evidence)evidenceEntry).GetPinned(val) != (Object)null;
}
catch
{
}
if (!flag)
{
flag = AlreadyPinned((Evidence)(object)evidenceEntry, (DataKey)14);
}
if (flag)
{
Once.Add(text);
Plugin.L.LogInfo((object)("[PIN] location already pinned, skipped " + ((Object)loc).name + " (" + why + ") case=" + c.name));
return false;
}
panel.PinToCasePanel(c, (Evidence)(object)evidenceEntry, val, true, Vector2.zero, false);
Once.Add(text);
Plugin.L.LogInfo((object)("[PIN] location " + ((Object)loc).name + " (" + why + ") case=" + c.name));
return true;
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("[PIN] loc " + why + ": " + ex.Message));
return false;
}
}
private static bool IsAnswer(Case c, NewGameLocation loc)
{
try
{
SideJob val = ((c != null) ? c.job : null);
if (val == null || (Object)(object)loc == (Object)null)
{
return false;
}
Human purp = val.purp;
if ((Object)(object)purp != (Object)null)
{
if (Same((NewGameLocation)(object)purp.home))
{
return true;
}
try
{
Occupation job = purp.job;
object x;
if (job == null)
{
x = null;
}
else
{
Company employer = job.employer;
x = ((employer != null) ? employer.address : null);
}
if (Same((NewGameLocation)x))
{
return true;
}
}
catch
{
}
}
if (val.activeJobItems != null)
{
Enumerator<JobTag, Interactable> enumerator = val.activeJobItems.GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<JobTag, Interactable> current = enumerator.Current;
try
{
Interactable value = current.Value;
if (value != null)
{
NewNode obj2 = value.node ?? value.spawnNode;
if (Same((obj2 != null) ? obj2.gameLocation : null))
{
return true;
}
}
}
catch
{
}
}
}
}
catch
{
}
return false;
bool Same(NewGameLocation val2)
{
if ((Object)(object)val2 != (Object)null)
{
return ((Il2CppObjectBase)val2).Pointer == ((Il2CppObjectBase)loc).Pointer;
}
return false;
}
}
private static bool PinPhonesAt(CasePanelController panel, Case c, NewGameLocation loc, ObjectiveTrigger t)
{
int num = 0;
try
{
Evidence evidence = t.evidence;
EvidenceTelephone val = ((evidence != null) ? ((Il2CppObjectBase)evidence).TryCast<EvidenceTelephone>() : null);
if (val != null && val.telephone != null && PinTelephone(panel, c, val.telephone, "trigger"))
{
num++;
}
}
catch
{
}
try
{
if ((Object)(object)loc != (Object)null && loc.telephones != null)
{
int num2 = loc.telephones.Count;
if (num2 > 2)
{
num2 = 2;
}
for (int i = 0; i < num2; i++)
{
if (PinTelephone(panel, c, loc.telephones[i], "loc"))
{
num++;
}
}
}
}
catch
{
}
return num > 0;
}
private static bool PinTelephone(CasePanelController panel, Case c, Telephone tel, string why)
{
//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
if (tel == null)
{
return false;
}
string item = c.name + ":phone:" + tel.number;
if (Once.Contains(item))
{
return false;
}
try
{
if (tel.telephoneEntry == null)
{
tel.CreateEvidence();
}
EvidenceTelephone telephoneEntry = tel.telephoneEntry;
if (telephoneEntry == null)
{
return false;
}
try
{
((Evidence)telephoneEntry).AddDiscovery((Discovery)6);
}
catch
{
}
if (AlreadyPinned((Evidence)(object)telephoneEntry, (DataKey)33))
{
Once.Add(item);
Plugin.L.LogInfo((object)("[PIN] phone already pinned, skipped " + tel.numberString + " (" + why + ") case=" + c.name));
return false;
}
panel.PinToCasePanel(c, (Evidence)(object)telephoneEntry, (DataKey)33, true, Vector2.zero, false);
Once.Add(item);
Plugin.L.LogInfo((object)("[PIN] phone " + tel.numberString + " (" + why + ") case=" + c.name));
return true;
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("[PIN] phone " + why + ": " + ex.Message));
return false;
}
}
}
[HarmonyPatch]
public static class SightingProbe
{
internal static float ArmedUntil = -1f;
private static Human? asked;
private static string? seenAt;
private static int words;
private static readonly HashSet<string> Seen = new HashSet<string>();
internal static readonly List<NewGameLocation> Heard = new List<NewGameLocation>();
[HarmonyPatch(typeof(Human), "RevealSighting", new Type[]
{
typeof(Human),
typeof(bool),
typeof(bool),
typeof(SpeechController),
typeof(bool)
})]
[HarmonyPrefix]
private static void Ask(Human __instance, Human prospectCitizen, bool allowCalls, bool allowSounds)
{
try
{
Arm();
asked = prospectCitizen;
seenAt = null;
Find($"[SIGHT] ask: {Name(__instance)} about {Name(prospectCitizen)} (calls={allowCalls}, sounds={allowSounds})");
}
catch
{
}
}
[HarmonyPatch(typeof(Human), "RevealSighting", new Type[]
{
typeof(Human),
typeof(Sighting),
typeof(SpeechController)
})]
[HarmonyPrefix]
private static void Reveal(Human __instance, Human prospectCitizen, Sighting sighting)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
try
{
Arm();
asked = prospectCitizen;
seenAt = null;
try
{
NewNode? obj = Node(sighting.node);
object obj2;
if (obj == null)
{
obj2 = null;
}
else
{
NewGameLocation gameLocation = obj.gameLocation;
obj2 = ((gameLocation != null) ? ((Object)gameLocation).name : null);
}
seenAt = (string?)obj2;
}
catch
{
}
if (sighting == null)
{
Find("[SIGHT] " + Name(__instance) + " about " + Name(prospectCitizen) + ": no sighting");
return;
}
float num = 0f;
try
{
num = SessionData.Instance.gameTime - sighting.time;
}
catch
{
}
Find($"[SIGHT] {Name(__instance)} saw {Name(prospectCitizen)} {num:0.00} h ago, mov={sighting.mov} run={sighting.run} phone={sighting.phone} poi={sighting.poi} sound={sighting.sound} exp={sighting.exp}" + " | at " + Where(sighting.node) + " | heading " + Where(sighting.dest));
}
catch (Exception ex)
{
Plugin.L.LogInfo((object)("[SIGHT] reveal: " + ex.Message));
}
}
[HarmonyPatch(typeof(Strings), "GetContainedValue")]
[HarmonyPostfix]
private static void Word(string withinScope, string newValue, Object inputObject)
{
if (Time.unscaledTime > ArmedUntil || words++ > 40)
{
return;
}
try
{
string text = "-";
if (inputObject != null)
{
NewGameLocation val = ((Il2CppObjectBase)inputObject).TryCast<NewGameLocation>();
Human val2 = ((Il2CppObjectBase)inputObject).TryCast<Human>();
text = (((Object)(object)val != (Object)null) ? ("location " + Describe(val)) : (((Object)(object)val2 != (Object)null) ? ("person " + Name(val2)) : ((MemberInfo)inputObject.GetIl2CppType()).Name));
}
Find("[SIGHT] word " + withinScope + "." + newValue + " -> " + text);
Truth((inputObject != null) ? ((Il2CppObjectBase)inputObject).TryCast<NewGameLocation>() : null);
NewGameLocation val3 = ((inputObject != null) ? ((Il2CppObjectBase)inputObject).TryCast<NewGameLocation>() : null);
if (!((Object)(object)val3 != (Object)null) || !Plugin.PinSightings.Value)
{
return;
}
lock (Heard)
{
if (!Heard.Contains(val3))
{
Heard.Add(val3);
}
}
}
catch
{
}
}
private static void Truth(NewGameLocation? said)
{
if ((Object)(object)said == (Object)null || (Object)(object)asked == (Object)null)
{
return;
}
string name = ((Object)said).name;
string text = "";
string text2 = "";
try
{
text = (((Object)(object)asked.home != (Object)null) ? ((Object)asked.home).name : "");
}
catch
{
}
try
{
Occupation job = asked.job;
Company val = ((job != null) ? job.employer : null);
if (val != null)
{
text2 = (((Object)(object)val.placeOfBusiness != (Object)null) ? ((Object)val.placeOfBusiness).name : (((Object)(object)val.address != (Object)null) ? ((Object)val.address).name : ""));
}
}
catch
{
}
bool flag = false;
try
{
flag = (Object)(object)said.thisAsStreet != (Object)null;
}
catch
{
}
string text3 = ((flag && seenAt != null) ? ((name == seenAt) ? "true (where the sighting was)" : ("WRONG: the sighting was on " + seenAt)) : ((name == text) ? "true (their home)" : ((name == text2) ? "true (their workplace)" : ((!flag) ? ("WRONG: home is " + text + ", work is " + text2) : "no sighting to compare"))));
Find("[SIGHT] check: says '" + name + "' about " + Name(asked) + ": " + text3);
}
private static NewNode? Node(Vector3 node)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
Dictionary<Vector3, NewNode> nodeMap = PathFinder.Instance.nodeMap;
NewNode val = null;
if (nodeMap.TryGetValue(node, ref val) && val != null)
{
return val;
}
if (nodeMap.TryGetValue(CityData.Instance.RealPosToNode(node), ref val) && val != null)
{
return val;
}
return null;
}
private static void Arm()
{
ArmedUntil = Time.unscaledTime + 3f;
words = 0;
}
private static string Name(Human h)
{
if ((Object)(object)h == (Object)null)
{
return "?";
}
try
{
return h.GetCitizenName();
}
catch
{
return ((Object)h).name;
}
}
private static string Where(Vector3 node)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
if (node == Vector3.zero)
{
return "nowhere";
}
try
{
Dictionary<Vector3, NewNode> nodeMap = PathFinder.Instance.nodeMap;
NewNode val = null;
if (!nodeMap.TryGetValue(node, ref val) || val == null)
{
Vector3 val2 = CityData.Instance.RealPosToNode(node);
if (!nodeMap.TryGetValue(val2, ref val) || val == null)
{
return $"{node} (no node)";
}
}
NewGameLocation gameLocation = val.gameLocation;
string text = "";
try
{
if ((Object)(object)val.room != (Object)null)
{
text = ", room " + val.room.name;
}
}
catch
{
}
string arg = Describe(gameLocation);
string arg2 = text;
Vector3Int nodeCoord = val.nodeCoord;
return $"{arg}{arg2} floor {((Vector3Int)(ref nodeCoord)).z}";
}
catch (Exception ex)
{
return $"{node} ({ex.Message})";
}
}
private static string Describe(NewGameLocation loc)
{
if ((Object)(object)loc == (Object)null)
{
return "no location";
}
string text = "place";
try
{
if ((Object)(object)loc.thisAsAddress != (Object)null)
{
text = "address";
}
else if ((Object)(object)loc.thisAsStreet != (Object)null)
{
text = "street";
}
}
catch
{
}
string text2 = "";
try
{
if ((Object)(object)loc.building != (Object)null)
{
text2 = " in " + ((Object)loc.building).name;
}
}
catch
{
}
bool flag = false;
try
{
flag = loc.evidenceEntry != null;
}
catch
{
}
return text + " '" + ((Object)loc).name + "'" + text2 + (flag ? "" : " (no evidence)");
}
private static void Find(string line)
{
Plugin.L.LogInfo((object)line);
Seen.Add(line);
}
}
}