Decompiled source of DetectiveRoutine v1.0.0
DetectiveRoutine.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
using System; 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.Security; using System.Security.Permissions; using System.Text; using System.Text.Json; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using DetectiveRoutine.Cruncher; using DetectiveRoutine.Dialog; using DetectiveRoutine.Effects; using DetectiveRoutine.Model; using DetectiveRoutine.Survey; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using Il2CppSystem.Reflection; using Microsoft.CodeAnalysis; using SOD.Common; using SOD.Common.Helpers; using SOD.Common.Helpers.DialogObjects; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("DetectiveRoutine")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DetectiveRoutine")] [assembly: AssemblyTitle("DetectiveRoutine")] [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 DetectiveRoutine { [BepInPlugin("ekem.detectiveroutine", "Detective Routine", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BasePlugin { private Harmony? _harmony; public static ManualLogSource Log { get; private set; } public static Settings Cfg { get; private set; } public override void Load() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown Log = ((BasePlugin)this).Log; Cfg = new Settings(((BasePlugin)this).Config); DialogRegistry.Install(); _harmony = new Harmony("ekem.detectiveroutine"); _harmony.PatchAll(); Warrants.Install(); InstallHeartbeat(); ManualLogSource log = Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(9, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Detective Routine"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("1.0.0"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" loaded."); } log.LogInfo(val); } private static void InstallHeartbeat() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) ClassInjector.RegisterTypeInIl2Cpp<Heartbeat>(); ClassInjector.RegisterTypeInIl2Cpp<WarrantsApp>(); ClassInjector.RegisterTypeInIl2Cpp<ReportsApp>(); GameObject val = new GameObject("Detective RoutineHeartbeat"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; val.AddComponent<Heartbeat>(); } } public class Settings { public readonly ConfigEntry<bool> OnTheForce; public readonly ConfigEntry<bool> HireInGame; public readonly ConfigEntry<float> ApplicationHours; public readonly ConfigEntry<float> ShiftStart; public readonly ConfigEntry<float> ShiftEnd; public readonly ConfigEntry<string> ShiftDays; public readonly ConfigEntry<float> LateWindowHours; public readonly ConfigEntry<float> WorkDaysPerYear; public readonly ConfigEntry<float> FallbackShiftPay; public readonly ConfigEntry<float> BonusShifts; public readonly ConfigEntry<int> BonusMinShifts; public readonly ConfigEntry<float> DockShifts; public readonly ConfigEntry<float> ProbationDays; public readonly ConfigEntry<float> ProbationChancePenalty; public readonly ConfigEntry<float> PaperworkHours; public readonly ConfigEntry<float> CoolDays; public readonly ConfigEntry<float> BadgeHours; public readonly ConfigEntry<bool> CaptainWorkweek; public readonly ConfigEntry<float> ReportDays; public readonly ConfigEntry<float> ShiftReportHours; public readonly ConfigEntry<float> ExplanationHours; public readonly ConfigEntry<float> SceneReportHours; public readonly ConfigEntry<float> CaseReportHours; public readonly ConfigEntry<float> FocusedWriteBonus; public readonly ConfigEntry<float> SceneMinutesPerLink; public readonly ConfigEntry<float> SceneReportMaxHours; public readonly ConfigEntry<float> WarrantAppHours; public readonly ConfigEntry<float> WarrantMinutesPerGround; public readonly ConfigEntry<float> WarrantAppMaxHours; public readonly ConfigEntry<float> HoursToTimeOfDeath; public readonly ConfigEntry<float> HoursToWeapon; public readonly ConfigEntry<float> SceneAccessHours; public readonly ConfigEntry<float> ReviewHours; public readonly ConfigEntry<float> NoGroundsChance; public readonly ConfigEntry<int> WarrantsPerDay; public readonly ConfigEntry<float> WarrantHours; public readonly ConfigEntry<bool> CarryablePrintouts; public readonly ConfigEntry<bool> DebugLogging; public readonly ConfigEntry<bool> DebugKeys; public readonly ConfigEntry<KeyCode> BoardKey; public readonly ConfigEntry<KeyCode> WarrantKey; public readonly ConfigEntry<KeyCode> GrantKey; public readonly ConfigEntry<KeyCode> BuildingKey; public readonly ConfigEntry<KeyCode> ReportKey; public Settings(ConfigFile config) { OnTheForce = config.Bind<bool>("Employment", "OnTheForce", true, "Enable the detective career: joining an Enforcer Division, crime scene briefings, access, search warrants. Off means the plain game."); HireInGame = config.Bind<bool>("Employment", "HireInGame", true, "Apply for the job at the City Hall front desk. Off: you join the division whose cruncher you first log into with your own account, no application needed."); ApplicationHours = config.Bind<float>("Employment", "ApplicationHours", 4f, "Game hours until your application is answered."); ShiftStart = config.Bind<float>("Shifts", "ShiftStart", 9f, "Hour your shift starts (0-24, 9.5 is 9:30)."); ShiftEnd = config.Bind<float>("Shifts", "ShiftEnd", 17f, "Hour your shift ends. Earlier than the start means it runs past midnight."); ShiftDays = config.Bind<string>("Shifts", "ShiftDays", "monday,tuesday,wednesday,thursday,friday", "Days you work, comma separated."); LateWindowHours = config.Bind<float>("Shifts", "LateWindowHours", 1f, "How late you can sign in at your division's cruncher before it counts as being late."); WorkDaysPerYear = config.Bind<float>("Pay", "WorkDaysPerYear", 260f, "Your yearly salary divided by this is your pay for one shift."); FallbackShiftPay = config.Bind<float>("Pay", "FallbackShiftPay", 150f, "Pay per shift if your position has no salary."); BonusShifts = config.Bind<float>("Pay", "BonusShifts", 2f, "Weekly bonus for a clean week (no late arrivals, missed shifts or overdue reports), in shifts' pay."); BonusMinShifts = config.Bind<int>("Pay", "BonusMinShifts", 4, "Shifts you must have worked in the week to earn the bonus."); DockShifts = config.Bind<float>("Discipline", "DockShifts", 2f, "Second strike: this many shifts' pay comes out of your next pay."); ProbationDays = config.Bind<float>("Discipline", "ProbationDays", 7f, "Third strike: probation for this many game days. Warrant reviews take twice as long and are granted less often; enforcers tell you less and let you in for less time."); ProbationChancePenalty = config.Bind<float>("Discipline", "ProbationChancePenalty", 0.2f, "How much less likely a warrant is granted while you are on probation."); PaperworkHours = config.Bind<float>("Discipline", "PaperworkHours", 4f, "Third strike also hands you disciplinary paperwork: a report this many game hours long."); CaptainWorkweek = config.Bind<bool>("Pay", "CaptainWorkweek", true, "Your captain works Monday to Friday (some captains only work three days a week, which would leave your warrants and pay waiting)."); BadgeHours = config.Bind<float>("Badge", "BadgeHours", 1f, "After you show your badge, questions to that person can't be refused for this many game hours. Using it to get into their home without a warrant is a strike."); CoolDays = config.Bind<float>("Discipline", "CoolDays", 7f, "Every this many game days without a new strike, one strike is forgiven. Four strikes and you're dismissed."); ReportDays = config.Bind<float>("Reports", "ReportDays", 3f, "Game days you have to write a report before it is overdue."); ShiftReportHours = config.Bind<float>("Reports", "ShiftReportHours", 1f, "Game hours it takes to write a shift report. Time runs fast while you write."); ExplanationHours = config.Bind<float>("Reports", "ExplanationHours", 0.5f, "Game hours it takes to explain a late arrival or a missed shift."); SceneReportHours = config.Bind<float>("Reports", "SceneReportHours", 1.5f, "Game hours it takes to write up a crime scene."); CaseReportHours = config.Bind<float>("Reports", "CaseReportHours", 3f, "Game hours it takes to write the report after you hand a case in."); FocusedWriteBonus = config.Bind<float>("Reports", "FocusedWriteBonus", 1.5f, "How much faster you write while Focused (coffee and the like). 1 turns it off."); SceneMinutesPerLink = config.Bind<float>("Reports", "SceneMinutesPerLink", 10f, "Extra game minutes to write up a crime scene for every piece of evidence on your board linked to the scene or the victim."); SceneReportMaxHours = config.Bind<float>("Reports", "SceneReportMaxHours", 4f, "A crime scene write-up never takes longer than this, in game hours."); WarrantAppHours = config.Bind<float>("Reports", "WarrantAppHours", 0.25f, "Game hours to write a search warrant application with no grounds."); WarrantMinutesPerGround = config.Bind<float>("Reports", "WarrantMinutesPerGround", 10f, "Extra game minutes to write a warrant application for every ground you list."); WarrantAppMaxHours = config.Bind<float>("Reports", "WarrantAppMaxHours", 2f, "A warrant application never takes longer than this, in game hours."); HoursToTimeOfDeath = config.Bind<float>("Briefing", "HoursToTimeOfDeath", 1f, "Game hours after the enforcers arrive before they can tell you the time of death."); HoursToWeapon = config.Bind<float>("Briefing", "HoursToWeapon", 2f, "Game hours after the enforcers arrive before they can tell you what the victim was killed with."); SceneAccessHours = config.Bind<float>("Access", "SceneAccessHours", 2f, "How long the pass lasts when an enforcer lets you into a crime scene, in game hours."); ReviewHours = config.Bind<float>("Warrants", "ReviewHours", 6f, "Game hours to review a search warrant request with no grounds. Every piece of evidence linked to the place on your case board makes it faster."); NoGroundsChance = config.Bind<float>("Warrants", "NoGroundsChance", 0.3f, "Chance a request with no grounds is granted. With grounds it starts at 0.7 and grows."); WarrantsPerDay = config.Bind<int>("Warrants", "WarrantsPerDay", 3, "How many search warrant requests you can file in 24 game hours."); WarrantHours = config.Bind<float>("Warrants", "WarrantHours", 24f, "How long a granted search warrant lasts, in game hours."); CarryablePrintouts = config.Bind<bool>("Printouts", "CarryablePrintouts", true, "Printed vmails and database records can be picked up and carried, not just pinned. Print your warrant to leave a copy at the door."); DebugLogging = config.Bind<bool>("Debug", "DebugLogging", false, "Write what the mod does to LogOutput.log."); DebugKeys = config.Bind<bool>("Debug", "DebugKeys", false, "Enable the debug keys below."); BoardKey = config.Bind<KeyCode>("Debug", "BoardKey", (KeyCode)286, "Write the places on your case board and the grounds for a warrant on each to the log."); WarrantKey = config.Bind<KeyCode>("Debug", "WarrantKey", (KeyCode)287, "File a search warrant request for the place you pinned last. Stand-in until the cruncher app exists."); GrantKey = config.Bind<KeyCode>("Debug", "GrantKey", (KeyCode)285, "Grant a search warrant for the place you pinned last right away, letter included. For testing."); BuildingKey = config.Bind<KeyCode>("Debug", "BuildingKey", (KeyCode)284, "Write every address in the building you are in to the log, with its company and staff."); ReportKey = config.Bind<KeyCode>("Debug", "ReportKey", (KeyCode)283, "Add a test report to your queue, so you don't have to wait for the end of a shift."); } } public static class PluginInfo { public const string Guid = "ekem.detectiveroutine"; public const string Name = "Detective Routine"; public const string Version = "1.0.0"; } } namespace DetectiveRoutine.Survey { public static class BuildingSurvey { public static void Run() { //IL_04dd: Unknown result type (might be due to invalid IL or missing references) //IL_04e4: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Expected O, but got Unknown bool flag = default(bool); try { Player instance = Player.Instance; NewBuilding val = ((instance != null) ? ((Actor)instance).currentBuilding : null); CityData instance2 = CityData.Instance; Dictionary<int, NewAddress> val2 = ((instance2 != null) ? instance2.addressDictionary : null); if ((Object)(object)val == (Object)null || val2 == null) { Plugin.Log.LogInfo((object)"[building] you are not inside a building"); return; } ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(14, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[building] "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)val).name); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ("); BepInExInfoLogInterpolatedStringHandler obj = val3; BuildingPreset preset = val.preset; ((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((preset != null) ? ((Object)preset).name : null); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(")"); } log.LogInfo(val3); Enumerator<int, NewAddress> enumerator = val2.GetEnumerator(); while (enumerator.MoveNext()) { NewAddress value = enumerator.Current.Value; if ((Object)(object)((value != null) ? ((NewGameLocation)value).building : null) == (Object)null || ((Il2CppObjectBase)((NewGameLocation)value).building).Pointer != ((Il2CppObjectBase)val).Pointer) { continue; } Company company = value.company; ManualLogSource log2 = Plugin.Log; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(23, 3); defaultInterpolatedStringHandler.AppendLiteral("[building] "); defaultInterpolatedStringHandler.AppendFormatted(((Object)value).name); defaultInterpolatedStringHandler.AppendLiteral(" ["); AddressPreset addressPreset = value.addressPreset; defaultInterpolatedStringHandler.AppendFormatted((addressPreset != null) ? ((Object)addressPreset).name : null); defaultInterpolatedStringHandler.AppendLiteral("] floor "); NewFloor floor = ((NewGameLocation)value).floor; defaultInterpolatedStringHandler.AppendFormatted((floor != null) ? new int?(floor.floor) : ((int?)null)); string text = defaultInterpolatedStringHandler.ToStringAndClear(); object obj2; if (company != null) { string name = company.name; Human director = company.director; obj2 = ", company " + name + ", director " + (((director != null) ? director.GetCitizenName() : null) ?? "-"); } else { obj2 = ""; } IntPtr pointer = ((Il2CppObjectBase)value).Pointer; NewGameLocation currentGameLocation = ((Actor)instance).currentGameLocation; IntPtr? obj3; if (currentGameLocation == null) { obj3 = null; } else { NewAddress thisAsAddress = currentGameLocation.thisAsAddress; obj3 = ((thisAsAddress != null) ? new IntPtr?(((Il2CppObjectBase)thisAsAddress).Pointer) : ((IntPtr?)null)); } log2.LogInfo((object)(text + (string?)obj2 + ((pointer == obj3) ? " <- you are here" : ""))); List<Occupation> val4 = ((company != null) ? company.companyRoster : null); if (val4 == null) { continue; } HashSet<IntPtr> hashSet = new HashSet<IntPtr>(); Enumerator<Occupation> enumerator2; if (company.currentStaff != null) { enumerator2 = company.currentStaff.GetEnumerator(); while (enumerator2.MoveNext()) { Occupation current = enumerator2.Current; if (current != null) { hashSet.Add(((Il2CppObjectBase)current).Pointer); } } } enumerator2 = val4.GetEnumerator(); while (enumerator2.MoveNext()) { Occupation current2 = enumerator2.Current; Human val5 = ((current2 != null) ? current2.employee : null); if (current2 == null) { continue; } IntPtr? obj4; if (val5 == null) { obj4 = null; } else { NewGameLocation currentGameLocation2 = ((Actor)val5).currentGameLocation; if (currentGameLocation2 == null) { obj4 = null; } else { NewAddress thisAsAddress2 = currentGameLocation2.thisAsAddress; obj4 = ((thisAsAddress2 != null) ? new IntPtr?(((Il2CppObjectBase)thisAsAddress2).Pointer) : ((IntPtr?)null)); } } bool flag2 = obj4 == ((Il2CppObjectBase)value).Pointer; ManualLogSource log3 = Plugin.Log; val3 = new BepInExInfoLogInterpolatedStringHandler(22, 11, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[building] "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(current2.name); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(current2.startTimeDecimalHour, "0.#"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("-"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<float>(current2.endTimeDecialHour, "0.#"); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ("); BepInExInfoLogInterpolatedStringHandler obj5 = val3; OccupationPreset preset2 = current2.preset; ((BepInExLogInterpolatedStringHandler)obj5).AppendFormatted<string>((preset2 != null) ? ((Object)preset2).name : null); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((SoCustomComparison)(object)current2.preset != (SoCustomComparison)null && current2.preset.receptionist) ? ", receptionist" : ""); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(current2.isOwner ? ", owner" : ""); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(current2.teamLeader ? ", team leader" : ""); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("): "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((val5 != null) ? val5.GetCitizenName() : null) ?? "vacant"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(hashSet.Contains(((Il2CppObjectBase)current2).Pointer) ? ", on shift" : ""); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(flag2 ? ", here now" : ""); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)(object)val5 != (Object)null && ((Actor)val5).isEnforcer) ? ", enforcer" : ""); } log3.LogInfo(val3); } } } catch (Exception ex) { ManualLogSource log4 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val6 = new BepInExErrorLogInterpolatedStringHandler(26, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[building] survey failed: "); ((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<Exception>(ex); } log4.LogError(val6); } } } [HarmonyPatch(typeof(MainMenuController), "Start")] public static class CruncherSurvey { private static bool _done; private static readonly string[] DumpApps = new string[0]; [HarmonyPostfix] public static void Postfix() { //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_03a0: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown if (_done || !Plugin.Cfg.DebugLogging.Value) { return; } _done = true; bool flag = default(bool); try { Il2CppArrayBase<CruncherAppPreset> val = Resources.FindObjectsOfTypeAll<CruncherAppPreset>(); ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[cruncher] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.Length); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" app presets"); } log.LogInfo(val2); foreach (CruncherAppPreset app in val) { List<GameObject> content = app.appContent; string text = ((content == null) ? "-" : string.Join(", ", from i in Enumerable.Range(0, content.Count) select (!((Object)(object)content[i] == (Object)null)) ? (((Object)content[i]).name + "<" + Components(content[i]) + ">") : "null")); string text2 = ((app.onlyInAddresses == null) ? "" : string.Join(",", Enumerable.Range(0, app.onlyInAddresses.Count).Select(delegate(int i) { AddressPreset obj2 = app.onlyInAddresses[i]; return ((obj2 != null) ? ((Object)obj2).name : null) ?? "?"; }))); ManualLogSource log2 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(110, 8, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[cruncher] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)app).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": alwaysInstalled "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.alwaysInstalled); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", companyOnly "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.companyOnly); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("onlyIfOwner "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.onlyIfOwner); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", residential "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<bool>(app.onlyIfResidential); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("conditions "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(app.installationConditions?.Count ?? 0); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", addresses ["); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text2); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("], content "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(text); } log2.LogInfo(val2); } foreach (InteractablePreset item in Resources.FindObjectsOfTypeAll<InteractablePreset>()) { List<CruncherAppPreset> extra = item.additionalApps; if (extra != null && extra.Count != 0) { Plugin.Log.LogInfo((object)("[cruncher] computer " + ((Object)item).name + ": " + string.Join(", ", Enumerable.Range(0, extra.Count).Select(delegate(int i) { CruncherAppPreset obj2 = extra[i]; return ((obj2 != null) ? ((Object)obj2).name : null) ?? "null"; })))); } } string[] dumpApps = DumpApps; foreach (string name in dumpApps) { CruncherAppPreset val3 = ((IEnumerable<CruncherAppPreset>)val).FirstOrDefault((Func<CruncherAppPreset, bool>)((CruncherAppPreset a) => ((Object)a).name == name)); if (((val3 != null) ? val3.appContent : null) != null) { for (int num2 = 0; num2 < val3.appContent.Count; num2++) { GameObject obj = val3.appContent[num2]; Dump((obj != null) ? obj.transform : null, 0); } } } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(26, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[cruncher] survey failed: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<Exception>(ex); } log3.LogError(val4); } } private static string Components(GameObject go) { return string.Join("+", ((IEnumerable<Component>)go.GetComponents<Component>()).Select((Component c) => (!((Object)(object)c == (Object)null)) ? ((MemberInfo)((Object)c).GetIl2CppType()).Name : "null")); } private static void Dump(Transform? t, int depth) { //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)t == (Object)null) && depth <= 8) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(' ', depth * 2).Append(((Object)t).name).Append(" <") .Append(Components(((Component)t).gameObject)) .Append('>'); TextMeshProUGUI component = ((Component)t).GetComponent<TextMeshProUGUI>(); if ((Object)(object)component != (Object)null) { stringBuilder.Append(" \"").Append(((TMP_Text)component).text?.Replace("\n", " ")).Append('"'); } if (!((Component)t).gameObject.activeSelf) { stringBuilder.Append(" (inactive)"); } RectTransform val = ((Il2CppObjectBase)t).TryCast<RectTransform>(); if ((Object)(object)val != (Object)null) { StringBuilder stringBuilder2 = stringBuilder; StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(12, 4, stringBuilder2); handler.AppendLiteral(" rect "); Rect rect = val.rect; handler.AppendFormatted(((Rect)(ref rect)).width, "F3"); handler.AppendLiteral("x"); rect = val.rect; handler.AppendFormatted(((Rect)(ref rect)).height, "F3"); handler.AppendLiteral(" at "); handler.AppendFormatted(val.anchoredPosition.x, "F3"); handler.AppendLiteral(","); handler.AppendFormatted(val.anchoredPosition.y, "F3"); stringBuilder2.Append(ref handler); } ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[cruncher] tree "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<StringBuilder>(stringBuilder); } log.LogInfo(val2); for (int i = 0; i < t.childCount; i++) { Dump(t.GetChild(i), depth + 1); } } } } public static class FurnitureSurvey { public static void Run() { //IL_04b5: Unknown result type (might be due to invalid IL or missing references) //IL_04bc: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Expected O, but got Unknown //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: Expected O, but got Unknown bool flag = default(bool); try { Player instance = Player.Instance; object obj; if (instance == null) { obj = null; } else { NewGameLocation currentGameLocation = ((Actor)instance).currentGameLocation; obj = ((currentGameLocation != null) ? currentGameLocation.thisAsAddress : null); } NewAddress val = (NewAddress)obj; if ((Object)(object)val == (Object)null) { Plugin.Log.LogInfo((object)"[furniture] not at an address"); return; } ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(15, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)val).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ["); BepInExInfoLogInterpolatedStringHandler obj2 = val2; AddressPreset addressPreset = val.addressPreset; ((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((addressPreset != null) ? ((Object)addressPreset).name : null); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("]"); } log.LogInfo(val2); Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> furnitureBelongsTo = ((NewGameLocation)val).furnitureBelongsTo; if (furnitureBelongsTo != null) { Enumerator<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> enumerator = furnitureBelongsTo.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> current = enumerator.Current; Enumerator<FurnitureLocation, List<Human>> enumerator2 = current.Value.GetEnumerator(); while (enumerator2.MoveNext()) { KeyValuePair<FurnitureLocation, List<Human>> current2 = enumerator2.Current; List<string> list = new List<string>(); if (current2.Value != null) { Enumerator<Human> enumerator3 = current2.Value.GetEnumerator(); while (enumerator3.MoveNext()) { Human current3 = enumerator3.Current; list.Add(((current3 != null) ? current3.GetCitizenName() : null) ?? "?"); } } ManualLogSource log2 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(26, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture] owned "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<OwnershipClass>(current.Key); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Describe(current2.Key)); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((list.Count == 0) ? "nobody" : string.Join(", ", list)); } log2.LogInfo(val2); } } } if (((NewGameLocation)val).rooms != null) { Enumerator<NewRoom> enumerator4 = ((NewGameLocation)val).rooms.GetEnumerator(); while (enumerator4.MoveNext()) { NewRoom current4 = enumerator4.Current; if (((current4 != null) ? current4.individualFurniture : null) == null) { continue; } ManualLogSource log3 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(29, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture] room "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(current4.name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(current4.individualFurniture.Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" pieces)"); } log3.LogInfo(val2); Enumerator<FurnitureLocation> enumerator5 = current4.individualFurniture.GetEnumerator(); while (enumerator5.MoveNext()) { FurnitureLocation current5 = enumerator5.Current; if (!((SoCustomComparison)(object)((current5 != null) ? current5.furniture : null) == (SoCustomComparison)null)) { List<string> list2 = new List<string>(); Collect(current5.integratedInteractables, list2); Collect(current5.spawnedInteractables, list2); ManualLogSource log4 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(16, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(Describe(current5)); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>((list2.Count == 0) ? "" : (": " + string.Join(", ", list2))); } log4.LogInfo(val2); } } } } if (val.company != null) { ManualLogSource log5 = Plugin.Log; val2 = new BepInExInfoLogInterpolatedStringHandler(38, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[furniture] work positions: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Desks.All(val).Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", free: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Desks.Free(val).Count); } log5.LogInfo(val2); } Company company = val.company; List<Occupation> val3 = ((company != null) ? company.companyRoster : null); if (val3 == null) { return; } Enumerator<Occupation> enumerator6 = val3.GetEnumerator(); while (enumerator6.MoveNext()) { Occupation current6 = enumerator6.Current; Human val4 = ((current6 != null) ? current6.employee : null); if (!((Object)(object)val4 == (Object)null)) { Interactable workPosition = val4.workPosition; ManualLogSource log6 = Plugin.Log; string obj3 = $"[furniture] {val4.GetCitizenName()} ({current6.name}) works at "; object obj4; if (workPosition != null) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(6, 3); InteractablePreset preset = workPosition.preset; defaultInterpolatedStringHandler.AppendFormatted((preset != null) ? ((SoCustomComparison)preset).presetName : null); defaultInterpolatedStringHandler.AppendLiteral(" #"); defaultInterpolatedStringHandler.AppendFormatted(workPosition.id); defaultInterpolatedStringHandler.AppendLiteral(" on "); defaultInterpolatedStringHandler.AppendFormatted(Describe(workPosition.furnitureParent)); obj4 = defaultInterpolatedStringHandler.ToStringAndClear(); } else { obj4 = "nothing"; } log6.LogInfo((object)(obj3 + (string?)obj4)); } } } catch (Exception ex) { ManualLogSource log7 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(27, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[furniture] survey failed: "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<Exception>(ex); } log7.LogError(val5); } } private static string Describe(FurnitureLocation? f) { if ((SoCustomComparison)(object)((f != null) ? f.furniture : null) == (SoCustomComparison)null) { return "none"; } return $"{((Object)f.furniture).name} #{f.id}{(f.furniture.isWorkPosition ? " (work position)" : "")}"; } private static void Collect(List<Interactable>? list, List<string> into) { if (list == null) { return; } Enumerator<Interactable> enumerator = list.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current = enumerator.Current; if (!((SoCustomComparison)(object)((current != null) ? current.preset : null) == (SoCustomComparison)null)) { into.Add($"{((SoCustomComparison)current.preset).presetName} #{current.id}" + (((Object)(object)current.belongsTo != (Object)null) ? (" [" + current.belongsTo.GetCitizenName() + "]") : "")); } } } } } namespace DetectiveRoutine.Model { public static class Captain { private static IntPtr _adjusted; public static Occupation? Job() { Company? division = Employment.Division; List<Occupation> val = ((division != null) ? division.companyRoster : null); if (val == null) { return null; } Enumerator<Occupation> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { Occupation current = enumerator.Current; if (current != null && current.isOwner && (Object)(object)current.employee != (Object)null) { return current; } } return null; } public static bool OnDuty(float time) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Occupation val = Job(); if (val == null) { return true; } SessionData instance = SessionData.Instance; float startTimeDecimalHour = val.startTimeDecimalHour; float endTimeDecialHour = val.endTimeDecialHour; float num = default(float); WeekDay day = default(WeekDay); int num2 = default(int); Month val2 = default(Month); int num3 = default(int); instance.ParseTimeData(time, ref num, ref day, ref num2, ref val2, ref num3); if (endTimeDecialHour > startTimeDecimalHour) { if (num >= startTimeDecimalHour && num < endTimeDecialHour) { return Works(val, day); } return false; } if (num >= startTimeDecimalHour) { return Works(val, day); } if (num < endTimeDecialHour) { float num4 = default(float); WeekDay day2 = default(WeekDay); instance.ParseTimeData(time - 24f, ref num4, ref day2, ref num3, ref val2, ref num2); return Works(val, day2); } return false; } private static bool Works(Occupation job, WeekDay day) { //IL_001e: 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) List<WeekDay> workDaysList = job.workDaysList; if (workDaysList == null || workDaysList.Count == 0) { return true; } Enumerator<WeekDay> enumerator = workDaysList.GetEnumerator(); while (enumerator.MoveNext()) { if (enumerator.Current == day) { return true; } } return false; } public static void EnsureWorkweek() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown if (!Plugin.Cfg.CaptainWorkweek.Value) { return; } Occupation val = Job(); if (val == null || ((Il2CppObjectBase)val).Pointer == _adjusted) { return; } WeekDay[] array = new WeekDay[5]; RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/); WeekDay[] array2 = (WeekDay[])(object)array; List<WeekDay> workDaysList = val.workDaysList; bool flag = workDaysList != null && workDaysList.Count == array2.Length; if (flag) { WeekDay[] array3 = array2; foreach (WeekDay val2 in array3) { if (!workDaysList.Contains(val2)) { flag = false; } } } if (!flag) { List<WeekDay> val3 = new List<WeekDay>(); WeekDay[] array3 = array2; foreach (WeekDay val4 in array3) { val3.Add(val4); } val.workDaysList = val3; ManualLogSource log = Plugin.Log; bool flag2 = default(bool); BepInExInfoLogInterpolatedStringHandler val5 = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[pay] "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(Name()); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" now works Monday to Friday"); } log.LogInfo(val5); } _adjusted = ((Il2CppObjectBase)val).Pointer; } public static void Memo(string subject, string text) { Company division = Employment.Division; Human val = ((division != null) ? division.director : null); Human val2 = val ?? WarrantMail.Sender(); if (!((Object)(object)val2 == (Object)null)) { WarrantMail.Letter(val2, text, subject.ToUpperInvariant(), (!((Object)(object)val == (Object)null)) ? ("Captain " + val.GetCitizenName() + ", " + division.name) : (((division != null) ? division.name : null) ?? "Enforcer Division"), "memo '" + subject + "'"); } } public static float RankAndFileSalary() { Company? division = Employment.Division; List<Occupation> val = ((division != null) ? division.companyRoster : null); if (val == null) { return 0f; } Enumerator<Occupation> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { Occupation current = enumerator.Current; if (current != null && !current.isOwner && !current.teamLeader && current.salary > 0f) { return current.salary; } } return 0f; } public static string Name() { Occupation? obj = Job(); object obj2; if (obj == null) { obj2 = null; } else { Human employee = obj.employee; obj2 = ((employee != null) ? employee.GetCitizenName() : null); } if (obj2 == null) { obj2 = "the captain"; } return (string)obj2; } } public static class CaseBoard { public sealed record Place(Evidence Evidence, NewAddress Address); public sealed record Ground(string Name, bool Custom, string? Label, string Id = ""); private const string DefaultLinkName = "Created Link"; public static HashSet<string> PinnedIds() { HashSet<string> hashSet = new HashSet<string>(); CasePanelController instance = CasePanelController.Instance; object obj; if (instance == null) { obj = null; } else { Case activeCase = instance.activeCase; obj = ((activeCase != null) ? activeCase.caseElements : null); } List<CaseElement> val = (List<CaseElement>)obj; if (val == null) { return hashSet; } Enumerator<CaseElement> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { CaseElement current = enumerator.Current; if (!string.IsNullOrEmpty((current != null) ? current.id : null)) { hashSet.Add(current.id); } } return hashSet; } public static List<Place> Places() { List<Place> list = new List<Place>(); CasePanelController instance = CasePanelController.Instance; object obj; if (instance == null) { obj = null; } else { Case activeCase = instance.activeCase; obj = ((activeCase != null) ? activeCase.caseElements : null); } List<CaseElement> val = (List<CaseElement>)obj; if (val == null) { return list; } Enumerator<CaseElement> enumerator = val.GetEnumerator(); Evidence val2 = default(Evidence); while (enumerator.MoveNext()) { CaseElement current = enumerator.Current; if (current == null || string.IsNullOrEmpty(current.id) || !Toolbox.Instance.TryGetEvidence(current.id, ref val2) || val2 == null) { continue; } EvidenceLocation obj2 = ((Il2CppObjectBase)val2).TryCast<EvidenceLocation>(); NewGameLocation val3 = ((obj2 != null) ? obj2.locationController : null); if (!((Object)(object)val3 == (Object)null) && !val3.isOutside) { NewAddress thisAsAddress = val3.thisAsAddress; if (!((Object)(object)thisAsAddress == (Object)null)) { list.Add(new Place(val2, thisAsAddress)); } } } return list; } public static List<Ground> GroundsFor(Evidence place, HashSet<string> pinned) { Dictionary<string, Ground> dictionary = new Dictionary<string, Ground>(); List<FactLink> allFacts = place.allFacts; if (allFacts == null) { return new List<Ground>(); } Enumerator<FactLink> enumerator = allFacts.GetEnumerator(); while (enumerator.MoveNext()) { FactLink current = enumerator.Current; Fact val = ((current != null) ? current.fact : null); List<Evidence> val2 = ((current != null) ? current.destinationEvidence : null); if (val == null || val2 == null) { continue; } Enumerator<Evidence> enumerator2 = val2.GetEnumerator(); while (enumerator2.MoveNext()) { Evidence current2 = enumerator2.Current; if (current2 != null && !(current2.evID == place.evID) && pinned.Contains(current2.evID)) { bool isCustom = val.isCustom; string label = ((isCustom && !string.IsNullOrWhiteSpace(val.customName) && val.customName != "Created Link") ? val.customName : null); if (!dictionary.TryGetValue(current2.evID, out var value) || (!value.Custom && isCustom)) { dictionary[current2.evID] = new Ground(NameOf(current2), isCustom, label, current2.evID); } } } } return new List<Ground>(dictionary.Values); } public static int SceneLinks(NewAddress scene) { HashSet<string> pinned = PinnedIds(); HashSet<string> hashSet = new HashSet<string>(); if (((NewGameLocation)scene).evidenceEntry != null) { foreach (Ground item in GroundsFor((Evidence)(object)((NewGameLocation)scene).evidenceEntry, pinned)) { hashSet.Add(item.Id); } } Murder? obj = CrimeScenes.MurderAt((NewGameLocation)(object)scene); object obj2; if (obj == null) { obj2 = null; } else { Human victim = obj.victim; obj2 = ((victim != null) ? ((Actor)victim).evidenceEntry : null); } EvidenceWitness val = (EvidenceWitness)obj2; if (val != null) { foreach (Ground item2 in GroundsFor((Evidence)(object)val, pinned)) { hashSet.Add(item2.Id); } } if (((NewGameLocation)scene).evidenceEntry != null) { hashSet.Remove(((Evidence)((NewGameLocation)scene).evidenceEntry).evID); } if (val != null) { hashSet.Remove(((Evidence)val).evID); } return hashSet.Count; } public static string NameOf(Evidence evidence) { try { string nameForDataKey = evidence.GetNameForDataKey((DataKey)0); if (!string.IsNullOrWhiteSpace(nameForDataKey)) { return nameForDataKey; } } catch { } return evidence.evID; } } public static class CrimeScenes { public sealed record Scene(NewGameLocation Location, EnforcerCall Call, Murder? Murder); public static Scene? GuardedBy(Human enforcer) { GameplayController instance = GameplayController.Instance; Dictionary<NewGameLocation, EnforcerCall> val = ((instance != null) ? instance.enforcerCalls : null); if (val == null) { return null; } int humanID = enforcer.humanID; Enumerator<NewGameLocation, EnforcerCall> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair<NewGameLocation, EnforcerCall> current = enumerator.Current; EnforcerCall value = current.Value; if (value != null && value.isCrimeScene && (value.guard == humanID || (value.response != null && value.response.Contains(humanID)))) { return new Scene(current.Key, value, MurderAt(current.Key)); } } return null; } public static Murder? MurderAt(NewGameLocation location) { MurderController instance = MurderController.Instance; if ((Object)(object)instance == (Object)null) { return null; } List<Murder>[] array = new List<Murder>[2] { instance.activeMurders, instance.inactiveMurders }; foreach (List<Murder> val in array) { if (val == null) { continue; } for (int num = val.Count - 1; num >= 0; num--) { Murder val2 = val[num]; if ((Object)(object)((val2 != null) ? val2.location : null) != (Object)null && ((Il2CppObjectBase)val2.location).Pointer == ((Il2CppObjectBase)location).Pointer) { return val2; } } } return null; } } public static class Desks { private const string PlacardPreset = "NamePlacard"; private static bool _placardFailed; private const string PhotoPreset = "EmployeePhoto"; private const string PhotoBoard = "EmployeePhotoBoard"; private static bool _photoFailed; private static bool _noPhotoSpotReported; private static bool _noTemplateReported; public static int PlacardDesk { get; set; } = -1; public static int PlacardId { get; set; } = -1; public static List<FurnitureLocation> All(NewAddress office) { List<FurnitureLocation> list = new List<FurnitureLocation>(); foreach (FurnitureLocation item in Furniture(office)) { if (item.furniture.isWorkPosition) { list.Add(item); } } return list; } public static List<FurnitureLocation> Free(NewAddress office) { HashSet<IntPtr> hashSet = new HashSet<IntPtr>(); Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> furnitureBelongsTo = ((NewGameLocation)office).furnitureBelongsTo; if (furnitureBelongsTo != null) { Enumerator<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> enumerator = furnitureBelongsTo.GetEnumerator(); while (enumerator.MoveNext()) { Enumerator<FurnitureLocation, List<Human>> enumerator2 = enumerator.Current.Value.GetEnumerator(); while (enumerator2.MoveNext()) { KeyValuePair<FurnitureLocation, List<Human>> current = enumerator2.Current; if (current.Key != null && current.Value != null && current.Value.Count > 0) { hashSet.Add(((Il2CppObjectBase)current.Key).Pointer); } } } } HashSet<string> hashSet2 = new HashSet<string>(); Company company = office.company; List<Occupation> val = ((company != null) ? company.companyRoster : null); if (val != null) { Enumerator<Occupation> enumerator3 = val.GetEnumerator(); while (enumerator3.MoveNext()) { Occupation current2 = enumerator3.Current; Human val2 = ((current2 != null) ? current2.employee : null); object obj; if (val2 == null) { obj = null; } else { Interactable workPosition = val2.workPosition; obj = ((workPosition != null) ? workPosition.furnitureParent : null); } FurnitureLocation val3 = (FurnitureLocation)obj; if (!((Object)(object)val2 == (Object)null) && val3 != null && !((Actor)val2).isPlayer) { hashSet.Add(((Il2CppObjectBase)val3).Pointer); if ((SoCustomComparison)(object)val3.furniture != (SoCustomComparison)null) { hashSet2.Add(((Object)val3.furniture).name); } } } } List<FurnitureLocation> list = new List<FurnitureLocation>(); foreach (FurnitureLocation item in All(office)) { if (!hashSet.Contains(((Il2CppObjectBase)item).Pointer) && (hashSet2.Count == 0 || hashSet2.Contains(((Object)item.furniture).name))) { list.Add(item); } } return list; } public static FurnitureLocation? Find(NewAddress office, int id) { foreach (FurnitureLocation item in Furniture(office)) { if (item.id == id) { return item; } } return null; } public static void Claim(NewAddress office, FurnitureLocation desk) { Player instance = Player.Instance; if (!((Object)(object)instance == (Object)null)) { Own(office, desk, (OwnershipClass)2, (Human)(object)instance, own: true); FurnitureLocation val = Drawers(office, desk); if (val != null) { Own(office, val, (OwnershipClass)4, (Human)(object)instance, own: true); } Interactable val2 = WorkSpot(desk); if (val2 != null && (((Human)instance).workPosition == null || ((Il2CppObjectBase)((Human)instance).workPosition).Pointer != ((Il2CppObjectBase)val2).Pointer)) { ((Human)instance).SetWorkFurniture(val2); } EnsurePlacard(office, desk, (Human)(object)instance); } } private static void EnsurePlacard(NewAddress office, FurnitureLocation desk, Human player) { //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Expected O, but got Unknown List<Interactable> spawnedInteractables = desk.spawnedInteractables; bool flag = default(bool); if (spawnedInteractables != null) { List<Interactable> list = new List<Interactable>(); Enumerator<Interactable> enumerator = spawnedInteractables.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current = enumerator.Current; if ((SoCustomComparison)(object)((current != null) ? current.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)current.preset).presetName == "NamePlacard") { list.Add(current); } } for (int i = 1; i < list.Count; i++) { list[i].SafeDelete(false); } if (list.Count > 1) { ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] removed "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(list.Count - 1); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" extra name placards from your desk"); } log.LogInfo(val); } if (list.Count > 0) { PlacardDesk = desk.id; PlacardId = list[0].id; return; } } if (PlacardDesk == desk.id) { return; } Interactable val2 = null; foreach (FurnitureLocation item in Furniture(office)) { if (((Il2CppObjectBase)item).Pointer == ((Il2CppObjectBase)desk).Pointer || item.spawnedInteractables == null) { continue; } Enumerator<Interactable> enumerator = item.spawnedInteractables.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current3 = enumerator.Current; if ((SoCustomComparison)(object)((current3 != null) ? current3.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)current3.preset).presetName == "NamePlacard" && (val2 == null || ((Object)item.furniture).name == ((Object)desk.furniture).name)) { val2 = current3; } } } if (val2 == null) { if (!_noTemplateReported) { ManualLogSource log2 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(62, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] no name placard in "); BepInExInfoLogInterpolatedStringHandler obj = val; Company company = office.company; ((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((company != null) ? company.name : null); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" to copy, your desk stays without one"); } log2.LogInfo(val); } _noTemplateReported = true; } else { if (_placardFailed) { return; } try { Interactable val3 = InteractableCreator.Instance.CreateFurnitureSpawnedInteractable(val2.preset, desk, val2.subObject, player, player, (Human)null, new List<Passed>(), (LightingPreset)null, (Object)null, ""); Plugin.Log.LogInfo((object)((val3 == null) ? "[job] the game refused to place your name placard" : $"[job] name placard placed on your desk (#{val3.id})")); if (val3 == null) { _placardFailed = true; return; } PlacardDesk = desk.id; PlacardId = val3.id; } catch (Exception ex) { _placardFailed = true; ManualLogSource log3 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(69, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] could not place your name placard, giving up for this session: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message); } log3.LogError(val4); } } } public static void EnsurePhoto(NewAddress office, Human player) { //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Expected O, but got Unknown if (_photoFailed) { return; } bool flag = default(bool); foreach (FurnitureLocation item in Furniture(office)) { if (((Object)item.furniture).name != "EmployeePhotoBoard") { continue; } Interactable val = null; HashSet<IntPtr> hashSet = new HashSet<IntPtr>(); if (item.spawnedInteractables != null) { Enumerator<Interactable> enumerator2 = item.spawnedInteractables.GetEnumerator(); while (enumerator2.MoveNext()) { Interactable current2 = enumerator2.Current; if ((SoCustomComparison)(object)((current2 != null) ? current2.preset : null) == (SoCustomComparison)null) { continue; } if (current2.subObject != null) { hashSet.Add(((Il2CppObjectBase)current2.subObject).Pointer); } if (!(((SoCustomComparison)current2.preset).presetName != "EmployeePhoto")) { if ((Object)(object)current2.belongsTo != (Object)null && ((Il2CppObjectBase)current2.belongsTo).Pointer == ((Il2CppObjectBase)player).Pointer) { return; } if (val == null) { val = current2; } } } } if (((val != null) ? val.subObject : null) == null) { continue; } SubObject val2 = null; List<SubObject> subObjects = item.furniture.subObjects; if (subObjects != null) { Enumerator<SubObject> enumerator3 = subObjects.GetEnumerator(); while (enumerator3.MoveNext()) { SubObject current3 = enumerator3.Current; if (current3 != null && !hashSet.Contains(((Il2CppObjectBase)current3).Pointer) && (SoCustomComparison)(object)current3.preset != (SoCustomComparison)null && (SoCustomComparison)(object)val.subObject.preset != (SoCustomComparison)null && ((Il2CppObjectBase)current3.preset).Pointer == ((Il2CppObjectBase)val.subObject.preset).Pointer) { val2 = current3; break; } } } if (val2 == null) { if (!_noPhotoSpotReported) { ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(50, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] no free spot on the employee photo board in "); Company company = office.company; ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((company != null) ? company.name : null); } log.LogInfo(val3); } _noPhotoSpotReported = true; break; } try { Interactable val4 = InteractableCreator.Instance.CreateFurnitureSpawnedInteractable(val.preset, item, val2, player, player, (Human)null, new List<Passed>(), (LightingPreset)null, (Object)null, ""); Plugin.Log.LogInfo((object)((val4 == null) ? "[job] the game refused to pin your photo" : $"[job] your photo pinned to the employee board (#{val4.id})")); if (val4 == null) { _photoFailed = true; } break; } catch (Exception ex) { _photoFailed = true; ManualLogSource log2 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(60, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[job] could not pin your photo, giving up for this session: "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ex.Message); } log2.LogError(val5); break; } } } public static void RemovePhoto(NewAddress office, Human player) { foreach (FurnitureLocation item in Furniture(office)) { if (((Object)item.furniture).name != "EmployeePhotoBoard" || item.spawnedInteractables == null) { continue; } for (int num = item.spawnedInteractables.Count - 1; num >= 0; num--) { Interactable val = item.spawnedInteractables[num]; if ((SoCustomComparison)(object)((val != null) ? val.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)val.preset).presetName == "EmployeePhoto" && (Object)(object)val.belongsTo != (Object)null && ((Il2CppObjectBase)val.belongsTo).Pointer == ((Il2CppObjectBase)player).Pointer) { val.SafeDelete(false); } } } } public static void Release(NewAddress office, FurnitureLocation desk) { Player instance = Player.Instance; if ((Object)(object)instance == (Object)null) { return; } Own(office, desk, (OwnershipClass)2, (Human)(object)instance, own: false); PlacardDesk = -1; CityData instance2 = CityData.Instance; Dictionary<int, Interactable> val = ((instance2 != null) ? instance2.savableInteractableDictionary : null); Interactable val2 = default(Interactable); if (PlacardId >= 0 && val != null && val.TryGetValue(PlacardId, ref val2) && val2 != null) { val2.SafeDelete(false); } PlacardId = -1; FurnitureLocation val3 = Drawers(office, desk); if (val3 != null) { Own(office, val3, (OwnershipClass)4, (Human)(object)instance, own: false); } Interactable val4 = WorkSpot(desk); if (val4 != null && ((Human)instance).workPosition != null && ((Il2CppObjectBase)((Human)instance).workPosition).Pointer == ((Il2CppObjectBase)val4).Pointer) { ((Human)instance).SetWorkFurniture((Interactable)null); } List<Interactable> spawnedInteractables = desk.spawnedInteractables; if (spawnedInteractables == null) { return; } for (int num = spawnedInteractables.Count - 1; num >= 0; num--) { Interactable val5 = spawnedInteractables[num]; if ((SoCustomComparison)(object)((val5 != null) ? val5.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)val5.preset).presetName == "NamePlacard" && (Object)(object)val5.belongsTo != (Object)null && ((Il2CppObjectBase)val5.belongsTo).Pointer == ((Il2CppObjectBase)instance).Pointer) { val5.SafeDelete(false); } } } private static FurnitureLocation? Drawers(NewAddress office, FurnitureLocation desk) { FurnitureLocation val = Find(office, desk.id + 1); if (!((SoCustomComparison)(object)((val != null) ? val.furniture : null) != (SoCustomComparison)null) || !((Object)val.furniture).name.Contains("Drawers")) { return null; } return val; } private static Interactable? WorkSpot(FurnitureLocation desk) { List<Interactable> integratedInteractables = desk.integratedInteractables; if (integratedInteractables == null) { return null; } Enumerator<Interactable> enumerator = integratedInteractables.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current = enumerator.Current; if ((SoCustomComparison)(object)((current != null) ? current.preset : null) != (SoCustomComparison)null && ((SoCustomComparison)current.preset).presetName == ((Object)desk.furniture).name) { return current; } } if (integratedInteractables.Count <= 0) { return null; } return integratedInteractables[0]; } private static void Own(NewAddress office, FurnitureLocation f, OwnershipClass cls, Human who, bool own) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> furnitureBelongsTo = ((NewGameLocation)office).furnitureBelongsTo; if (furnitureBelongsTo != null) { OwnInMap(furnitureBelongsTo, f, cls, who, own); } List<Interactable> integratedInteractables = f.integratedInteractables; if (integratedInteractables == null) { return; } Enumerator<Interactable> enumerator = integratedInteractables.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current = enumerator.Current; if (!((SoCustomComparison)(object)((current != null) ? current.preset : null) == (SoCustomComparison)null) && !((SoCustomComparison)current.preset).presetName.Contains("Cruncher")) { if (own && (Object)(object)current.belongsTo == (Object)null) { current.belongsTo = who; } else if (!own && (Object)(object)current.belongsTo != (Object)null && ((Il2CppObjectBase)current.belongsTo).Pointer == ((Il2CppObjectBase)who).Pointer) { current.belongsTo = null; } } } } private static void OwnInMap(Dictionary<OwnershipClass, Dictionary<FurnitureLocation, List<Human>>> belongs, FurnitureLocation f, OwnershipClass cls, Human who, bool own) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) Dictionary<FurnitureLocation, List<Human>> val = default(Dictionary<FurnitureLocation, List<Human>>); if (!belongs.TryGetValue(cls, ref val) || val == null) { if (!own) { return; } val = (belongs[cls] = new Dictionary<FurnitureLocation, List<Human>>()); } List<Human> val3 = default(List<Human>); if (!val.TryGetValue(f, ref val3) || val3 == null) { if (!own) { return; } val3 = (val[f] = new List<Human>()); } bool flag = false; Enumerator<Human> enumerator = val3.GetEnumerator(); while (enumerator.MoveNext()) { Human current = enumerator.Current; if ((Object)(object)current != (Object)null && ((Il2CppObjectBase)current).Pointer == ((Il2CppObjectBase)who).Pointer) { flag = true; } } if (own && !flag) { val3.Add(who); } if (!(!own && flag)) { return; } for (int num = val3.Count - 1; num >= 0; num--) { if ((Object)(object)val3[num] != (Object)null && ((Il2CppObjectBase)val3[num]).Pointer == ((Il2CppObjectBase)who).Pointer) { val3.RemoveAt(num); } } } private static IEnumerable<FurnitureLocation> Furniture(NewAddress office) { if (((NewGameLocation)office).rooms == null) { yield break; } Enumerator<NewRoom> enumerator = ((NewGameLocation)office).rooms.GetEnumerator(); while (enumerator.MoveNext()) { NewRoom current = enumerator.Current; if (((current != null) ? current.individualFurniture : null) == null) { continue; } Enumerator<FurnitureLocation> enumerator2 = current.individualFurniture.GetEnumerator(); while (enumerator2.MoveNext()) { FurnitureLocation current2 = enumerator2.Current; if ((SoCustomComparison)(object)((current2 != null) ? current2.furniture : null) != (SoCustomComparison)null) { yield return current2; } } } } } public static class Discipline { public static int Strikes { get; private set; } public static float LastStrikeAt { get; private set; } = -1f; public static float ProbationUntil { get; private set; } = -1f; public static int Deduction { get; set; } public static bool OnProbation { get { if ((Object)(object)SessionData.Instance != (Object)null) { return SessionData.Instance.gameTime < ProbationUntil; } return false; } } public static void Load(int strikes, float last, float probation, int deduction) { Strikes = strikes; LastStrikeAt = last; ProbationUntil = probation; Deduction = deduction; } public static void Reset() { Load(0, -1f, -1f, 0); } public static void Strike(string subject, string what) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown if (Employment.Employed) { float gameTime = SessionData.Instance.gameTime; Strikes++; LastStrikeAt = gameTime; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(22, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[discipline] strike "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Strikes); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(subject); } log.LogInfo(val); string text; switch (Strikes) { case 1: text = "Consider this a warning."; break; case 2: { int num = (int)(Payroll.PerShift() * Plugin.Cfg.DockShifts.Value); Deduction += num; text = $"Cr {num} will come out of your next pay."; break; } case 3: ProbationUntil = gameTime + 24f * Plugin.Cfg.ProbationDays.Value; Reports.Expect(Reports.Kind.Paperwork, "Disciplinary paperwork", gameTime); text = $"You're on probation for {Plugin.Cfg.ProbationDays.Value:0} days: your warrant requests go to the bottom of the pile, " + "and the uniforms have been told to keep you at arm's length. You also have paperwork to catch up on."; break; default: text = "That's the last one. You're dismissed. Hand in your badge at the front desk on your way out."; break; } Captain.Memo(subject, "|receiver.casualname|, " + what + " " + text); if (Strikes >= 4) { Employment.Dismiss(); } } } public static void Tick() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Expected O, but got Unknown if (!Employment.Employed || Strikes <= 0) { return; } float gameTime = SessionData.Instance.gameTime; if (LastStrikeAt >= 0f && gameTime - LastStrikeAt >= 24f * Plugin.Cfg.CoolDays.Value) { Strikes--; LastStrikeAt = gameTime; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(46, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[discipline] a clean stretch: strikes down to "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Strikes); } log.LogInfo(val); } } public static int TakeDeduction(int amount) { int num = Math.Min(amount, Deduction); Deduction -= num; return num; } } public static class Employment { private const string OfficePreset = "EnforcerOffice"; private static readonly Random Dice = new Random(); private static float _nextCheck; private const string JobName = "Detective"; private const int JobId = 990001; private static NewAddress? _granted; public static int DivisionAddressId { get; private set; } = -1; public static int DeskId { get; private set; } = -1; public static float ApplicationAt { get; private set; } = -1f; public static bool Employed { get { if (Plugin.Cfg.OnTheForce.Value) { return DivisionAddressId >= 0; } return false; } } public static bool AutoHire { get { if (Plugin.Cfg.OnTheForce.Value) { return !Plugin.Cfg.HireInGame.Value; } return false; } } public static bool Applied => ApplicationAt >= 0f; public static Company? Division { get { CityData instance = CityData.Instance; Dictionary<int, NewAddress> val = ((instance != null) ? instance.addressDictionary : null); NewAddress val2 = default(NewAddress); if (DivisionAddressId < 0 || val == null || !val.TryGetValue(DivisionAddressId, ref val2)) { return null; } if (val2 == null) { return null; } return val2.company; } } public static bool IsOwn(NewAddress? address) { if ((Object)(object)address != (Object)null && DivisionAddressId >= 0) { return address.id == DivisionAddressId; } return false; } public static bool IsOffice(NewAddress? address) { if ((SoCustomComparison)(object)((address != null) ? address.addressPreset : null) != (SoCustomComparison)null && ((Object)address.addressPreset).name == "EnforcerOffice") { return address.company != null; } return false; } public static string Apply() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (Employed) { Company? division = Division; return "You already serve with " + ((division != null) ? division.name : null) + "."; } if (Applied) { return "Your application is already being reviewed."; } float value = Plugin.Cfg.ApplicationHours.Value; ApplicationAt = SessionData.Instance.gameTime + value; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(26, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] applied, answer in "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(value, "0.#"); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("h"); } log.LogInfo(val); return $"Application filed. You'll hear back in about {Mathf.CeilToInt(value)} hours."; } public static void Dismiss() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Company division = Division; Leave(); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(21, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] dismissed from "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((division != null) ? division.name : null) ?? "the force"); } log.LogInfo(val); Notify("You have been dismissed from " + (((division != null) ? division.name : null) ?? "the force") + ".", (Icon)29); } public static void Resign() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown Company division = Division; Leave(); ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(20, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] resigned from "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((division != null) ? division.name : null) ?? "the force"); } log.LogInfo(val); Notify("You have resigned from " + (((division != null) ? division.name : null) ?? "the force") + ".", (Icon)29); } private static void Leave() { ReleaseDesk(); Shifts.Reset(); Reports.Reset(); Payroll.Reset(); Discipline.Reset(); DivisionAddressId = -1; ApplicationAt = -1f; EnsureAuthority(); EnsureRoster(); } public static bool Join(NewAddress office) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown if (DivisionAddressId >= 0 || !IsOffice(office)) { return false; } DivisionAddressId = office.id; ApplicationAt = -1f; EnsureAuthority(); EnsureRoster(); EnsureDesk(); Human director = office.company.director; ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[job] you now serve in "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(office.company.name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (office "); ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)office).name); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", floor "); NewFloor floor = ((NewGameLocation)office).floor; ((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int?>((floor != null) ? new int?(floor.floor) : ((int?)null)); ((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")"); } log.LogInfo(val); Notify("You've been assigned to " + office.company.name + (((Object)(object)director == (Object)null) ? "." : (". Report to Captain " + director.GetCitizenName() + ".")), (Icon)13); Human val2 = director ?? WarrantMail.Sender(); if ((Object)(object)val2 != (Object)null) { string[] obj = new string[9] { "|receiver.name|, your application has been approved. You are assigned to ", office.company.name, " as a detective. ", ((Object)(object)director == (Object)null) ? "" : ("Report to Captain " + director.GetCitizenName() + " "), null, null, null, null, null }; DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(35, 2); defaultInterpolatedStringHandler.AppendLiteral("at the "); defaultInterpolatedStringHandler.AppendFormatted(office.company.name); defaultInterpolatedStringHandler.AppendLiteral(" office, City Hall, floor "); NewFloor floor2 = ((NewGameLocation)office).floor; defaultInterpolatedStringHandler.AppendFormatted((floor2 != null) ? new int?(floor2.floor) : ((int?)null)); defaultInterpolatedStringHandler.AppendLiteral(". "); obj[4] = defaultInterpolatedStringHandler.ToStringAndClear(); string text = DeskRoom(); obj[5] = ((text != null) ? ("Your desk is waiting for you in the " + text + ". ") : ""); obj[6] = "Your shifts are "; obj[7] = Shifts.ScheduleText(); obj[8] = ". Sign in at a division cruncher when each one starts. You have an account on the division's crunchers, and our premises are open to you at any hour."; WarrantMail.Letter(val2, string.Concat(obj), "WELCOME TO " + office.company.name.ToUpperInvariant(), "City Hall personnel office.", "welcome letter from " + office.company.name); } return true; } private static void Decide() { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown ApplicationAt = -1f; List<NewAddress> list = new List<NewAddress>(); List<NewAddress> list2 = new List<NewAddress>(); CityData instance = CityData.Instance; Dictionary<int, NewAddress> val = ((instance != null) ? instance.addressDictionary : null); if (val != null) { Enumerator<int, NewAddress> enumerator = val.GetEnumerator(); bool flag = default(bool); while (enumerator.MoveNext()) { KeyValuePair<int, NewAddress> current = enumerator.Current; if (!IsOffice(current.Value)) { continue; } list.Add(current.Value); int count = Desks.Free(current.Value).Count; if (count > 0) { list2.Add(current.Value); } if (Plugin.Cfg.DebugLogging.Value) { ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(33, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[job] "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(current.Value.company.name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" ("); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)current.Value).name); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("): "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(Desks.All(current.Value).Count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" work positions, "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(count); ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" free"); } log.LogInfo(val2); } } } if (list.Count == 0) { Plugin.Log.LogWarning((object)"[job] no enforcer divisions in this city"); Notify("Your application was lost. Try again.", (Icon)29); } else { List<NewAddress> list3 = ((list2.Count > 0) ? list2 : list); Join(list3[Dice.Next(list3.Count)]); } } private static void Notify(string text, Icon icon) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) Lib.GameMessage.Broadcast(text, (GameMessageType)0, icon, (Color?)null, 0f); } public static void Load(int addressId, float applicationAt, int deskId) { DivisionAddressId = addressId; ApplicationAt = applicationAt; DeskId = deskId; EnsureAuthority(); EnsureRoster(); EnsureDesk(); } public static void Reset() { DivisionAddressId = -1; ApplicationAt = -1f; DeskId = -1; } public static void Tick() { if (!(Time.unscaledTime < _nextCheck)) { _nextCheck = Time.unscaledTime + 5f; SessionData instance = SessionData.Instance; if (Applied && (Object)(object)instance != (Object)null && instance.gameTime >= ApplicationAt) { Decide(); } EnsureAuthority(); EnsureRoster(); EnsureDesk(); } } public static void EnsureAuthority() { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown bool flag = default(bool); try { Player instance = Player.Instance; HashSet<NewGameLocation> val = ((instance != null) ? ((Actor)instance).locationsOfAuthority : null); if ((Object)(object)instance == (Object)null || val == null) { return; } NewAddress val2 = null; CityData instance2 = CityData.Instance; Dictionary<int, NewAddress> val3 = ((instance2 != null) ? instance2.addressDictionary : null); if (Employed) { val3?.TryGetValue(DivisionAddressId, ref val2); } if ((Object)(object)_granted != (Object)null && ((Object)(object)val2 == (Object)null || ((Il2CppObjectBase)_granted).Pointer != ((Il2CppObjectBase)val2).Pointer)) { val.Remove((NewGameLocation)(object)_granted); if (Plugin.Cfg.DebugLogging.Value) { ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] authority removed: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)_granted).name); } log.LogInfo(val4); } _granted = null; } if ((Object)(object)val2 == (Object)null || val.Contains((NewGameLocation)(object)val2)) { if (_granted == null) { _granted = val2; } return; } val.Add((NewGameLocation)(object)val2); _granted = val2; if (Plugin.Cfg.DebugLogging.Value) { ManualLogSource log2 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val4 = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] authority granted: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(((Object)val2).name); } log2.LogInfo(val4); } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val5 = new BepInExErrorLogInterpolatedStringHandler(36, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[job] could not set your authority: "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ex.Message); } log3.LogError(val5); } } private static NewAddress? Office() { CityData instance = CityData.Instance; Dictionary<int, NewAddress> val = ((instance != null) ? instance.addressDictionary : null); NewAddress result = default(NewAddress); if (!Employed || val == null || !val.TryGetValue(DivisionAddressId, ref result)) { return null; } return result; } public static void EnsureDesk() { //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown bool flag = default(bool); try { NewAddress val = Office(); if ((Object)(object)val == (Object)null) { return; } Player instance = Player.Instance; if ((Object)(object)instance != (Object)null) { Desks.EnsurePhoto(val, (Human)(object)instance); } FurnitureLocation val2 = ((DeskId >= 0) ? Desks.Find(val, DeskId) : null); if (val2 == null) { List<FurnitureLocation> list = Desks.Free(val); BepInExInfoLogInterpolatedStringHandler val3; if (list.Count == 0) { if (DeskId != -2) { ManualLogSource log = Plugin.Log; val3 = new BepInExInfoLogInterpolatedStringHandler(22, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] no free desk in "); BepInExInfoLogInterpolatedStringHandler obj = val3; Company company = val.company; ((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>((company != null) ? company.name : null); } log.LogInfo(val3); } DeskId = -2; return; } list.Sort((FurnitureLocation a, FurnitureLocation b) => a.id.CompareTo(b.id)); val2 = list[0]; DeskId = val2.id; ManualLogSource log2 = Plugin.Log; val3 = new BepInExInfoLogInterpolatedStringHandler(23, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] your desk: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)val2.furniture).name); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" #"); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(val2.id); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" in "); BepInExInfoLogInterpolatedStringHandler obj2 = val3; NewNode anchorNode = val2.anchorNode; object obj3; if (anchorNode == null) { obj3 = null; } else { NewRoom room = anchorNode.room; obj3 = ((room != null) ? room.name : null); } ((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((string)obj3); } log2.LogInfo(val3); } Desks.Claim(val, val2); } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; BepInExErrorLogInterpolatedStringHandler val4 = new BepInExErrorLogInterpolatedStringHandler(34, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[job] could not set up your desk: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message); } log3.LogError(val4); } } private static void ReleaseDesk() { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown try { NewAddress val = Office(); FurnitureLocation val2 = (((Object)(object)val != (Object)null && DeskId >= 0) ? Desks.Find(val, DeskId) : null); if ((Object)(object)val != (Object)null && val2 != null) { Desks.Release(val, val2); } if ((Object)(object)val != (Object)null && (Object)(object)Player.Instance != (Object)null) { Desks.RemovePhoto(val, (Human)(object)Player.Instance); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; bool flag = default(bool); BepInExErrorLogInterpolatedStringHandler val3 = new BepInExErrorLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[job] could not clear your desk: "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(ex.Message); } log.LogError(val3); } DeskId = -1; } private static string? DeskRoom() { NewAddress val = Office(); FurnitureLocation? obj = (((Object)(object)val != (Object)null && DeskId >= 0) ? Desks.Find(val, DeskId) : null); object obj2; if (obj == null) { obj2 = null; } else { NewNode anchorNode = obj.anchorNode; if (anchorNode == null) { obj2 = null; } else { NewRoom room = anchorNode.room; obj2 = ((room != null) ? room.name : null); } } string text = (string)obj2; if (text == null) { return null; } Company company = val.company; string text2 = ((company != null) ? company.name : null) ?? ""; if (text2.Length <= 0 || !text.StartsWith(text2)) { return text; } return text.Substring(text2.Length).Trim() + " room"; } public static void EnsureRoster() { //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_059b: Expected O, but got Unknown //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_053e: Unknown result type (might be due to invalid IL or missing references) //IL_0545: Expected O, but got Unknown //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_02a4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Expected O, but got Unknown //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Expected O, but got Unknown bool flag = default(bool); try { Player instance = Player.Instance; if ((Object)(object)instance == (Object)null) { return; } Company val = (Employed ? Division : null); Occupation val2 = null; CityData instance2 = CityData.Instance; Dictionary<int, NewAddress> val3 = ((instance2 != null) ? instance2.addressDictionary : null); if (val3 != null) { Enumerator<int, NewAddress> enumerator = val3.GetEnumerator(); while (enumerator.MoveNext()) { KeyValuePair<int, NewAddress> current = enumerator.Current; NewAddress value = current.Value; object obj; if (value == null) { obj = null; } else { Company company = value.company; obj = ((company != null) ? company.companyRoster : null); } List<Occupation> val4 = (List<Occupation>)obj; if (val4 == null || !IsOffice(current.Value)) { continue; } for (int num = val4.Count - 1; num >= 0; num--) { Occupation val5 = val4[num]; if (val5 != null && !(val5.name != "Detective")) { if (val != null && ((Il2CppObjectBase)current.Value.company).Pointer == ((Il2CppObjectBase)val).Pointer && val2 == null) { val2 = val5; } else { val4.RemoveAt(num); if (Plugin.Cfg.DebugLogging.Value) { ManualLogSource log = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[job] removed your position from "); ((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(current.Value.company.name); } log.LogInfo(val6); } } } } } } if (val == null) { if (((Human)instance).job != null && ((Human)instance).job.name == "Detective") { ((Human)instance).job = null; } return; } if (val2 == null) { Occupation val7 = RankAndFile(val); val2 = new Occupation { id = 990001, name = "Detective", employer = val, preset = ((val7 != null) ? val7.preset : null), boss = (((val7 != null) ? val7.boss : null) ?? CaptainOf(val)), paygrade = ((val7 != null) ? val7.paygrade : 0f), teamID = ((val7 != null) ? val7.teamID : 0), work = (workType)((val7 != null) ? ((int)val7.work) : 0), tags = ((val7 != null) ? val7.tags : null), shift = ((val7 != null) ? val7.shift : null), workHours = Mathf.Repeat(Plugin.Cfg.ShiftEnd.Value - Plugin.Cfg.ShiftStart.Value, 24f), startTimeDecimalHour = Plugin.Cfg.ShiftStart.Value, endTimeDecialHour = Plugin.Cfg.ShiftEnd.Value, lunchBreak = (val7 != null && val7.lunchBreak), lunchBreakHoursAfterStart = ((val7 != null) ? val7.lunchBreakHoursAfterStart : 4f), workDaysList = Shifts.WorkDayList(), salary = ((val7 != null) ? val7.salary : 0f), salaryString = (((val7 != null) ? val7.salaryString : null) ?? "") }; val.companyRoster.Add(val2); if (Plugin.Cfg.DebugLogging.Value) { ManualLogSource log2 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(47, 4, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[job] added your position to "); ((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>(val.name); ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("(modelled on "); BepInExInfoLogInterpolatedStringHandler obj2 = val6; object obj3; if (val7 == null) { obj3 = null; } else { Human employee = val7.employee; obj3 = ((employee != null) ? employee.GetCitizenName() : null); } if (obj3 == null) { obj3 = "nobody"; } ((BepInExLogInterpolatedStringHandler)obj2).AppendFormatted<string>((string)obj3); ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(", "); ((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(val2.startTimeDecimalHour, "0.#"); ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("-"); ((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<float>(val2.endTimeDecialHour, "0.#"); ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral(")"); } log2.LogInfo(val6); } } if (Math.Abs(val2.startTimeDecimalHour - Plugin.Cfg.ShiftStart.Value) > 0.01f || Math.Abs(val2.endTimeDecialHour - Plugin.Cfg.ShiftEnd.Value) > 0.01f || val2.workDaysList == null || val2.workDaysList.Count != Shifts.WorkDayList().Count) { val2.startTimeDecimalHour = Plugin.Cfg.ShiftStart.Value; val2.endTimeDecialHour = Plugin.Cfg.ShiftEnd.Value; val2.workHours = Mathf.Repeat(Plugin.Cfg.ShiftEnd.Value - Plugin.Cfg.ShiftStart.Value, 24f); val2.workDaysList = Shifts.WorkDayList(); } if ((Object)(object)val2.employee == (Object)null || ((Il2CppObjectBase)val2.employee).Pointer != ((Il2CppObjectBase)instance).Pointer || ((Human)instance).job == null || ((Il2CppObjectBase)((Human)instance).job).Pointer != ((Il2CppObjectBase)val2).Pointer) { val2.employee = (Human)(object)instance; ((Human)instance).job = val2; if (Plugin.Cfg.DebugLogging.Value) { ManualLogSource log3 = Plugin.Log; BepInExInfoLogInterpolatedStringHandler val6 = new BepInExInfoLogInterpolatedStringHandler(32, 2, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val6).AppendLiteral("[job] you hold the "); ((BepInExLogInterpolatedStringHandler)val6).AppendFormatted<string>("Detective"); ((BepInExLogInterpolatedStringHandler)val6).Appe