Decompiled source of PlacementPlus v1.0.2
PlacementPlus.dll
Decompiled a month 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.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Core.Logging.Interpolation; using BepInEx.Logging; using BepInEx.Unity.IL2CPP; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSystem.Collections.Generic; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("PlacementPlus")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+7d2219598bf08d3847b163d97ca54b7ddc17917a")] [assembly: AssemblyProduct("PlacementPlus")] [assembly: AssemblyTitle("PlacementPlus")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [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 PlacementPlus { internal static class ApartmentShutters { internal static int SuppressLockdown; internal static bool Enabled => PlacementConfig.ApartmentShutters?.Value ?? true; internal static bool IsOurDoor(Interactable inter) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Invalid comparison between Unknown and I4 try { if (inter == null || (SoCustomComparison)(object)inter.preset == (SoCustomComparison)null) { return false; } if ((int)inter.preset.specialCaseFlag != 5) { return false; } FurnitureLocation furnitureParent = inter.furnitureParent; return furnitureParent != null && furnitureParent.userPlaced; } catch { return false; } } internal static bool IsOurBreaker(Interactable inter) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 try { if (inter == null || (SoCustomComparison)(object)inter.preset == (SoCustomComparison)null) { return false; } SpecialCase specialCaseFlag = inter.preset.specialCaseFlag; if ((int)specialCaseFlag != 28 && (int)specialCaseFlag != 27 && (int)specialCaseFlag != 26) { return false; } FurnitureLocation furnitureParent = inter.furnitureParent; return furnitureParent != null && furnitureParent.userPlaced; } catch { return false; } } internal static NewAddress AddressOf(Interactable inter) { try { return (inter != null && inter.node != null && (Object)(object)inter.node.gameLocation != (Object)null) ? inter.node.gameLocation.thisAsAddress : null; } catch { return null; } } internal static void DriveDoors(Interactable breaker, bool sw0) { try { NewAddress val = AddressOf(breaker); if ((Object)(object)val == (Object)null || ((NewGameLocation)val).rooms == null) { return; } bool flag = true; try { flag = (Object)(object)SessionData.Instance != (Object)null && SessionData.Instance.startedGame; } catch { } List<NewRoom> rooms = ((NewGameLocation)val).rooms; for (int i = 0; i < rooms.Count; i++) { NewRoom val2 = rooms[i]; if ((Object)(object)val2 == (Object)null || val2.specialCaseInteractables == null || !val2.specialCaseInteractables.ContainsKey((SpecialCase)5)) { continue; } List<Interactable> val3 = val2.specialCaseInteractables[(SpecialCase)5]; if (val3 == null) { continue; } for (int j = 0; j < val3.Count; j++) { Interactable val4 = val3[j]; if (val4 == null || !IsOurDoor(val4)) { continue; } try { if (val4.sw0 != sw0) { val4.SetSwitchState(sw0, (Actor)null, flag, false, false); } } catch { } } } } catch { } } internal static void ForEachHomeDoorsBreaker(Action<Interactable> act) { try { Player instance = Player.Instance; if ((Object)(object)instance == (Object)null) { return; } ProcessAddress(((Human)instance).home, act); List<NewAddress> apartmentsOwned = instance.apartmentsOwned; if (apartmentsOwned != null) { for (int i = 0; i < apartmentsOwned.Count; i++) { ProcessAddress(apartmentsOwned[i], act); } } } catch { } } private static void ProcessAddress(NewAddress addr, Action<Interactable> act) { try { if ((Object)(object)addr == (Object)null || ((NewGameLocation)addr).rooms == null) { return; } List<NewRoom> rooms = ((NewGameLocation)addr).rooms; for (int i = 0; i < rooms.Count; i++) { NewRoom val = rooms[i]; if ((Object)(object)val == (Object)null || val.specialCaseInteractables == null || !val.specialCaseInteractables.ContainsKey((SpecialCase)28)) { continue; } List<Interactable> val2 = val.specialCaseInteractables[(SpecialCase)28]; if (val2 == null) { continue; } for (int j = 0; j < val2.Count; j++) { Interactable val3 = val2[j]; if (val3 != null && IsOurBreaker(val3)) { try { act(val3); } catch { } } } } } catch { } } internal static void ResyncAll() { if (!Enabled) { return; } ForEachHomeDoorsBreaker(delegate(Interactable b) { try { DriveDoors(b, b.sw0); } catch { } }); } internal static void OpenSealedHomes() { ForEachHomeDoorsBreaker(delegate(Interactable b) { try { if (!b.sw0) { b.SetSwitchState(true, (Actor)null, true, false, false); DriveDoors(b, sw0: true); } } catch { } }); } } public class DecorProbe : MonoBehaviour { public DecorProbe(IntPtr ptr) : base(ptr) { } private void Update() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) try { ConfigEntry<bool> enabled = PlacementConfig.Enabled; if (enabled != null && enabled.Value) { Player instance = Player.Instance; if ((!((Object)(object)instance != (Object)null) || instance.computerInteractable == null) && Input.GetKeyDown(PlacementConfig.ProbeKey.Value)) { DumpAll(); } } } catch { } } private void DumpAll() { StringBuilder stringBuilder = new StringBuilder(32768); List<string> list = new List<string>(); stringBuilder.Append("===== PlacementPlus DecorProbe @ ").Append(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")).Append(" =====\n"); try { DumpFurnitureCensus(stringBuilder, list); } catch (Exception ex) { Line(stringBuilder, list, "[FURNITURE CENSUS FAILED: " + ex.Message + "]"); } try { DumpItemPlacementCensus(stringBuilder, list); } catch (Exception ex2) { Line(stringBuilder, list, "[ITEM PLACEMENT CENSUS FAILED: " + ex2.Message + "]"); } try { DumpCeilingMeasurements(stringBuilder, list); } catch (Exception ex3) { Line(stringBuilder, list, "[CEILING MEASUREMENT FAILED: " + ex3.Message + "]"); } try { DumpSurfaceProbe(stringBuilder, list); } catch (Exception ex4) { Line(stringBuilder, list, "[SURFACE PROBE FAILED: " + ex4.Message + "]"); } try { DumpSecurityFixtures(stringBuilder, list); } catch (Exception ex5) { Line(stringBuilder, list, "[SECURITY FIXTURE PROBE FAILED: " + ex5.Message + "]"); } stringBuilder.Append("===== end DecorProbe ====="); string text = stringBuilder.ToString(); ConfigEntry<bool> writeFile = PlacementConfig.WriteFile; string text2 = ((writeFile == null || writeFile.Value) ? WriteToFile(text) : null); Plugin.Log2.LogMessage((object)"[PlacementPlus] DecorProbe dump:"); foreach (string item in list) { Plugin.Log2.LogMessage((object)(" " + item)); } if (text2 != null) { Plugin.Log2.LogMessage((object)("[PlacementPlus] full census written to: " + text2)); } } private void DumpFurnitureCensus(StringBuilder sb, List<string> echo) { //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) Toolbox instance = Toolbox.Instance; List<FurniturePreset> val = (((Object)(object)instance != (Object)null) ? instance.allFurniture : null); sb.Append("\n--- FURNITURE CENSUS ---\n"); if (val == null) { Line(sb, echo, "allFurniture is null (not loaded yet?)"); return; } int count = val.Count; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; sb.Append("status | name | decorClass | purchasable | disableFromMenu | hasPrefab | cost | class0\n"); Enumerator<FurniturePreset> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { FurniturePreset current = enumerator.Current; if ((SoCustomComparison)(object)current == (SoCustomComparison)null) { continue; } try { bool flag = (Object)(object)current.prefab != (Object)null; string value; if (!flag) { value = "UNPLACEABLE"; num4++; } else if (current.disableFromDecorMenu) { value = "HIDDEN-MENU"; num3++; } else if (!current.purchasable) { value = "HIDDEN-SHOP"; num2++; } else { value = "VISIBLE"; num++; } string value2 = "-"; if (current.classes != null && current.classes.Count > 0 && (SoCustomComparison)(object)current.classes[0] != (SoCustomComparison)null) { FurnitureClass val2 = current.classes[0]; StringBuilder stringBuilder = new StringBuilder(); if (val2.ceilingPiece) { stringBuilder.Append("CEIL "); } if (val2.wallPiece) { stringBuilder.Append("WALL "); } if (val2.useWallSnappingInDecorMode) { stringBuilder.Append("WSNAP "); } value2 = stringBuilder.ToString() + val2.objectSize.x.ToString("0.#") + "x" + val2.objectSize.y.ToString("0.#"); } sb.Append(value).Append(" | ").Append(SafeName((Object)(object)current)) .Append(" | ") .Append(((object)current.decorClass/*cast due to .constrained prefix*/).ToString()) .Append(" | p=") .Append(current.purchasable) .Append(" | dm=") .Append(current.disableFromDecorMenu) .Append(" | prefab=") .Append(flag) .Append(" | cost=") .Append(current.cost) .Append(" | ") .Append(value2) .Append('\n'); } catch (Exception ex) { sb.Append("[row error: ").Append(ex.Message).Append("]\n"); } } Line(sb, echo, $"furniture: {count} total | {num} visible | {num2} hidden-shop | {num3} hidden-menu | {num4} unplaceable"); } private unsafe void DumpItemPlacementCensus(StringBuilder sb, List<string> echo) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Invalid comparison between Unknown and I4 //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Invalid comparison between Unknown and I4 //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Invalid comparison between Unknown and I4 Il2CppArrayBase<InteractablePreset> val = Resources.FindObjectsOfTypeAll<InteractablePreset>(); sb.Append("\n--- ITEM PLACEMENT-MODE CENSUS ---\n"); if (val == null) { Line(sb, echo, "no InteractablePresets found"); return; } int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int length = val.Length; StringBuilder stringBuilder = new StringBuilder(); sb.Append("name | apartmentPlacementMode | isInventoryItem | allowInStorage | mustTouchFurniture (non-physics rows only)\n"); for (int i = 0; i < val.Length; i++) { InteractablePreset val2 = val[i]; if ((SoCustomComparison)(object)val2 == (SoCustomComparison)null) { continue; } try { ApartmentPlacementMode apartmentPlacementMode = val2.apartmentPlacementMode; bool isInventoryItem = val2.isInventoryItem; if ((int)apartmentPlacementMode == 2) { num3++; } else if ((int)apartmentPlacementMode == 1) { num2++; } else { num++; } if (isInventoryItem) { num4++; } if ((int)apartmentPlacementMode == 0) { continue; } int value = ((val2.mustTouchFurniture != null) ? val2.mustTouchFurniture.Count : 0); sb.Append(SafeName((Object)(object)val2)).Append(" | ").Append(((object)(*(ApartmentPlacementMode*)(&apartmentPlacementMode))/*cast due to .constrained prefix*/).ToString()) .Append(" | inv=") .Append(isInventoryItem) .Append(" | storage=") .Append(val2.allowInApartmentStorage) .Append(" | mustTouch=") .Append(value) .Append('\n'); if ((int)apartmentPlacementMode == 2) { if (stringBuilder.Length > 0) { stringBuilder.Append(", "); } stringBuilder.Append(SafeName((Object)(object)val2)); } } catch { } } Line(sb, echo, $"items: {length} presets | physics={num} vertical(wall)={num2} ceiling={num3} | inventory={num4}"); Line(sb, echo, "ceiling-mode items (Path C targets): " + ((stringBuilder.Length > 0) ? stringBuilder.ToString() : "(none)")); } private void DumpCeilingMeasurements(StringBuilder sb, List<string> echo) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02e6: Invalid comparison between Unknown and I4 //IL_02ff: Unknown result type (might be due to invalid IL or missing references) sb.Append("\n--- CEILING MEASUREMENTS (current room) ---\n"); Player instance = Player.Instance; NewRoom val = (((Object)(object)instance != (Object)null) ? ((Actor)instance).currentRoom : null); if ((Object)(object)val == (Object)null) { Line(sb, echo, "no current room (stand inside a room and press again)"); return; } sb.Append("room: ").Append(SafeRoomName(val)).Append('\n'); List<Interactable> mainLights = val.mainLights; int num = 0; if (mainLights != null) { Enumerator<Interactable> enumerator = mainLights.GetEnumerator(); while (enumerator.MoveNext()) { Interactable current = enumerator.Current; if (current != null) { try { float num2 = TrueCeilingY(current.node); float y = current.wPos.y; Line(sb, echo, $"mainLight '{InterName(current)}': y={y:0.###} trueCeiling={num2:0.###} gap={num2 - y:0.###}m (Path A)"); num++; } catch (Exception ex) { sb.Append(" [light err: ").Append(ex.Message).Append("]\n"); } } } } if (num == 0) { Line(sb, echo, "no main lights in this room"); } List<FurnitureLocation> individualFurniture = val.individualFurniture; int num3 = 0; if (individualFurniture != null) { Enumerator<FurnitureLocation> enumerator2 = individualFurniture.GetEnumerator(); while (enumerator2.MoveNext()) { FurnitureLocation current2 = enumerator2.Current; if (current2 == null) { continue; } try { if (current2.furnitureClasses != null && current2.furnitureClasses.Count != 0 && !((SoCustomComparison)(object)current2.furnitureClasses[0] == (SoCustomComparison)null) && current2.furnitureClasses[0].ceilingPiece) { GameObject spawnedObject = current2.spawnedObject; if (!((Object)(object)spawnedObject == (Object)null)) { float num4 = TrueCeilingY(current2.anchorNode); float y2 = spawnedObject.transform.position.y; float num5 = TopY(spawnedObject, y2); Line(sb, echo, $"ceilFurniture '{SafeName((Object)(object)current2.furnitureClasses[0])}': objY={y2:0.###} top={num5:0.###} trueCeiling={num4:0.###} gap(top->ceil)={num4 - num5:0.###}m (Path B)"); num3++; } } } catch (Exception ex2) { sb.Append(" [furn err: ").Append(ex2.Message).Append("]\n"); } } } if (num3 == 0) { Line(sb, echo, "no ceiling furniture placed in this room"); } try { InteractionController instance2 = InteractionController.Instance; InteractableController val2 = (((Object)(object)instance2 != (Object)null) ? instance2.carryingObject : null); if ((Object)(object)val2 != (Object)null && val2.interactable != null && (SoCustomComparison)(object)val2.interactable.preset != (SoCustomComparison)null && (int)val2.interactable.preset.apartmentPlacementMode == 2) { float num6 = TrueCeilingY(((Actor)instance).currentNode); float y3 = ((Component)val2).transform.position.y; float num7 = TopY(((Component)val2).gameObject, y3); Line(sb, echo, $"CARRIED ceiling item '{InterName(val2.interactable)}': objY={y3:0.###} top={num7:0.###} trueCeiling={num6:0.###} gap(top->ceil)={num6 - num7:0.###}m (Path C, while placing)"); } else { Line(sb, echo, "no ceiling-mode item carried — to measure Path C, hold a hanging light in placement mode and press again"); } } catch (Exception ex3) { sb.Append(" [carried err: ").Append(ex3.Message).Append("]\n"); } } private void DumpSurfaceProbe(StringBuilder sb, List<string> echo) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) sb.Append("\n--- SURFACE PROBE (crosshair) ---\n"); Player instance = Player.Instance; Transform val = (((Object)(object)instance != (Object)null && (Object)(object)instance.cam != (Object)null) ? ((Component)instance.cam).transform : null); if ((Object)(object)val == (Object)null) { Line(sb, echo, "no camera"); return; } Vector3 position = val.position; Vector3 forward = val.forward; ProbeMask(sb, echo, "layer29(wall/shell)", position, forward, 536870912); ProbeMask(sb, echo, "layer0(furniture) ", position, forward, 1); ProbeMask(sb, echo, "any-layer ", position, forward, -1); try { InteractionController instance2 = InteractionController.Instance; Interactable val2 = (((Object)(object)instance2 != (Object)null && (Object)(object)instance2.carryingObject != (Object)null) ? instance2.carryingObject.interactable : null); if (val2 == null) { InventorySlot val3 = (((Object)(object)BioScreenController.Instance != (Object)null) ? BioScreenController.Instance.selectedSlot : null); val2 = ((val3 != null) ? val3.GetInteractable() : null); } GameObject val4 = ((val2 != null) ? val2.spawnedObject : null); if ((Object)(object)val4 == (Object)null) { Line(sb, echo, "no carried/held item to measure (hold the silenced pistol and press again)"); return; } Line(sb, echo, "item renderers for '" + InterName(val2) + "':"); Il2CppArrayBase<Renderer> componentsInChildren = val4.GetComponentsInChildren<Renderer>(true); int num = componentsInChildren?.Length ?? 0; for (int i = 0; i < num && i < 12; i++) { Renderer val5 = componentsInChildren[i]; if (!((Object)(object)val5 == (Object)null)) { Bounds localBounds = val5.localBounds; object[] obj = new object[5] { i, SafeName((Object)(object)val5), Fmt(((Bounds)(ref localBounds)).center), Fmt(((Bounds)(ref localBounds)).extents), null }; Bounds bounds = val5.bounds; obj[4] = Fmt(((Bounds)(ref bounds)).center); Line(sb, echo, string.Format(" rend[{0}]={1} localCenter={2} localExtents={3} worldCenter={4}", obj)); } } } catch (Exception ex) { Line(sb, echo, "[item measure err: " + ex.Message + "]"); } } private static void ProbeMask(StringBuilder sb, List<string> echo, string label, Vector3 o, Vector3 d, int mask) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) try { RaycastHit val = default(RaycastHit); if (Physics.Raycast(o, d, ref val, 10f, mask, (QueryTriggerInteraction)1)) { Collider collider = ((RaycastHit)(ref val)).collider; GameObject val2 = (((Object)(object)collider != (Object)null) ? ((Component)collider).gameObject : null); int num = (((Object)(object)val2 != (Object)null) ? val2.layer : (-1)); string text = "?"; try { text = LayerMask.LayerToName(num); } catch { } Line(sb, echo, string.Format("{0}: hit='{1}' layer={2}({3}) tag={4} dist={5:0.###} point={6}", label, ((Object)(object)collider != (Object)null) ? SafeName((Object)(object)collider) : "?", num, text, SafeTag(val2), ((RaycastHit)(ref val)).distance, Fmt(((RaycastHit)(ref val)).point))); } else { Line(sb, echo, label + ": no hit"); } } catch (Exception ex) { Line(sb, echo, label + ": err " + ex.Message); } } private static string SafeTag(GameObject go) { try { return ((Object)(object)go != (Object)null) ? go.tag : "-"; } catch { return "?"; } } private static string Fmt(Vector3 v) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) return $"({v.x:0.##},{v.y:0.##},{v.z:0.##})"; } private void DumpSecurityFixtures(StringBuilder sb, List<string> echo) { //IL_025c: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Invalid comparison between Unknown and I4 //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Invalid comparison between Unknown and I4 //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Invalid comparison between Unknown and I4 //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Invalid comparison between Unknown and I4 sb.Append("\n--- SECURITY FIXTURE PRESETS (breaker/door integrated interactables) ---\n"); Toolbox instance = Toolbox.Instance; List<FurniturePreset> val = (((Object)(object)instance != (Object)null) ? instance.allFurniture : null); if (val == null) { Line(sb, echo, "allFurniture null"); return; } int num = 0; Enumerator<FurniturePreset> enumerator = val.GetEnumerator(); while (enumerator.MoveNext()) { FurniturePreset current = enumerator.Current; if ((SoCustomComparison)(object)current == (SoCustomComparison)null) { continue; } try { List<IntegratedInteractable> integratedInteractables = current.integratedInteractables; if (integratedInteractables == null || integratedInteractables.Count == 0) { continue; } bool flag = false; for (int i = 0; i < integratedInteractables.Count; i++) { InteractablePreset val2 = ((integratedInteractables[i] != null) ? integratedInteractables[i].preset : null); if (!((SoCustomComparison)(object)val2 == (SoCustomComparison)null)) { SpecialCase specialCaseFlag = val2.specialCaseFlag; if ((int)specialCaseFlag == 5 || (int)specialCaseFlag == 28 || (int)specialCaseFlag == 27 || (int)specialCaseFlag == 26) { flag = true; break; } } } if (!flag) { continue; } num++; Line(sb, echo, "FURNITURE '" + SafeName((Object)(object)current) + "' (purchasable=" + current.purchasable + ")"); for (int j = 0; j < integratedInteractables.Count; j++) { InteractablePreset val3 = ((integratedInteractables[j] != null) ? integratedInteractables[j].preset : null); if ((SoCustomComparison)(object)val3 == (SoCustomComparison)null) { continue; } string text = ""; try { List<InteractionAction> actions = val3.GetActions(0); if (actions != null) { for (int k = 0; k < actions.Count && k < 8; k++) { InteractionAction val4 = actions[k]; if (val4 != null) { if (text.Length > 0) { text += ", "; } text = text + (((SoCustomComparison)(object)val4.action != (SoCustomComparison)null) ? ((Object)val4.action).name : "?") + (string.IsNullOrEmpty(val4.interactionName) ? "" : ("[" + val4.interactionName + "]")); } } } } catch (Exception ex) { text = "(actions err: " + ex.Message + ")"; } Line(sb, echo, " inter '" + SafeName((Object)(object)val3) + "' flag=" + ((object)val3.specialCaseFlag/*cast due to .constrained prefix*/).ToString() + " startSwitch=" + val3.startingSwitchState + " startLock=" + val3.startingLockState + " reset=" + val3.resetSwitchStates + "/" + val3.resetTimer.ToString("0.##") + " padlock=" + (((SoCustomComparison)(object)val3.includeLock != (SoCustomComparison)null) ? SafeName((Object)(object)val3.includeLock) : "none")); Line(sb, echo, " actions: " + ((text.Length > 0) ? text : "(none)")); } } catch (Exception ex2) { sb.Append("[fixture err: ").Append(ex2.Message).Append("]\n"); } } Line(sb, echo, "security fixtures found: " + num); } private static float TrueCeilingY(NewNode node) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (node == null) { return float.NaN; } return node.position.y + (float)node.floor.defaultCeilingHeight * 0.1f - (float)node.floorHeight * 0.1f; } private static float TopY(GameObject go, float fallback) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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) try { Renderer componentInChildren = go.GetComponentInChildren<Renderer>(); if ((Object)(object)componentInChildren != (Object)null) { Bounds bounds = componentInChildren.bounds; return ((Bounds)(ref bounds)).max.y; } } catch { } return fallback; } private static string SafeName(Object o) { try { return (o != (Object)null) ? o.name : "null"; } catch { return "?"; } } private static string InterName(Interactable inter) { try { if (inter != null && (SoCustomComparison)(object)inter.preset != (SoCustomComparison)null) { return ((Object)inter.preset).name; } } catch { } return "item"; } private static string SafeRoomName(NewRoom room) { try { return room.name; } catch { } try { return ((SoCustomComparison)(object)room.preset != (SoCustomComparison)null) ? ((Object)room.preset).name : "room"; } catch { return "room"; } } private static void Line(StringBuilder sb, List<string> echo, string s) { sb.Append(s).Append('\n'); echo.Add(s); } private string WriteToFile(string text) { try { string text2 = Path.Combine(Paths.BepInExRootPath, "PlacementPlus"); Directory.CreateDirectory(text2); string text3 = Path.Combine(text2, "decor_census_" + DateTime.Now.ToString("yyyyMMdd_HHmmss") + ".txt"); File.WriteAllText(text3, text); return text3; } catch (Exception ex) { Plugin.Log2.LogWarning((object)("[PlacementPlus] file write failed: " + ex.Message)); return null; } } } internal static class Diag { internal static void DumpAnchors(string tag, Interactable inter) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Expected O, but got Unknown //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Expected O, but got Unknown //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_039a: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) try { if (!PlacementController.Verbose || inter == null) { return; } InteractableController controller = inter.controller; Transform val = (((Object)(object)inter.spawnedObject != (Object)null) ? inter.spawnedObject.transform : null); Transform val2 = (((Object)(object)controller != (Object)null) ? ((Component)controller).transform : null); Transform val3 = (((Object)(object)controller != (Object)null) ? controller.alternativePhysicsParent : null); Transform val4 = (((Object)(object)val3 != (Object)null) ? val3 : val2); string text = PlacementController.PresetName(inter); bool flag = (Object)(object)val3 == (Object)null; bool flag2 = (Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && (Object)(object)val == (Object)(object)val2; bool flag3 = (Object)(object)val4 != (Object)null && (Object)(object)val != (Object)null && val4.IsChildOf(val); ManualLogSource log = Plugin.Log2; bool flag4 = default(bool); BepInExWarningLogInterpolatedStringHandler val5 = new BepInExWarningLogInterpolatedStringHandler(93, 8, ref flag4); if (flag4) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[PlacementPlus][DIAG "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(tag); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" altNull="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" rootIsCtrl="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag2); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("tChildOfRoot="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag3); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" rootParent="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ParentName(val)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" ctrlParent="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ParentName(val2)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" altParent="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(ParentName(val3)); } log.LogWarning(val5); ManualLogSource log2 = Plugin.Log2; val5 = new BepInExWarningLogInterpolatedStringHandler(87, 9, ref flag4); if (flag4) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[PlacementPlus][DIAG "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(tag); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" rootPos="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(P(val)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" rootEul="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(E(val)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" | "); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("ctrlPos="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(P(val2)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" ctrlEul="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(E(val2)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" | altPos="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(P(val3)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" altEul="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(E(val3)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" | wPos="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(PlacementController.V(inter.wPos)); } log2.LogWarning(val5); if (!((Object)(object)val != (Object)null)) { return; } Il2CppArrayBase<Renderer> componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true); int num = componentsInChildren?.Length ?? 0; for (int i = 0; i < num && i < 12; i++) { Renderer val6 = componentsInChildren[i]; if (!((Object)(object)val6 == (Object)null)) { bool flag5 = (Object)(object)val4 != (Object)null && ((Component)val6).transform.IsChildOf(val4); ManualLogSource log3 = Plugin.Log2; val5 = new BepInExWarningLogInterpolatedStringHandler(47, 6, ref flag4); if (flag4) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[PlacementPlus][DIAG "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(tag); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" rend["); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(i); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("]="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((Object)val6).name); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" underT="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag5); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" center="); BepInExWarningLogInterpolatedStringHandler obj = val5; Bounds bounds = val6.bounds; ((BepInExLogInterpolatedStringHandler)obj).AppendFormatted<string>(PlacementController.V(((Bounds)(ref bounds)).center)); } log3.LogWarning(val5); } } } catch { } } internal static void DumpPhysState(string tag, Interactable inter) { //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a2: Expected O, but got Unknown //IL_03e0: 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_010a: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) try { if (!PlacementController.Verbose || inter == null) { return; } InteractableController controller = inter.controller; Transform val = (((Object)(object)inter.spawnedObject != (Object)null) ? inter.spawnedObject.transform : null); string text = PlacementController.PresetName(inter); float num = -1f; Vector3 euler; try { if (FrozenMark.TryGetPose(inter, out var pos, out euler)) { num = Vector3.Distance(inter.wPos, pos); } } catch { } bool flag = false; try { flag = FrozenMark.IsFrozen(inter); } catch { } string text2 = "rb=null"; bool flag2 = false; string text3 = "coll=?"; if ((Object)(object)controller != (Object)null) { try { flag2 = ((Behaviour)controller).enabled; } catch { } try { if ((Object)(object)controller.rb != (Object)null) { DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(27, 4); defaultInterpolatedStringHandler.AppendLiteral("rb[kin="); defaultInterpolatedStringHandler.AppendFormatted(controller.rb.isKinematic); defaultInterpolatedStringHandler.AppendLiteral(" grav="); defaultInterpolatedStringHandler.AppendFormatted(controller.rb.useGravity); defaultInterpolatedStringHandler.AppendLiteral(" vel="); euler = controller.rb.velocity; defaultInterpolatedStringHandler.AppendFormatted(((Vector3)(ref euler)).magnitude, "0.##"); defaultInterpolatedStringHandler.AppendLiteral(" detect="); defaultInterpolatedStringHandler.AppendFormatted(controller.rb.detectCollisions); defaultInterpolatedStringHandler.AppendLiteral("]"); text2 = defaultInterpolatedStringHandler.ToStringAndClear(); } } catch { } try { if ((Object)(object)controller.coll != (Object)null) { text3 = $"coll[en={controller.coll.enabled} trig={controller.coll.isTrigger}]"; } } catch { } } bool flag3 = false; int num2 = 0; int num3 = 0; bool flag4 = false; try { flag3 = (Object)(object)inter.spawnedObject != (Object)null && inter.spawnedObject.activeInHierarchy; } catch { } try { if ((Object)(object)val != (Object)null) { Il2CppArrayBase<Renderer> componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true); num3 = componentsInChildren?.Length ?? 0; for (int i = 0; i < num3; i++) { Renderer val2 = componentsInChildren[i]; if (!((Object)(object)val2 == (Object)null)) { if (val2.enabled) { num2++; } if (val2.isVisible) { flag4 = true; } } } } } catch { } string text4 = "room=?"; try { NewNode node = inter.node; NewRoom val3 = ((node != null) ? node.room : null); bool value = (Object)(object)val3 != (Object)null && (Object)(object)Player.Instance != (Object)null && (Object)(object)val3 == (Object)(object)((Actor)Player.Instance).currentRoom; text4 = $"room[{(((Object)(object)val3 != (Object)null) ? val3.name : "null")} isCur={value}]"; } catch { } string text5 = "anc:"; try { Transform val4 = val; int num4 = 0; while ((Object)(object)val4 != (Object)null && num4 < 7) { text5 += $" {((Object)val4).name}={((Component)val4).gameObject.activeSelf}"; val4 = val4.parent; num4++; } } catch { } ManualLogSource log = Plugin.Log2; bool flag5 = default(bool); BepInExWarningLogInterpolatedStringHandler val5 = new BepInExWarningLogInterpolatedStringHandler(110, 15, ref flag5); if (flag5) { ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("[PlacementPlus][WATCH "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(tag); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("] "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" wPos="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(PlacementController.V(inter.wPos)); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("rootPos="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(((Object)(object)val != (Object)null) ? PlacementController.V(val.position) : "-"); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" distFromStored="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<float>(num, "0.###"); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("active="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag3); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" rendersOn="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(num2); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral("/"); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<int>(num3); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" onScreen="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag4); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" frozen="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" ctrlEnabled="); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<bool>(flag2); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text2); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text3); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text4); ((BepInExLogInterpolatedStringHandler)val5).AppendLiteral(" "); ((BepInExLogInterpolatedStringHandler)val5).AppendFormatted<string>(text5); } log.LogWarning(val5); } catch { } } private static string ParentName(Transform tr) { try { return ((Object)(object)tr != (Object)null && (Object)(object)tr.parent != (Object)null) ? ((Object)tr.parent).name : "-"; } catch { return "?"; } } private static string P(Transform tr) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) try { return ((Object)(object)tr != (Object)null) ? PlacementController.V(tr.position) : "-"; } catch { return "?"; } } private static string E(Transform tr) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) try { return ((Object)(object)tr != (Object)null) ? PlacementController.V(tr.eulerAngles) : "-"; } catch { return "?"; } } } internal static class FrozenMark { private const int FrozenVarInt = 7777; internal static bool IsFrozen(Interactable inter) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Invalid comparison between Unknown and I4 try { List<Passed> val = ((inter != null) ? inter.pv : null); if (val == null) { return false; } for (int i = 0; i < val.Count; i++) { if (val[i] != null && (int)val[i].varType == 7777) { return true; } } } catch { } return false; } internal static void SetFrozen(Interactable inter, Vector3 pos, Vector3 euler) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown try { if (inter != null && inter.pv != null) { ClearFrozen(inter); string text = string.Format(CultureInfo.InvariantCulture, "{0},{1},{2},{3},{4},{5}", pos.x, pos.y, pos.z, euler.x, euler.y, euler.z); inter.pv.Add(new Passed((PassedVarType)7777, 0f, text)); } } catch { } } internal static void ClearFrozen(Interactable inter) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Invalid comparison between Unknown and I4 try { List<Passed> val = ((inter != null) ? inter.pv : null); if (val == null) { return; } for (int num = val.Count - 1; num >= 0; num--) { if (val[num] != null && (int)val[num].varType == 7777) { val.RemoveAt(num); } } } catch { } } internal static bool TryGetPose(Interactable inter, out Vector3 pos, out Vector3 euler) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Invalid comparison between Unknown and I4 //IL_0097: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) pos = Vector3.zero; euler = Vector3.zero; try { List<Passed> val = ((inter != null) ? inter.pv : null); if (val == null) { return false; } for (int i = 0; i < val.Count; i++) { Passed val2 = val[i]; if (val2 != null && (int)val2.varType == 7777) { string str = val2.str; if (string.IsNullOrEmpty(str)) { return false; } string[] array = str.Split(','); if (array.Length < 6) { return false; } pos = new Vector3(F(array[0]), F(array[1]), F(array[2])); euler = new Vector3(F(array[3]), F(array[4]), F(array[5])); return true; } } } catch { } return false; } private static float F(string s) { if (!float.TryParse(s, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return 0f; } return result; } } internal static class Gate { internal static bool InPlay() { try { SessionData instance = SessionData.Instance; if ((Object)(object)instance == (Object)null || !instance.play) { return false; } Player instance2 = Player.Instance; if ((Object)(object)instance2 == (Object)null || ((Actor)instance2).isDead) { return false; } if (instance2.computerInteractable != null) { return false; } return true; } catch { return false; } } internal static bool TextOrPopupActive() { try { InterfaceController instance = InterfaceController.Instance; if ((Object)(object)instance != (Object)null && instance.playerTextInputActive) { return true; } PopupMessageController instance2 = PopupMessageController.Instance; if ((Object)(object)instance2 != (Object)null && instance2.active) { return true; } return false; } catch { return true; } } internal static bool VanillaDecorActive() { try { SessionData instance = SessionData.Instance; if ((Object)(object)instance != (Object)null && instance.isDecorEdit) { return true; } PlayerApartmentController instance2 = PlayerApartmentController.Instance; if ((Object)(object)instance2 != (Object)null && (instance2.furniturePlacementMode || instance2.decoratingMode)) { return true; } return false; } catch { return false; } } } internal static class PlacementConfig { internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyCode> ProbeKey; internal static ConfigEntry<bool> WriteFile; internal static ConfigEntry<bool> PrecisionPlacement; internal static ConfigEntry<float> MaxDistance; internal static ConfigEntry<bool> AllowPitchRoll; internal static ConfigEntry<bool> ShowOverlay; internal static ConfigEntry<bool> SurfaceClearance; internal static ConfigEntry<bool> FixtureMoveAway; internal static ConfigEntry<bool> SurfaceHidden; internal static ConfigEntry<string> Allowlist; internal static ConfigEntry<int> Price; internal static ConfigEntry<bool> HideUnplaceable; internal static ConfigEntry<bool> IncludeSecurity; internal static ConfigEntry<bool> CeilingFixItems; internal static ConfigEntry<bool> ApartmentShutters; internal const string DefaultAllowlist = "VintageWallLampBallroom,FlowerBed,FlowerBedCorner,FlowerBedOld,BushBuddleia,BushMossy,Tree,TreeTall,BasketballHoop,PublicCorkboard,MagazineStand,Newsstand,HotelDeskLong,MoldedWaitingSeats,SyncBed,UnderDeskDrawers,LockersX6,HotelKeyRack,WashingMachines,Loudspeaker,TelevisionBillboard,SecurityCamera,SentryGun,ScoutLaser,CCTVTower,TelephoneBooth,AmusementRide,SupermarketFridge,SupermarketFreezer,SupermarketFreezerCorner,SupermarketShelving1,SupermarketShelving2,SupermarketEndShelf,SupermarketEmptyShelfLarge,SupermarketEmptyShelfSmall,SupermarketCounterLeft,SupermarketCounterRight,SupermarketScales,SupermarketSignSynthBeef,SupermarketSignStarch,ShopCounter,FruitStand,FruitStandApples,FruitStandBananas,FruitStandCabbages,NoodleStand,SynthFishStand,BasketStack,OpenSign,24HrSign,HotelWelcomeSign,FlowerBedOldCorner,HospitalBed,WalkInClosetItems,ClosetSlatDoors,TallJunkShelfDouble,IndustrialMachineShort,IndustrialMachineLong,IndustrialMachineLarge,IndustrialMachineCylinder,Loom,CableSpool,PowerBox,BreakerBox,RouterBox,NewspaperBox,ElGenSyncMachine,BurningBarrel,DinerWindowShelf,SecurityDoorDouble,SecurityDoorTriple,TelephoneBox,BathroomScales,TrousersOnFloor,ShirtOnFloor,DressOnFloor,ClothesPile,Graffiti,WallGrimeTop,WallGrimeBottom,LitterDecal,StaticCeilingRotLong,StaticCeilingRotShort,StaticCeilingRotCorner,Bollard,Hydrant,MooringPost"; internal static ConfigEntry<bool> PutBackRestorePose; internal static ConfigEntry<KeyCode> EnterKey; internal static ConfigEntry<KeyCode> NudgeForward; internal static ConfigEntry<KeyCode> NudgeBack; internal static ConfigEntry<KeyCode> NudgeLeft; internal static ConfigEntry<KeyCode> NudgeRight; internal static ConfigEntry<KeyCode> NudgeUp; internal static ConfigEntry<KeyCode> NudgeDown; internal static ConfigEntry<KeyCode> RotateCCW; internal static ConfigEntry<KeyCode> RotateCW; internal static ConfigEntry<KeyCode> CycleAxis; internal static ConfigEntry<KeyCode> Confirm; internal static ConfigEntry<KeyCode> Reset; internal static ConfigEntry<KeyCode> CoarseMod; internal static ConfigEntry<KeyCode> FineMod; internal static ConfigEntry<KeyCode> CopyRot; internal static ConfigEntry<KeyCode> PasteRot; internal static void Init(ConfigFile cfg) { Enabled = cfg.Bind<bool>("Debug", "Enabled", false, "Enable the DecorProbe diagnostic (a dev tool that only reads and logs). Independent of the gameplay features."); ProbeKey = cfg.Bind<KeyCode>("Debug", "ProbeKey", (KeyCode)290, "Key to dump the decor census + item placement modes + ceiling measurements to the log (and a text file)."); WriteFile = cfg.Bind<bool>("Debug", "WriteFile", true, "Also write each probe dump to BepInEx/PlacementPlus/decor_census_*.txt."); PrecisionPlacement = cfg.Bind<bool>("Items", "PrecisionPlacement", true, "Master switch for precision item placement (the enter-key mode that pins a held/carried object so you can move + rotate it freely, then place it)."); MaxDistance = cfg.Bind<float>("Items", "MaxDistance", 10f, "Maximum distance (metres) you can push a pinned object away from yourself."); AllowPitchRoll = cfg.Bind<bool>("Items", "AllowPitchRoll", true, "Allow tilting items on all three axes (pitch/roll as well as yaw). Turn off for yaw-only."); ShowOverlay = cfg.Bind<bool>("Items", "ShowOverlay", true, "Show a small on-screen control hint while in placement mode."); SurfaceClearance = cfg.Bind<bool>("Items", "SurfaceClearance", true, "When placing an item, nudge it out of any wall/floor/ceiling its mesh is sunk into, so long or asymmetric items (silencers, barrels, scopes) can't clip behind a panel and become unpickable. Only pushes along the buried surface; never moves an item sitting clear of a wall, and never treats furniture (racks/shelves/doors) as an obstacle."); FixtureMoveAway = cfg.Bind<bool>("Fixtures", "MoveAway", true, "While placing furniture from the decor menu, use the same move keys (arrows) to push the preview further away or pull it closer/sideways, instead of it being stuck ~1m in front of you. Wall pieces keep their vanilla aim-at-wall behaviour. Height stays game-controlled."); SurfaceHidden = cfg.Bind<bool>("Fixtures", "SurfaceHidden", true, "Add a curated set of normally-hidden fixtures to the decor shop (see Allowlist). Session-only: turning this off and restarting fully reverts."); Allowlist = cfg.Bind<string>("Fixtures", "Allowlist", "VintageWallLampBallroom,FlowerBed,FlowerBedCorner,FlowerBedOld,BushBuddleia,BushMossy,Tree,TreeTall,BasketballHoop,PublicCorkboard,MagazineStand,Newsstand,HotelDeskLong,MoldedWaitingSeats,SyncBed,UnderDeskDrawers,LockersX6,HotelKeyRack,WashingMachines,Loudspeaker,TelevisionBillboard,SecurityCamera,SentryGun,ScoutLaser,CCTVTower,TelephoneBooth,AmusementRide,SupermarketFridge,SupermarketFreezer,SupermarketFreezerCorner,SupermarketShelving1,SupermarketShelving2,SupermarketEndShelf,SupermarketEmptyShelfLarge,SupermarketEmptyShelfSmall,SupermarketCounterLeft,SupermarketCounterRight,SupermarketScales,SupermarketSignSynthBeef,SupermarketSignStarch,ShopCounter,FruitStand,FruitStandApples,FruitStandBananas,FruitStandCabbages,NoodleStand,SynthFishStand,BasketStack,OpenSign,24HrSign,HotelWelcomeSign,FlowerBedOldCorner,HospitalBed,WalkInClosetItems,ClosetSlatDoors,TallJunkShelfDouble,IndustrialMachineShort,IndustrialMachineLong,IndustrialMachineLarge,IndustrialMachineCylinder,Loom,CableSpool,PowerBox,BreakerBox,RouterBox,NewspaperBox,ElGenSyncMachine,BurningBarrel,DinerWindowShelf,SecurityDoorDouble,SecurityDoorTriple,TelephoneBox,BathroomScales,TrousersOnFloor,ShirtOnFloor,DressOnFloor,ClothesPile,Graffiti,WallGrimeTop,WallGrimeBottom,LitterDecal,StaticCeilingRotLong,StaticCeilingRotShort,StaticCeilingRotCorner,Bollard,Hydrant,MooringPost", "Comma-separated FurniturePreset names to surface in the decor shop. Edit freely; run the DecorProbe (F9) to see every available name."); Price = cfg.Bind<int>("Fixtures", "Price", 50, "Flat price applied to every surfaced fixture (you pay for decor in-game)."); HideUnplaceable = cfg.Bind<bool>("Fixtures", "HideUnplaceable", true, "Hide fixtures the apartment decor editor cannot actually place. Ceiling-mounted pieces are blocked by air ducts in almost every apartment tile, so they never place. Turn off to offer them anyway (they place only in rare duct-free spots)."); IncludeSecurity = cfg.Bind<bool>("Fixtures", "IncludeSecurity", true, "Add security fixtures to the decor shop with proper names: security cameras, sentry guns, laser tripwires (ScoutLaser), and alarm switches and sirens. This is separate from the Allowlist and ignores the HideUnplaceable filter for these pieces. The alarm switch (wall) and siren (floor) place like any other fixture; the camera, sentry gun and laser are ceiling-mounted, so the decor editor can only place them on a clear (duct-free) ceiling."); CeilingFixItems = cfg.Bind<bool>("CeilingFix", "Items", true, "Fix player-placed ceiling lights that hang ~1m below the ceiling (the vanilla item-ceiling placement bug). Snaps the fixture's top to the ceiling. Does not touch vanilla room lights."); ApartmentShutters = cfg.Bind<bool>("Security", "ApartmentShutters", true, "Make a breaker box + security doors you place in your OWN apartment work as a self-contained privacy shutter: flipping the breaker's doors switch closes/opens only that apartment's doors, with no whole-floor lockdown. Fully isolated from the floor's security system and never affects vanilla alarms. Only affects fixtures you place yourself."); PutBackRestorePose = cfg.Bind<bool>("PutBack", "RestorePose", true, "When you drop an item near where it was, the game's native put-back returns its position but loses its rotation. This restores the exact placed rotation (and re-freezes display-placed items)."); EnterKey = cfg.Bind<KeyCode>("Keys", "EnterPlacement", (KeyCode)118, "Enter precision placement for the held/carried item (press again to cancel)."); NudgeForward = cfg.Bind<KeyCode>("Keys", "NudgeForward", (KeyCode)273, "Move the pinned object away from you."); NudgeBack = cfg.Bind<KeyCode>("Keys", "NudgeBack", (KeyCode)274, "Move the pinned object toward you."); NudgeLeft = cfg.Bind<KeyCode>("Keys", "NudgeLeft", (KeyCode)276, "Move the pinned object left."); NudgeRight = cfg.Bind<KeyCode>("Keys", "NudgeRight", (KeyCode)275, "Move the pinned object right."); NudgeUp = cfg.Bind<KeyCode>("Keys", "NudgeUp", (KeyCode)280, "Raise the pinned object (Home also works if you rebind)."); NudgeDown = cfg.Bind<KeyCode>("Keys", "NudgeDown", (KeyCode)281, "Lower the pinned object."); RotateCCW = cfg.Bind<KeyCode>("Keys", "RotateCCW", (KeyCode)44, "Rotate the active axis counter-clockwise."); RotateCW = cfg.Bind<KeyCode>("Keys", "RotateCW", (KeyCode)46, "Rotate the active axis clockwise."); CycleAxis = cfg.Bind<KeyCode>("Keys", "CycleAxis", (KeyCode)116, "Cycle the rotation axis (yaw -> pitch -> roll)."); Confirm = cfg.Bind<KeyCode>("Keys", "Confirm", (KeyCode)13, "Place the object statically at the previewed pose."); Reset = cfg.Bind<KeyCode>("Keys", "Reset", (KeyCode)8, "Reset tilt (pitch/roll to 0, yaw to the nearest 45 degrees)."); CoarseMod = cfg.Bind<KeyCode>("Keys", "CoarseModifier", (KeyCode)304, "Hold for larger move/rotate steps."); FineMod = cfg.Bind<KeyCode>("Keys", "FineModifier", (KeyCode)308, "Hold for finer move/rotate steps (Alt, not Ctrl, to avoid the crouch/sprint keys)."); CopyRot = cfg.Bind<KeyCode>("Keys", "CopyRotation", (KeyCode)111, "While placing, store the current rotation/orientation (not position) so you can apply it to other items. (O = copy Orientation; C is the game's crouch key.)"); PasteRot = cfg.Bind<KeyCode>("Keys", "PasteRotation", (KeyCode)112, "While placing, apply the stored rotation/orientation to the current item, for lining several items up the same way."); } } public class PlacementController : MonoBehaviour { private sealed class Watch { public Interactable inter; public int start; public int stage; } internal static bool EntryBInProgress; internal static Interactable PendingDiag; private static bool _clearanceWarned; private static bool _shutterResyncDone; private static bool _frozenHealDone; internal static Vector3? CopiedEuler; private static readonly List<Watch> _watch = new List<Watch>(); internal static float FixtureOffsetX; internal static float FixtureOffsetZ; private static PlacementController _inst; private bool _active; private Interactable _target; private int _targetId = -1; private InteractableController _ctrl; private Vector3 _anchor; private Vector3 _euler; private int _axis; private bool _fromHand; private readonly Dictionary<KeyCode, float> _repeatAt = new Dictionary<KeyCode, float>(); private Player _lastPlayer; private bool _fixtureWas; internal static bool ModeActive { get { if ((Object)(object)_inst != (Object)null) { return _inst._active; } return false; } } internal static bool Verbose => PlacementConfig.Enabled?.Value ?? false; public PlacementController(IntPtr ptr) : base(ptr) { } internal static void WatchAfterPutback(Interactable inter) { try { if (inter != null) { _watch.Add(new Watch { inter = inter, start = Time.frameCount, stage = 0 }); } } catch { } } private static void TickWatch() { try { int frameCount = Time.frameCount; int[] array = new int[3] { 15, 45, 90 }; for (int num = _watch.Count - 1; num >= 0; num--) { Watch watch = _watch[num]; if (watch.inter == null) { _watch.RemoveAt(num); } else { while (watch.stage < array.Length && frameCount - watch.start >= array[watch.stage]) { Diag.DumpPhysState("PB+" + array[watch.stage] + "f", watch.inter); watch.stage++; } if (watch.stage >= array.Length) { _watch.RemoveAt(num); } } } } catch { } } internal static string V(Vector3 v) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) return $"({v.x:0.##},{v.y:0.##},{v.z:0.##})"; } internal static string PresetName(Interactable inter) { try { return (inter != null && (SoCustomComparison)(object)inter.preset != (SoCustomComparison)null) ? ((Object)inter.preset).name : "?"; } catch { return "?"; } } private void Awake() { _inst = this; } private void OnDestroy() { if ((Object)(object)_inst == (Object)(object)this) { _inst = null; } } private void Update() { //IL_019a: Unknown result type (might be due to invalid IL or missing references) try { if (PendingDiag != null) { Interactable pendingDiag = PendingDiag; PendingDiag = null; Diag.DumpAnchors("PUTBACK-NEXTFRAME", pendingDiag); } if (_watch.Count > 0) { TickWatch(); } Player instance = Player.Instance; if ((Object)(object)instance != (Object)(object)_lastPlayer) { _lastPlayer = instance; EntryBInProgress = false; _shutterResyncDone = false; _frozenHealDone = false; if (_active) { Exit(placed: false); } } if (!_shutterResyncDone && (Object)(object)instance != (Object)null) { try { if ((Object)(object)SessionData.Instance != (Object)null && SessionData.Instance.startedGame && Gate.InPlay()) { _shutterResyncDone = true; ApartmentShutters.ResyncAll(); } } catch { _shutterResyncDone = true; } } if (!_frozenHealDone && (Object)(object)instance != (Object)null) { try { if ((Object)(object)SessionData.Instance != (Object)null && SessionData.Instance.startedGame && Gate.InPlay()) { _frozenHealDone = true; HealFrozenSaves(); } } catch { _frozenHealDone = true; } } PlayerApartmentController instance2 = PlayerApartmentController.Instance; if ((Object)(object)instance2 != (Object)null && instance2.furniturePlacementMode) { if (!_fixtureWas) { FixtureOffsetX = 0f; FixtureOffsetZ = 0f; _fixtureWas = true; } if (_active) { Exit(placed: false); } ConfigEntry<bool> fixtureMoveAway = PlacementConfig.FixtureMoveAway; if (fixtureMoveAway == null || fixtureMoveAway.Value) { HandleFixtureNudge(); } return; } _fixtureWas = false; ConfigEntry<bool> precisionPlacement = PlacementConfig.PrecisionPlacement; if (precisionPlacement != null && !precisionPlacement.Value) { if (_active) { Exit(placed: false); } return; } if (!_active) { if (Input.GetKeyDown(PlacementConfig.EnterKey.Value)) { TryEnter(); } return; } if (!Gate.InPlay() || Gate.TextOrPopupActive()) { Exit(placed: false); return; } InteractableController val = (((Object)(object)InteractionController.Instance != (Object)null) ? InteractionController.Instance.carryingObject : null); if ((Object)(object)val == (Object)null || (Object)(object)_ctrl == (Object)null || (Object)(object)val != (Object)(object)_ctrl) { Exit(placed: false); } else { HandleKeys(); } } catch { try { Exit(placed: false); } catch { } } } private void LateUpdate() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!_active || (Object)(object)_ctrl == (Object)null) { return; } try { (((Object)(object)_ctrl.alternativePhysicsParent != (Object)null) ? _ctrl.alternativePhysicsParent : ((Component)_ctrl).transform).SetPositionAndRotation(_anchor, Quaternion.Euler(_euler)); } catch { Exit(placed: false); } } private void TryEnter() { if (Gate.TextOrPopupActive() || Gate.VanillaDecorActive() || !Gate.InPlay()) { return; } InteractionController instance = InteractionController.Instance; if ((Object)(object)instance == (Object)null) { return; } if ((Object)(object)instance.carryingObject != (Object)null) { EnterFromCarry(instance.carryingObject); return; } InventorySlot val = (((Object)(object)BioScreenController.Instance != (Object)null) ? BioScreenController.Instance.selectedSlot : null); Interactable val2 = ((val != null) ? val.GetInteractable() : null); if (val2 != null) { EnterFromHand(val2); } } private void EnterFromCarry(InteractableController co) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) _ctrl = co; _target = co.interactable; _targetId = ((_target != null) ? _target.id : (-1)); _fromHand = false; Transform val = (((Object)(object)co.alternativePhysicsParent != (Object)null) ? co.alternativePhysicsParent : ((Component)co).transform); _anchor = InitialAnchor(co); _euler = val.eulerAngles; _axis = 0; _active = true; Announce(); } private void EnterFromHand(Interactable held) { //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) try { InventorySlot selectedSlot = BioScreenController.Instance.selectedSlot; EntryBInProgress = true; bool flag = false; try { flag = held.IsSpawnPositionRelevent(); } catch { } try { try { held.SetSpawnPositionRelevent(false); } catch { } FirstPersonItemController.Instance.EmptySlot(selectedSlot, false, false, false, false); } finally { EntryBInProgress = false; try { if (flag) { held.SetSpawnPositionRelevent(true); } } catch { } } ActionController.Instance.PickUp(held, ((Actor)Player.Instance).currentNode, (Actor)(object)Player.Instance); try { held.SetPhysicsPickupState(true, (Actor)(object)Player.Instance, true, false); } catch { } InteractableController carryingObject = InteractionController.Instance.carryingObject; if ((Object)(object)carryingObject == (Object)null || carryingObject.interactable == null) { Plugin.Log2.LogWarning((object)"[PlacementPlus] could not convert the held item to a carried object; returning it to the hand."); try { FirstPersonItemController.Instance.PickUpItem(held, true, false, true, true, true); return; } catch { return; } } _ctrl = carryingObject; _target = carryingObject.interactable; _targetId = _target.id; _fromHand = true; _anchor = InitialAnchor(carryingObject); Transform val = (((Object)(object)carryingObject.alternativePhysicsParent != (Object)null) ? carryingObject.alternativePhysicsParent : ((Component)carryingObject).transform); _euler = val.eulerAngles; _axis = 0; _active = true; Announce(); } catch (Exception ex) { ManualLogSource log = Plugin.Log2; bool flag2 = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(40, 1, ref flag2); if (flag2) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[PlacementPlus] enter-from-hand failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message); } log.LogWarning(val2); } } private void HandleKeys() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) float num = 0.1f; float num2 = 15f; bool key = Input.GetKey(PlacementConfig.CoarseMod.Value); bool key2 = Input.GetKey(PlacementConfig.FineMod.Value); if (key) { num = 0.3f; num2 = 45f; } else if (key2) { num = 0.01f; num2 = 1f; } Vector3 val = FlatForward(); Vector3 val2 = FlatRight(); if (Repeat(PlacementConfig.NudgeForward.Value)) { MoveAnchor(val * num); } if (Repeat(PlacementConfig.NudgeBack.Value)) { MoveAnchor(-val * num); } if (Repeat(PlacementConfig.NudgeRight.Value)) { MoveAnchor(val2 * num); } if (Repeat(PlacementConfig.NudgeLeft.Value)) { MoveAnchor(-val2 * num); } if (Repeat(PlacementConfig.NudgeUp.Value)) { MoveAnchor(Vector3.up * num); } if (Repeat(PlacementConfig.NudgeDown.Value)) { MoveAnchor(Vector3.down * num); } if (Repeat(PlacementConfig.RotateCCW.Value)) { RotateAxis(0f - num2); } if (Repeat(PlacementConfig.RotateCW.Value)) { RotateAxis(num2); } if (Input.GetKeyDown(PlacementConfig.CycleAxis.Value)) { _axis = (_axis + 1) % 3; ConfigEntry<bool> allowPitchRoll = PlacementConfig.AllowPitchRoll; if (allowPitchRoll != null && !allowPitchRoll.Value) { _axis = 0; } Plugin.Log2.LogInfo((object)("[PlacementPlus] rotation axis: " + AxisName())); } if (Input.GetKeyDown(PlacementConfig.Reset.Value)) { _euler = new Vector3(0f, Mathf.Round(_euler.y / 45f) * 45f, 0f); } if (Input.GetKeyDown(PlacementConfig.CopyRot.Value)) { CopiedEuler = _euler; Plugin.Log2.LogInfo((object)("[PlacementPlus] copied rotation " + V(_euler))); } if (Input.GetKeyDown(PlacementConfig.PasteRot.Value) && CopiedEuler.HasValue) { _euler = CopiedEuler.Value; Plugin.Log2.LogInfo((object)("[PlacementPlus] pasted rotation " + V(_euler))); } if (Input.GetKeyDown(PlacementConfig.Confirm.Value)) { Confirm(); } else if (Input.GetKeyDown(PlacementConfig.EnterKey.Value)) { Exit(placed: false); } } private void HandleFixtureNudge() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) if (!Gate.TextOrPopupActive()) { float num = (Input.GetKey(PlacementConfig.CoarseMod.Value) ? 0.9f : 0.3f); if (Repeat(PlacementConfig.NudgeForward.Value)) { FixtureOffsetZ += num; } if (Repeat(PlacementConfig.NudgeBack.Value)) { FixtureOffsetZ -= num; } if (Repeat(PlacementConfig.NudgeRight.Value)) { FixtureOffsetX += num; } if (Repeat(PlacementConfig.NudgeLeft.Value)) { FixtureOffsetX -= num; } if (Input.GetKeyDown(PlacementConfig.Reset.Value)) { FixtureOffsetX = 0f; FixtureOffsetZ = 0f; } float num2 = Mathf.Max(1f, PlacementConfig.MaxDistance?.Value ?? 10f); FixtureOffsetZ = Mathf.Clamp(FixtureOffsetZ, -0.9f, num2); FixtureOffsetX = Mathf.Clamp(FixtureOffsetX, 0f - num2, num2); } } private void MoveAnchor(Vector3 delta) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) _anchor += delta; try { Vector3 position = ((Component)Player.Instance.cam).transform.position; float num = Mathf.Max(1f, PlacementConfig.MaxDistance?.Value ?? 10f); Vector3 val = _anchor - position; if (((Vector3)(ref val)).magnitude > num) { _anchor = position + ((Vector3)(ref val)).normalized * num; } } catch { } } private void RotateAxis(float deg) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) Vector3 euler = _euler; bool flag = PlacementConfig.AllowPitchRoll?.Value ?? true; if (_axis == 0 || !flag) { euler.y += deg; } else if (_axis == 1) { euler.x += deg; } else { euler.z += deg; } _euler = euler; } private void Confirm() { //IL_0362: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_0302: Unknown result type (might be due to invalid IL or missing references) //IL_0320: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_ctrl == (Object)null || _target == null) { Exit(placed: false); return; } bool flag = default(bool); try { Transform val = (((Object)(object)_ctrl.alternativePhysicsParent != (Object)null) ? _ctrl.alternativePhysicsParent : ((Component)_ctrl).transform); Quaternion val2 = Quaternion.Euler(_euler); val.SetPositionAndRotation(_anchor, val2); ConfigEntry<bool> surfaceClearance = PlacementConfig.SurfaceClearance; if (surfaceClearance == null || surfaceClearance.Value) { Vector3 val3 = ComputeClearance(_ctrl, _anchor); if (val3 != Vector3.zero) { _anchor += val3; val.SetPositionAndRotation(_anchor, val2); if (Verbose) { ManualLogSource log = Plugin.Log2; BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(49, 3, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[PlacementPlus] surface-clearance lifted "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(PresetName(_target)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" by "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(V(val3)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" -> "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(V(_anchor)); } log.LogWarning(val4); } } } ActionController.Instance.PutDown(_target, ((Actor)Player.Instance).currentNode, (Actor)(object)Player.Instance); val.SetPositionAndRotation(_anchor, val2); try { if ((Object)(object)_ctrl.rb != (Object)null) { _ctrl.rb.velocity = Vector3.zero; _ctrl.rb.angularVelocity = Vector3.zero; } } catch { } _ctrl.SetPhysics(false, (Actor)null); ((Behaviour)_ctrl).enabled = false; _target.MoveInteractable(_anchor, _euler, true); _target.SetSpawnPositionRelevent(true); val.SetPositionAndRotation(_anchor, val2); FrozenMark.SetFrozen(_target, _anchor, _euler); try { _target.force = true; } catch { } try { _target.MarkAsTrash(false, false, 0f); } catch { } if (Verbose) { Vector3 v = (((Object)(object)_ctrl.alternativePhysicsParent != (Object)null) ? _ctrl.alternativePhysicsParent.position : ((Component)_ctrl).transform.position); ManualLogSource log2 = Plugin.Log2; BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(64, 6, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[PlacementPlus] FROZE "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(PresetName(_target)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(": anchor="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(V(_anchor)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" euler="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(V(_euler)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" ctrlPos="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(V(((Component)_ctrl).transform.position)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" altParent="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(V(v)); ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral(" wPos="); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(V(_target.wPos)); } log2.LogWarning(val4); } Diag.DumpAnchors("FROZE", _target); Plugin.Log2.LogInfo((object)"[PlacementPlus] placed item at the previewed pose."); } catch (Exception ex) { ManualLogSource log3 = Plugin.Log2; BepInExWarningLogInterpolatedStringHandler val4 = new BepInExWarningLogInterpolatedStringHandler(32, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val4).AppendLiteral("[PlacementPlus] confirm failed: "); ((BepInExLogInterpolatedStringHandler)val4).AppendFormatted<string>(ex.Message); } log3.LogWarning(val4); } Exit(placed: true); } private static void HealFrozenSaves() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Expected O, but got Unknown CityData instance = CityData.Instance; List<Interactable> val = (((Object)(object)instance != (Object)null) ? instance.interactableDirectory : null); if (val == null) { return; } int num = 0; for (int i = 0; i < val.Count; i++) { Interactable val2; try { val2 = val[i]; } catch { continue; } if (val2 == null) { continue; } try { if (FrozenMark.IsFrozen(val2)) { if (!val2.force) { val2.force = true; num++; } if (val2.mtr >= 0f) { val2.MarkAsTrash(false, false, 0f); } } } catch { } } if (num > 0) { ManualLogSource log = Plugin.Log2; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val3 = new BepInExWarningLogInterpolatedStringHandler(87, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[PlacementPlus] save-eligibility heal: re-forced "); ((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<int>(num); ((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" frozen item(s) from an earlier build."); } log.LogWarning(val3); } } private void Exit(bool placed) { //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown bool fromHand = _fromHand; Interactable target = _target; _active = false; _target = null; _ctrl = null; _fromHand = false; _axis = 0; _targetId = -1; if (!(!placed && fromHand) || target == null) { return; } try { InteractableController val = (((Object)(object)InteractionController.Instance != (Object)null) ? InteractionController.Instance.carryingObject : null); if ((Object)(object)val != (Object)null) { val.DropThis(false); } FirstPersonItemController.Instance.PickUpItem(target, true, false, true, true, true); } catch (Exception ex) { ManualLogSource log = Plugin.Log2; bool flag = default(bool); BepInExWarningLogInterpolatedStringHandler val2 = new BepInExWarningLogInterpolatedStringHandler(39, 1, ref flag); if (flag) { ((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("[PlacementPlus] return-to-hand failed: "); ((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message); } log.LogWarning(val2); } } private bool Repeat(KeyCode k) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) float unscaledTime = Time.unscaledTime; if (Input.GetKeyDown(k)) { _repeatAt[k] = unscaledTime + 0.35f; return true; } if (Input.GetKey(k)) { if (!_repeatAt.TryGetValue(k, out var value)) { value = unscaledTime + 0.35f; } if (unscaledTime >= value) { _repeatAt[k] = unscaledTime + 0.05f; return true; } } return false; } private static Vector3 FlatForward() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = ((Component)Player.Instance.cam).transform.forward; forward.y = 0f; if (!(((Vector3)(ref forward)).sqrMagnitude > 0.0001f)) { return Vector3.forward; } return ((Vector3)(ref forward)).normalized; } private static Vector3 FlatRight() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 right = ((Component)Player.Instance.cam).transform.right; right.y = 0f; if (!(((Vector3)(ref right)).sqrMagnitude > 0.0001f)) { return Vector3.right; } return ((Vector3)(ref right)).normalized; } private static Vector3 InitialAnchor(InteractableController co) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) try { Transform transform = ((Component)Player.Instance.cam).transform; RaycastHit val = default(RaycastHit); if (Physics.Raycast(transform.position, transform.forward, ref val, 4f, Toolbox.Instance.heldObjectsObjectsLayerMask)) { float num = 0.05f; try { num = Mathf.Max(0.05f, co.colliderExtents.y); } catch { } return ((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * num; } return transform.position + transform.forward * 1.5f; } catch { try { Transform transform2 = ((Component)Player.Instance.cam).transform; return transform2.position + transform2.forward * 1.5f; } catch { return Vector3.zero; } } } private Vector3 ComputeClearance(InteractableController ctrl, Vector3 anchor) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_028a: 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_0290: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: 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_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02bd: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0327: Unknown result type (might be due to invalid IL or missing references) //IL_0336: Unknown result type (might be due to invalid IL or missing references) //IL_033b: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Unknown result type (might be