Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of BuildCameraPlus v1.6.2
BuildCameraPlus.dll
Decompiled 9 hours agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyVersion("0.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 BuildCameraPlus { [HarmonyPatch] internal static class AreaDestroy { private const float Touch = 0.1f; private static ConfigEntry<bool> enabled; private static ConfigEntry<bool> includeWorld; private static ConfigEntry<KeyCode> holdKey; private static ConfigEntry<int> maxPieces; private static int mask; private static readonly FieldRef<Player, Piece> Hovering = AccessTools.FieldRefAccess<Player, Piece>("m_hoveringPiece"); internal static void Bind(ConfigFile c) { enabled = Cfg.Add(c, "07 Area Destroy", "Enabled", value: false, "Hold the key below and remove (middle mouse button) to remove a whole structure: the piece you aim at and everything connected to it."); holdKey = Cfg.Add<KeyCode>(c, "07 Area Destroy", "HoldKey", (KeyCode)91, "Keep this key held while you remove, so a whole structure is never removed by accident."); maxPieces = Cfg.Add(c, "07 Area Destroy", "MaxPieces", 300, "The most pieces one removal may take, a safety limit.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 2000)); includeWorld = Cfg.Add(c, "07 Area Destroy", "IncludeWorldStructures", value: true, "Also remove pieces of structures that were generated with the world (villages, ruins) even where the game normally does not let you."); } internal static bool Held() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (Plugin.modEnabled.Value && enabled.Value) { return ZInput.GetKey(holdKey.Value, false); } return false; } [HarmonyPatch(typeof(Player), "RemovePiece")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool Structure(Player __instance, ref bool __result) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer || !Held()) { return true; } __result = Destroy(__instance); return false; } private static bool Destroy(Player p) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) Piece val = Hovering.Invoke(p); if ((Object)(object)val == (Object)null) { return false; } WearNTear component = ((Component)val).GetComponent<WearNTear>(); if ((Object)(object)component == (Object)null) { return false; } if (mask == 0) { mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "vehicle" }); } List<WearNTear> list = new List<WearNTear> { component }; HashSet<WearNTear> hashSet = new HashSet<WearNTear> { component }; for (int i = 0; i < list.Count; i++) { if (list.Count >= maxPieces.Value) { break; } Collider[] componentsInChildren = ((Component)list[i]).GetComponentsInChildren<Collider>(); foreach (Collider val2 in componentsInChildren) { if (val2.isTrigger) { continue; } Bounds bounds = val2.bounds; Collider[] array = Physics.OverlapBox(((Bounds)(ref bounds)).center, ((Bounds)(ref bounds)).extents + Vector3.one * 0.1f, Quaternion.identity, mask); for (int k = 0; k < array.Length; k++) { WearNTear componentInParent = ((Component)array[k]).GetComponentInParent<WearNTear>(); if ((Object)(object)componentInParent != (Object)null && hashSet.Add(componentInParent) && list.Count < maxPieces.Value) { list.Add(componentInParent); } } } } int num = 0; foreach (WearNTear item in list) { if ((Object)(object)item == (Object)null) { continue; } Piece component2 = ((Component)item).GetComponent<Piece>(); ZNetView component3 = ((Component)item).GetComponent<ZNetView>(); if (!((Object)(object)component2 == (Object)null) && !((Object)(object)component3 == (Object)null) && component3.IsValid() && (component2.m_canBeRemoved || (includeWorld.Value && component2.GetCreator() == 0L)) && PrivateArea.CheckAccess(((Component)item).transform.position, 0f, true, false) && (includeWorld.Value || !Location.IsInsideNoBuildLocation(((Component)item).transform.position)) && component2.CanBeRemoved()) { IRemoved component4 = ((Component)component2).GetComponent<IRemoved>(); if (component4 != null) { component4.OnRemoved(); } item.Remove(false); num++; } } if (num > 0) { ((Character)p).Message((MessageType)1, "Removed structure: " + num + " pieces", 0, (Sprite)null, false); } return num > 0; } } [HarmonyPatch] internal static class Cam { private const float GroundClearance = 0.5f; internal static bool Active; private static bool carry; private static Vector3 pos; private static Vector3 start; private static float yaw; private static float pitch; private static Vector3? stationPoint; private static float vanillaPickup = -1f; private static readonly List<Renderer> hidden = new List<Renderer>(); private static readonly List<Collider> disabled = new List<Collider>(); private static readonly FieldRef<Character, float> MaxAir = AccessTools.FieldRefAccess<Character, float>("m_maxAirAltitude"); private static readonly FieldRef<Player, int> PlaceMask = AccessTools.FieldRefAccess<Player, int>("m_placeRayMask"); private static readonly FieldRef<Player, int> PlaceWaterMask = AccessTools.FieldRefAccess<Player, int>("m_placeWaterRayMask"); private static readonly FieldRef<Player, int> RemoveMask = AccessTools.FieldRefAccess<Player, int>("m_removeRayMask"); private static readonly FieldRef<Player, GameObject> Ghost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost"); private static readonly FieldRef<Player, Piece> Hovering = AccessTools.FieldRefAccess<Player, Piece>("m_hoveringPiece"); private static readonly FieldRef<float> TakeInputDelay = AccessTools.StaticFieldRefAccess<float>(AccessTools.Field(typeof(PlayerController), "takeInputDelay")); private static readonly FieldRef<GameCamera, AudioListener> Listener = AccessTools.FieldRefAccess<GameCamera, AudioListener>("m_listner"); private static readonly KeyCode[][] Groups = new KeyCode[3][] { (KeyCode[])(object)new KeyCode[2] { (KeyCode)304, (KeyCode)303 }, (KeyCode[])(object)new KeyCode[2] { (KeyCode)306, (KeyCode)305 }, (KeyCode[])(object)new KeyCode[2] { (KeyCode)308, (KeyCode)307 } }; internal static void Tick() { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if (Active && (!Plugin.cameraEnabled.Value || !CanStay(localPlayer))) { Exit(null); return; } if (Active && carry && (Object)(object)localPlayer != (Object)null) { if (vanillaPickup < 0f) { vanillaPickup = localPlayer.m_autoPickupRange; } localPlayer.m_autoPickupRange = Mathf.Max(vanillaPickup, Plugin.pickupRadius.Value); } if (Plugin.cameraEnabled.Value && !Typing()) { if (Pressed(Plugin.teleportKey.Value)) { Toggle(localPlayer, withCharacter: true); } else if (Pressed(Plugin.freeKey.Value)) { Toggle(localPlayer, withCharacter: false); } } } private static void Toggle(Player p, bool withCharacter) { //IL_0045: 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_0050: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) if (Active) { Exit("Build camera off"); } else { if ((Object)(object)GameCamera.instance == (Object)null || GameCamera.InFreeFly()) { return; } if (!Plugin.HoldsCameraTool(p)) { Message("Equip the Builder's Hammer to use the build camera"); return; } Transform transform = ((Component)GameCamera.instance).transform; pos = transform.position; yaw = transform.eulerAngles.y; float x = transform.eulerAngles.x; pitch = Mathf.Clamp((x > 180f) ? (x - 360f) : x, -89f, 89f); start = ((Component)p).transform.position; carry = withCharacter; if (carry) { Hide(p); } Active = true; Message(carry ? "Build camera on (character flies along)" : "Build camera on"); } } internal static void Exit(string message) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (Active) { Active = false; Player localPlayer = Player.m_localPlayer; if (carry && (Object)(object)localPlayer != (Object)null) { Show(); Teleport(localPlayer, start); MaxAir.Invoke((Character)(object)localPlayer) = start.y; } if ((Object)(object)localPlayer != (Object)null && vanillaPickup >= 0f) { localPlayer.m_autoPickupRange = vanillaPickup; } vanillaPickup = -1f; carry = false; if (message != null) { Message(message); } } } private static bool CanStay(Player p) { if ((Object)(object)p != (Object)null && (Object)(object)GameCamera.instance != (Object)null && !GameCamera.InFreeFly() && Plugin.HoldsCameraTool(p) && !((Character)p).IsDead() && !((Character)p).IsTeleporting() && !((Character)p).IsAttached()) { return !((Character)p).InCutscene(); } return false; } private static void Message(string text) { if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null, false); } } internal static bool Typing() { if ((!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()) && !Console.IsVisible() && !TextInput.IsVisible() && !Menu.IsVisible()) { if ((Object)(object)Hud.instance != (Object)null) { return Hud.instance.m_buildUi.SearchFieldFocused; } return false; } return true; } internal static bool Pressed(KeyboardShortcut s) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) if ((int)((KeyboardShortcut)(ref s)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref s)).MainKey, false)) { return false; } List<KeyCode> source = ((KeyboardShortcut)(ref s)).Modifiers.ToList(); int i; for (i = 0; i < Groups.Length; i++) { bool flag = source.Any((KeyCode m) => Groups[i].Contains(m)); bool flag2 = ZInput.GetKey(Groups[i][0], false) || ZInput.GetKey(Groups[i][1], false); if (flag && !flag2) { return false; } if (!flag && flag2 && i > 0) { return false; } } return true; } private static bool InputFree() { if (!Typing() && !InventoryGui.IsVisible() && !Minimap.IsOpen() && !StoreGui.IsVisible() && !Hud.IsPieceSelectionVisible()) { return !Hud.InRadial(); } return false; } private static void Drive(GameCamera cam, float dt) { //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_006e: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_026c: 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_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: 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_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: 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_01c6: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return; } if (InputFree()) { Vector2 val = ZInput.GetMouseDelta() * PlayerController.m_mouseSens * Plugin.mouseSensitivity.Value; if (PlayerController.m_invertMouse) { val.y = 0f - val.y; } yaw = Mathf.Repeat(yaw + val.x, 360f); pitch = Mathf.Clamp(pitch - val.y, -89f, 89f); Vector3 zero = Vector3.zero; if (ZInput.GetButton("Forward")) { zero.z += 1f; } if (ZInput.GetButton("Backward")) { zero.z -= 1f; } if (ZInput.GetButton("Right")) { zero.x += 1f; } if (ZInput.GetButton("Left")) { zero.x -= 1f; } if (ZInput.GetButton("Jump")) { zero.y += 1f; } if (ZInput.GetButton("Crouch")) { zero.y -= 1f; } if (((Vector3)(ref zero)).sqrMagnitude > 1f) { ((Vector3)(ref zero)).Normalize(); } float num = Plugin.speed.Value * (ZInput.GetButton("Run") ? Plugin.runMultiplier.Value : 1f); Quaternion val2 = (Plugin.flatMovement.Value ? Quaternion.Euler(0f, yaw, 0f) : Quaternion.Euler(pitch, yaw, 0f)); pos += (val2 * new Vector3(zero.x, 0f, zero.z) + Vector3.up * zero.y) * (num * dt); } Clamp(); ((Component)cam).transform.position = pos; ((Component)cam).transform.rotation = Quaternion.Euler(pitch, yaw, 0f); Camera component = ((Component)cam).GetComponent<Camera>(); if ((Object)(object)component != (Object)null && component.nearClipPlane != cam.m_nearClipPlaneMin) { component.nearClipPlane = cam.m_nearClipPlaneMin; } if (carry && (Object)(object)((Character)localPlayer).m_eye != (Object)null) { Teleport(localPlayer, pos - (((Character)localPlayer).m_eye.position - ((Component)localPlayer).transform.position)); MaxAir.Invoke((Character)(object)localPlayer) = ((Component)localPlayer).transform.position.y; if (Plugin.invincible.Value && ((Character)localPlayer).GetHealth() < ((Character)localPlayer).GetMaxHealth()) { ((Character)localPlayer).SetHealth(((Character)localPlayer).GetMaxHealth()); } } } private static void Clamp() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) Vector3 val = pos - start; float value = Plugin.maxDistance.Value; if (((Vector3)(ref val)).sqrMagnitude > value * value) { pos = start + ((Vector3)(ref val)).normalized * value; } float num = default(float); if (Plugin.stayAboveGround.Value && (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(pos, ref num) && pos.y < num + 0.5f) { pos.y = num + 0.5f; } } private static void Teleport(Player p, Vector3 to) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) ((Component)p).transform.position = to; Rigidbody component = ((Component)p).GetComponent<Rigidbody>(); if ((Object)(object)component != (Object)null) { component.position = to; component.linearVelocity = Vector3.zero; component.useGravity = false; } } private static void Hide(Player p) { hidden.Clear(); disabled.Clear(); Renderer[] componentsInChildren = ((Component)p).GetComponentsInChildren<Renderer>(); foreach (Renderer val in componentsInChildren) { if (val.enabled) { val.enabled = false; hidden.Add(val); } } Collider[] componentsInChildren2 = ((Component)p).GetComponentsInChildren<Collider>(); foreach (Collider val2 in componentsInChildren2) { if (val2.enabled && !val2.isTrigger) { val2.enabled = false; disabled.Add(val2); } } } private static void Show() { foreach (Renderer item in hidden) { if ((Object)(object)item != (Object)null) { item.enabled = true; } } foreach (Collider item2 in disabled) { if ((Object)(object)item2 != (Object)null) { item2.enabled = true; } } hidden.Clear(); disabled.Clear(); } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] [HarmonyPrefix] private static bool CameraPrefix(GameCamera __instance, float dt) { if (!Active) { return true; } Drive(__instance, dt); return false; } [HarmonyPatch(typeof(GameCamera), "UpdateListner")] [HarmonyPrefix] private static bool ListenerPrefix(GameCamera __instance) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!Active) { return true; } AudioListener val = Listener.Invoke(__instance); if ((Object)(object)val != (Object)null) { ((Component)val).transform.localPosition = Vector3.zero; } return false; } private static bool IsLocal(PlayerController c) { Player component = ((Component)c).GetComponent<Player>(); if ((Object)(object)component != (Object)null) { return (Object)(object)component == (Object)(object)Player.m_localPlayer; } return false; } [HarmonyPatch(typeof(PlayerController), "FixedUpdate")] [HarmonyPrefix] private static bool ControllerFixed(PlayerController __instance) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) if (!Active || !IsLocal(__instance)) { return true; } TakeInputDelay.Invoke() = Mathf.Max(0f, TakeInputDelay.Invoke() - Time.deltaTime); Player.m_localPlayer.SetControls(Vector3.zero, false, false, false, false, false, false, false, false, false, false, false); return false; } [HarmonyPatch(typeof(PlayerController), "LateUpdate")] [HarmonyPrefix] private static bool ControllerLate(PlayerController __instance) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!Active || !IsLocal(__instance)) { return true; } Player.m_localPlayer.SetMouseLook(Vector2.zero); return false; } [HarmonyPatch(typeof(Player), "OnDamaged")] [HarmonyPostfix] private static void Damaged(Player __instance) { if (Active && (Object)(object)__instance == (Object)(object)Player.m_localPlayer && Plugin.exitWhenHit.Value) { Exit("You were hit: camera back to your character"); } } private static bool Applies(Player p) { if (Active && (Object)(object)p != (Object)null && (Object)(object)p == (Object)(object)Player.m_localPlayer) { return (Object)(object)GameCamera.instance != (Object)null; } return false; } private static bool CameraHitWithin(int mask, float reach) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)GameCamera.instance).transform; RaycastHit val = default(RaycastHit); if (Physics.Raycast(transform.position, transform.forward, ref val, 50f, mask)) { return ((RaycastHit)(ref val)).distance <= reach; } return false; } private static float Lift(Player p) { float maxPlaceDistance = p.m_maxPlaceDistance; p.m_maxPlaceDistance = 1000f; return maxPlaceDistance; } private static void Restore(Player p, float old) { if (old >= 0f) { p.m_maxPlaceDistance = old; } } [HarmonyPatch(typeof(Player), "PieceRayTest")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool PieceRayPrefix(Player __instance, bool water, ref Vector3 point, ref Vector3 normal, ref Piece piece, ref Heightmap heightmap, ref Collider waterSurface, ref bool __result, out float __state) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0081: 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) __state = -1f; if (!Applies(__instance)) { return true; } float num = Plugin.placementReach.Value; GameObject val = Ghost.Invoke(__instance); Piece val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null); if ((Object)(object)val2 != (Object)null) { num += (float)val2.m_extraPlacementDistance; } if (!CameraHitWithin(water ? PlaceWaterMask.Invoke(__instance) : PlaceMask.Invoke(__instance), num)) { point = Vector3.zero; normal = Vector3.zero; piece = null; heightmap = null; waterSurface = null; __result = false; return false; } __state = Lift(__instance); return true; } [HarmonyPatch(typeof(Player), "PieceRayTest")] [HarmonyFinalizer] private static void PieceRayFinalizer(Player __instance, float __state) { Restore(__instance, __state); } [HarmonyPatch(typeof(Player), "UpdateWearNTearHover")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool HoverPrefix(Player __instance, out float __state) { __state = -1f; if (!Applies(__instance) || !((Character)__instance).InPlaceMode()) { return true; } if (!CameraHitWithin(RemoveMask.Invoke(__instance), Plugin.placementReach.Value)) { Hovering.Invoke(__instance) = null; return false; } __state = Lift(__instance); return true; } [HarmonyPatch(typeof(Player), "UpdateWearNTearHover")] [HarmonyFinalizer] private static void HoverFinalizer(Player __instance, float __state) { Restore(__instance, __state); } [HarmonyPatch(typeof(Player), "RemovePiece")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool RemovePrefix(Player __instance, ref bool __result, out float __state) { return RemoveLike(__instance, ref __result, out __state); } [HarmonyPatch(typeof(Player), "RemovePiece")] [HarmonyFinalizer] private static void RemoveFinalizer(Player __instance, float __state) { Restore(__instance, __state); } [HarmonyPatch(typeof(Player), "CopyPiece")] [HarmonyPrefix] [HarmonyPriority(800)] private static bool CopyPrefix(Player __instance, ref bool __result, out float __state) { return RemoveLike(__instance, ref __result, out __state); } [HarmonyPatch(typeof(Player), "CopyPiece")] [HarmonyFinalizer] private static void CopyFinalizer(Player __instance, float __state) { Restore(__instance, __state); } private static bool RemoveLike(Player p, ref bool result, out float state) { state = -1f; if (!Applies(p)) { return true; } if (!CameraHitWithin(RemoveMask.Invoke(p), Plugin.placementReach.Value)) { result = false; return false; } state = Lift(p); return true; } private static bool Immortal(Character c) { if (Active && carry && Plugin.invincible.Value && (Object)(object)c != (Object)null) { return (Object)(object)c == (Object)(object)Player.m_localPlayer; } return false; } [HarmonyPatch(typeof(Character), "ApplyDamage")] [HarmonyPrefix] private static bool NoDamage(Character __instance) { return !Immortal(__instance); } [HarmonyPatch(typeof(Character), "RPC_Damage")] [HarmonyPrefix] private static bool NoRpcDamage(Character __instance) { return !Immortal(__instance); } private static bool StationNear(Player p) { if (Applies(p)) { return Plugin.stationNearPiece.Value; } return false; } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyPrefix] private static void RequirementsPrefix(Player __instance, RequirementMode mode) { //IL_0000: 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) if ((int)mode == 0 && StationNear(__instance)) { GameObject val = Ghost.Invoke(__instance); if ((Object)(object)val != (Object)null) { stationPoint = val.transform.position; } } } [HarmonyPatch(typeof(Player), "HaveRequirements", new Type[] { typeof(Piece), typeof(RequirementMode) })] [HarmonyFinalizer] private static void RequirementsFinalizer() { stationPoint = null; } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] [HarmonyPrefix] [HarmonyPriority(800)] private static void CanRemovePrefix(Player __instance, Piece piece) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)piece != (Object)null && StationNear(__instance)) { stationPoint = ((Component)piece).transform.position; } } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] [HarmonyFinalizer] private static void CanRemoveFinalizer() { stationPoint = null; } [HarmonyPatch(typeof(CraftingStation), "HaveBuildStationInRange")] [HarmonyPrefix] private static void StationPrefix(ref Vector3 point) { //IL_0012: 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) if (stationPoint.HasValue) { point = stationPoint.Value; } } } internal sealed class ConfigurationManagerAttributes { public int? Order; } internal static class Cfg { private static int order = 10000; internal static ConfigEntry<T> Add<T>(ConfigFile c, string section, string key, T value, string description, AcceptableValueBase range = null) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_003d: Expected O, but got Unknown return c.Bind<T>(new ConfigDefinition(section, key), value, new ConfigDescription(description, range, new object[1] { new ConfigurationManagerAttributes { Order = order-- } })); } } [HarmonyPatch] internal static class Growth { private const string BonusKey = "BuildCameraPlus_bonus"; private static readonly FieldRef<Plant, ZNetView> View = AccessTools.FieldRefAccess<Plant, ZNetView>("m_nview"); private static readonly Dictionary<Plant, float> lastSeen = new Dictionary<Plant, float>(); private static readonly MethodInfo CheckBiome = AccessTools.Method(typeof(Beehive), "CheckBiome", (Type[])null, (Type[])null); private static readonly MethodInfo HaveFreeSpace = AccessTools.Method(typeof(Beehive), "HaveFreeSpace", (Type[])null, (Type[])null); private static bool On { get { if (Plugin.modEnabled.Value) { return Plugin.growthEnabled.Value; } return false; } } internal static float Speed(Plant plant) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) float num = 1f; if (EnvMan.IsWet()) { num *= Plugin.rainMultiplier.Value; } if (BeesNear(((Component)plant).transform.position)) { num *= Plugin.beeMultiplier.Value; } return num; } private static bool BeesNear(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Collider[] array = Physics.OverlapSphere(pos, Plugin.beeRadius.Value); for (int i = 0; i < array.Length; i++) { Beehive componentInParent = ((Component)array[i]).GetComponentInParent<Beehive>(); if ((Object)(object)componentInParent != (Object)null && (bool)CheckBiome.Invoke(componentInParent, null) && (bool)HaveFreeSpace.Invoke(componentInParent, null)) { return true; } } return false; } [HarmonyPatch(typeof(Plant), "SUpdate")] [HarmonyPrefix] private static void Earn(Plant __instance, float time) { if (!On) { return; } ZNetView val = View.Invoke(__instance); if ((Object)(object)val == (Object)null || !val.IsValid() || !val.IsOwner()) { return; } float value; bool num = lastSeen.TryGetValue(__instance, out value); lastSeen[__instance] = time; if (!num) { return; } float num2 = time - value; if (!(num2 <= 0f) && !(num2 > 60f)) { float num3 = Speed(__instance); if (!(num3 <= 1f)) { ZDO zDO = val.GetZDO(); zDO.Set("BuildCameraPlus_bonus", zDO.GetFloat("BuildCameraPlus_bonus", 0f) + num2 * (num3 - 1f)); } } } [HarmonyPatch(typeof(Plant), "TimeSincePlanted")] [HarmonyPostfix] private static void AddBonus(Plant __instance, ref double __result) { ZNetView val = View.Invoke(__instance); if ((Object)(object)val != (Object)null && val.IsValid()) { __result += val.GetZDO().GetFloat("BuildCameraPlus_bonus", 0f); } } } [HarmonyPatch] internal static class Planting { private const float DefaultReach = 0.25f; private const float HarvestRadius = 5f; private static readonly FieldRef<Player, GameObject> Ghost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost"); private static readonly Func<Player, float> BuildStamina = AccessTools.MethodDelegate<Func<Player, float>>(AccessTools.Method(typeof(Player), "GetBuildStamina", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Player, ItemData, float> PlaceDurability = AccessTools.MethodDelegate<Func<Player, ItemData, float>>(AccessTools.Method(typeof(Player), "GetPlaceDurability", (Type[])null, (Type[])null), (object)null, true); private static readonly Func<Humanoid, ItemData> RightItem = AccessTools.MethodDelegate<Func<Humanoid, ItemData>>(AccessTools.Method(typeof(Humanoid), "GetRightItem", (Type[])null, (Type[])null), (object)null, true); private static readonly Dictionary<string, float> reach = new Dictionary<string, float>(); private static readonly List<GameObject> markers = new List<GameObject>(); private static int spaceMask; private static bool placing; internal static void Tick(Player p) { //IL_0035: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.plantingEnabled.Value) { HideMarkers(0); return; } bool flag = !Cam.Typing() && !InventoryGui.IsVisible() && !Menu.IsVisible(); if (flag && Cam.Pressed(Plugin.bulkHarvestKey.Value)) { BulkHarvest(p); } Piece val = SelectedPlant(p); GameObject val2 = Ghost.Invoke(p); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || !val2.activeInHierarchy) { HideMarkers(0); return; } if (flag) { ReadKeys(p); } List<Vector3> list = Layout(val, val2); int num = Affordable(p, val) - 1; for (int i = 0; i < list.Count; i++) { GameObject obj = Marker(i); obj.transform.position = list[i] + Vector3.up * 0.15f; bool flag2 = i < num && Free(((Component)val).GetComponent<Plant>(), list[i]); obj.GetComponent<Renderer>().material.color = (flag2 ? new Color(0.3f, 1f, 0.3f, 1f) : new Color(1f, 0.25f, 0.25f, 1f)); obj.SetActive(true); } HideMarkers(list.Count); } private static Piece SelectedPlant(Player p) { if (!((Character)p).InPlaceMode()) { return null; } Piece selectedPiece = p.GetSelectedPiece(); if (!((Object)(object)selectedPiece != (Object)null) || !((Object)(object)((Component)selectedPiece).GetComponent<Plant>() != (Object)null)) { return null; } return selectedPiece; } private static void ReadKeys(Player p) { //IL_0005: 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_002f: 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) int num = (Cam.Pressed(Plugin.rowsUpKey.Value) ? 1 : (Cam.Pressed(Plugin.rowsDownKey.Value) ? (-1) : 0)); int num2 = (Cam.Pressed(Plugin.colsUpKey.Value) ? 1 : (Cam.Pressed(Plugin.colsDownKey.Value) ? (-1) : 0)); if (num != 0 || num2 != 0) { Plugin.rows.Value = Mathf.Clamp(Plugin.rows.Value + num, 1, 15); Plugin.columns.Value = Mathf.Clamp(Plugin.columns.Value + num2, 1, 15); ((Character)p).Message((MessageType)2, "Planting " + Plugin.rows.Value + " x " + Plugin.columns.Value, 0, (Sprite)null, false); } } private static float Spacing(Piece piece) { if (!reach.TryGetValue(((Object)piece).name, out var value)) { value = 0.25f; } return Mathf.Max(0.4f, ((Component)piece).GetComponent<Plant>().m_growRadius + value); } private static List<Vector3> Layout(Piece piece, GameObject ghost) { //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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0045: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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) List<Vector3> list = new List<Vector3>(); Vector3 val = Flat(ghost.transform.forward); Vector3 val2 = Flat(ghost.transform.right); float num = Spacing(piece); float num2 = ghost.transform.position.y - GroundAt(ghost.transform.position); for (int i = 0; i < Plugin.rows.Value; i++) { for (int j = 0; j < Plugin.columns.Value; j++) { if (i != 0 || j != 0) { Vector3 val3 = ghost.transform.position + val * ((float)i * num) + val2 * ((float)j * num); val3.y = GroundAt(val3) + num2; list.Add(val3); } } } return list; } private static Vector3 Flat(Vector3 v) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) v.y = 0f; if (!(((Vector3)(ref v)).sqrMagnitude < 0.0001f)) { return ((Vector3)(ref v)).normalized; } return Vector3.forward; } private static float GroundAt(Vector3 pos) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) float result = default(float); if (!((Object)(object)ZoneSystem.instance != (Object)null) || !ZoneSystem.instance.GetGroundHeight(pos, ref result)) { return pos.y; } return result; } private static bool Free(Plant plant, Vector3 pos) { //IL_0000: 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_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_008b: Unknown result type (might be due to invalid IL or missing references) Heightmap val = Heightmap.FindHeightmap(pos); if ((Object)(object)val == (Object)null || (val.GetBiome(pos, 0.02f, false) & plant.m_biome) == 0) { return false; } if (plant.m_needCultivatedGround && !val.IsCultivated(pos)) { return false; } if (!PrivateArea.CheckAccess(pos, 0f, false, false)) { return false; } if (spaceMask == 0) { spaceMask = LayerMask.GetMask(new string[5] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid" }); } return Physics.OverlapSphere(pos, plant.m_growRadius, spaceMask).All((Collider c) => (Object)(object)((Component)c).GetComponentInParent<Player>() != (Object)null); } private static int Affordable(Player p, Piece piece) { int num = int.MaxValue; Requirement[] resources = piece.m_resources; foreach (Requirement val in resources) { if (val.m_amount > 0) { num = Math.Min(num, ((Humanoid)p).GetInventory().CountItems(val.m_resItem.m_itemData.m_shared.m_name, -1, true) / val.m_amount); } } if (num != int.MaxValue) { return num; } return 0; } [HarmonyPatch(typeof(Player), "TryPlacePiece")] [HarmonyPostfix] private static void Placed(Player __instance, Piece piece, bool __result) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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_00c8: 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_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) if (!__result || placing || !Plugin.modEnabled.Value || !Plugin.plantingEnabled.Value || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || (Object)(object)piece == (Object)null || (Object)(object)((Component)piece).GetComponent<Plant>() == (Object)null) { return; } GameObject val = Ghost.Invoke(__instance); if ((Object)(object)val == (Object)null) { return; } Plant component = ((Component)piece).GetComponent<Plant>(); Quaternion rotation = val.transform.rotation; List<Vector3> list = Layout(piece, val); int num = Affordable(__instance, piece) - 1; MeasureReach(piece, val.transform.position); placing = true; try { ItemData val2 = RightItem((Humanoid)(object)__instance); float num2 = BuildStamina(__instance); int num3 = 0; foreach (Vector3 item in list) { if (num3 >= num || !((Character)__instance).HaveStamina(num2) || (val2 != null && val2.m_shared.m_useDurability && val2.m_durability <= 0f)) { break; } if (Free(component, item)) { __instance.PlacePiece(piece, item, rotation, false, false); __instance.ConsumeResources(piece.m_resources, 0, -1, 1); ((Character)__instance).UseStamina(num2); if (val2 != null && val2.m_shared.m_useDurability) { val2.m_durability = Mathf.Max(0f, val2.m_durability - PlaceDurability(__instance, val2)); } num3++; } } if (num3 > 0) { ((Character)__instance).Message((MessageType)1, "Planted " + (num3 + 1), 0, (Sprite)null, false); } } finally { placing = false; } } private static void MeasureReach(Piece piece, Vector3 near) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0094: 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_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) if (reach.ContainsKey(((Object)piece).name)) { return; } Plant val = (from c in Physics.OverlapSphere(near, 0.6f) select ((Component)c).GetComponentInParent<Plant>()).FirstOrDefault((Func<Plant, bool>)((Plant pl) => (Object)(object)pl != (Object)null && ((Object)pl).name.StartsWith(((Object)piece).name))); if (!((Object)(object)val == (Object)null)) { float num = 0f; Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(); foreach (Collider val2 in componentsInChildren) { float num3 = num; Bounds bounds = val2.bounds; float x = ((Bounds)(ref bounds)).extents.x; bounds = val2.bounds; float num4 = Mathf.Max(x, ((Bounds)(ref bounds)).extents.z); bounds = val2.bounds; num = Mathf.Max(num3, num4 + Flat3(((Bounds)(ref bounds)).center - ((Component)val).transform.position)); } reach[((Object)piece).name] = Mathf.Clamp(num, 0.05f, 1f); } } private static float Flat3(Vector3 v) { v.y = 0f; return ((Vector3)(ref v)).magnitude; } private static void BulkHarvest(Player p) { //IL_0023: 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) GameObject hoverObject = ((Humanoid)p).GetHoverObject(); Vector3 val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.transform.position : ((Component)p).transform.position); int num = 0; foreach (Pickable item in (from c in Physics.OverlapSphere(val, 5f) select ((Component)c).GetComponentInParent<Pickable>() into x where (Object)(object)x != (Object)null select x).Distinct().ToList()) { if (item.CanBePicked() && item.Interact((Humanoid)(object)p, false, false)) { num++; } } if (num > 0) { ((Character)p).Message((MessageType)1, "Picked " + num, 0, (Sprite)null, false); } } private static GameObject Marker(int i) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) while (markers.Count <= i) { GameObject val = GameObject.CreatePrimitive((PrimitiveType)0); Object.Destroy((Object)(object)val.GetComponent<Collider>()); val.transform.localScale = Vector3.one * 0.25f; val.SetActive(false); markers.Add(val); } return markers[i]; } private static void HideMarkers(int from) { for (int i = from; i < markers.Count; i++) { if ((Object)(object)markers[i] != (Object)null) { markers[i].SetActive(false); } } } } [BepInPlugin("saymonn.BuildCameraPlus", "BuildCameraPlus", "1.6.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { public const string Guid = "saymonn.BuildCameraPlus"; public const string PrefabName = "BuildCameraPlus_Hammer"; public const string ItemName = "$bcp_hammer"; internal static ConfigEntry<bool> modEnabled; internal static ConfigEntry<bool> hammerEnabled; internal static ConfigEntry<bool> cameraEnabled; internal static ConfigEntry<bool> repairEnabled; internal static ConfigEntry<bool> plantingEnabled; internal static ConfigEntry<bool> growthEnabled; internal static ConfigEntry<KeyboardShortcut> teleportKey; internal static ConfigEntry<KeyboardShortcut> freeKey; internal static ConfigEntry<float> speed; internal static ConfigEntry<float> runMultiplier; internal static ConfigEntry<float> mouseSensitivity; internal static ConfigEntry<float> maxDistance; internal static ConfigEntry<float> placementReach; internal static ConfigEntry<float> repairRadius; internal static ConfigEntry<float> pickupRadius; internal static ConfigEntry<bool> flatMovement; internal static ConfigEntry<bool> stayAboveGround; internal static ConfigEntry<bool> stationNearPiece; internal static ConfigEntry<bool> exitWhenHit; internal static ConfigEntry<bool> invincible; internal static ConfigEntry<bool> cameraWithFarmTools; internal static ConfigEntry<KeyboardShortcut> rowsUpKey; internal static ConfigEntry<KeyboardShortcut> rowsDownKey; internal static ConfigEntry<KeyboardShortcut> colsUpKey; internal static ConfigEntry<KeyboardShortcut> colsDownKey; internal static ConfigEntry<KeyboardShortcut> bulkHarvestKey; internal static ConfigEntry<int> rows; internal static ConfigEntry<int> columns; internal static ConfigEntry<float> rainMultiplier; internal static ConfigEntry<float> beeMultiplier; internal static ConfigEntry<float> beeRadius; private static readonly Func<Humanoid, ItemData> RightItem = AccessTools.MethodDelegate<Func<Humanoid, ItemData>>(AccessTools.Method(typeof(Humanoid), "GetRightItem", (Type[])null, (Type[])null), (object)null, true); private static readonly FieldRef<Humanoid, ItemData> HiddenRightItem = AccessTools.FieldRefAccess<Humanoid, ItemData>("m_hiddenRightItem"); private void Awake() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0468: Unknown result type (might be due to invalid IL or missing references) //IL_056c: Unknown result type (might be due to invalid IL or missing references) modEnabled = Cfg.Add(((BaseUnityPlugin)this).Config, "01 General", "Enabled", value: true, "Master switch. When off, the whole mod is inactive."); hammerEnabled = Cfg.Add(((BaseUnityPlugin)this).Config, "02 Hammer", "Craftable", value: true, "The Builder's Hammer can be crafted at the workbench for 1 wood (needs a game restart). Otherwise use the console: spawn BuildCameraPlus_Hammer"); cameraEnabled = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "Enabled", value: true, "Free build camera with the Builder's Hammer."); teleportKey = Cfg.Add<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "03 Camera", "TeleportKey", new KeyboardShortcut((KeyCode)98, Array.Empty<KeyCode>()), "Fly the camera and carry your invisible character with it, so you can pick up scattered pieces. Press again to return to where you started."); freeKey = Cfg.Add<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "03 Camera", "FreeKey", new KeyboardShortcut((KeyCode)98, (KeyCode[])(object)new KeyCode[1] { (KeyCode)308 }), "Detach only the camera; your character stays where it is."); cameraWithFarmTools = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "WorksWithCultivatorAndHoe", value: true, "The camera can also be started with any cultivator or hoe, not only with the Builder's Hammer (area repair stays hammer only)."); speed = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "Speed", 10f, "Flight speed in metres per second.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)); runMultiplier = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "RunMultiplier", 3f, "How much faster you fly while holding the Run key (Shift).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f)); mouseSensitivity = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "MouseSensitivity", 1f, "Multiplies the game's own mouse sensitivity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f)); flatMovement = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "HorizontalMovement", value: true, "On: forward/back move level with the ground. Off: forward goes where you look, up or down too."); maxDistance = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "MaxDistance", 250f, "How far (metres) the camera or character may fly from the spot where you started.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 1000f)); stayAboveGround = Cfg.Add(((BaseUnityPlugin)this).Config, "03 Camera", "StayAboveGround", value: false, "On: the camera cannot go below the terrain. Off: you can fly under the world (both B and Alt+B)."); invincible = Cfg.Add(((BaseUnityPlugin)this).Config, "04 Camera - B mode", "InvincibleWhileFlying", value: true, "In the B mode (character flies along) the character takes no damage at all: lava, fire, falling, drowning, monsters."); exitWhenHit = Cfg.Add(((BaseUnityPlugin)this).Config, "04 Camera - B mode", "ExitWhenHit", value: true, "If your character takes damage, the camera snaps back."); pickupRadius = Cfg.Add(((BaseUnityPlugin)this).Config, "04 Camera - B mode", "PickupRadius", 2f, "In the B mode (character flies along): radius in metres in which the character picks up lying items (leftovers of destroyed pieces and so on). In the game it is 2 m, which is the default here.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 50f)); placementReach = Cfg.Add(((BaseUnityPlugin)this).Config, "05 Camera - Building reach", "PlacementReach", 10f, "How far (metres) from the camera you can place, repair and remove pieces.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 50f)); stationNearPiece = Cfg.Add(((BaseUnityPlugin)this).Config, "05 Camera - Building reach", "WorkbenchNearPiece", value: false, "The crafting station must be near the piece, not near your character."); repairEnabled = Cfg.Add(((BaseUnityPlugin)this).Config, "06 Area Repair", "Enabled", value: true, "Repairing a piece with the Builder's Hammer also repairs every damaged piece around it, no crafting station needed."); repairRadius = Cfg.Add(((BaseUnityPlugin)this).Config, "06 Area Repair", "Radius", 50f, "Radius in metres around the repaired piece.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 500f)); AreaDestroy.Bind(((BaseUnityPlugin)this).Config); plantingEnabled = Cfg.Add(((BaseUnityPlugin)this).Config, "08 Planting", "Enabled", value: true, "Plant in rows and columns with the cultivator, and bulk-harvest."); rows = Cfg.Add(((BaseUnityPlugin)this).Config, "08 Planting", "Rows", 1, "Current number of rows.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 15)); columns = Cfg.Add(((BaseUnityPlugin)this).Config, "08 Planting", "Columns", 1, "Current number of columns.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 15)); rowsUpKey = Cfg.Add<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "08 Planting", "RowsUpKey", new KeyboardShortcut((KeyCode)273, Array.Empty<KeyCode>()), "More rows."); rowsDownKey = Cfg.Add<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "08 Planting", "RowsDownKey", new KeyboardShortcut((KeyCode)274, Array.Empty<KeyCode>()), "Fewer rows."); colsUpKey = Cfg.Add<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "08 Planting", "ColumnsUpKey", new KeyboardShortcut((KeyCode)275, Array.Empty<KeyCode>()), "More columns."); colsDownKey = Cfg.Add<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "08 Planting", "ColumnsDownKey", new KeyboardShortcut((KeyCode)276, Array.Empty<KeyCode>()), "Fewer columns."); bulkHarvestKey = Cfg.Add<KeyboardShortcut>(((BaseUnityPlugin)this).Config, "08 Planting", "BulkHarvestKey", new KeyboardShortcut((KeyCode)101, (KeyCode[])(object)new KeyCode[1] { (KeyCode)304 }), "Pick every ripe plant within 5 m of the one you pick."); growthEnabled = Cfg.Add(((BaseUnityPlugin)this).Config, "09 Growth", "Enabled", value: true, "Plants grow faster in rain and near working beehives."); rainMultiplier = Cfg.Add(((BaseUnityPlugin)this).Config, "09 Growth", "RainMultiplier", 2f, "Growth speed while it rains on the plant.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f)); beeMultiplier = Cfg.Add(((BaseUnityPlugin)this).Config, "09 Growth", "BeeMultiplier", 1.5f, "Growth speed within BeeRadius of a working beehive.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 10f)); beeRadius = Cfg.Add(((BaseUnityPlugin)this).Config, "09 Growth", "BeeRadius", 20f, "Radius in metres around a beehive.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)); AddTranslations(); Rules.Bind(((BaseUnityPlugin)this).Config); PrefabManager.OnVanillaPrefabsAvailable += CreateHammer; new Harmony("saymonn.BuildCameraPlus").PatchAll(); } private void Update() { if (modEnabled.Value && !((Object)(object)Player.m_localPlayer == (Object)null)) { Rules.Tick(Player.m_localPlayer); Cam.Tick(); Planting.Tick(Player.m_localPlayer); } } private void OnDestroy() { Cam.Exit(null); } internal static bool HoldsHammer(Player player) { if ((Object)(object)player == (Object)null) { return false; } ItemData val = RightItem((Humanoid)(object)player) ?? HiddenRightItem.Invoke((Humanoid)(object)player); if (val != null) { return val.m_shared.m_name == "$bcp_hammer"; } return false; } internal static bool HoldsCameraTool(Player player) { if (HoldsHammer(player)) { return true; } if (!cameraWithFarmTools.Value || (Object)(object)player == (Object)null) { return false; } ItemData val = RightItem((Humanoid)(object)player) ?? HiddenRightItem.Invoke((Humanoid)(object)player); if (val == null) { return false; } string name = val.m_shared.m_name; if (!(name == "$item_cultivator")) { return name == "$item_hoe"; } return true; } private static void AddTranslations() { CustomLocalization localization = LocalizationManager.Instance.GetLocalization(); string text = "English"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "bcp_hammer", "Builder's Hammer" }, { "bcp_hammer_desc", "A hammer that never wears out. B flies the camera with your character, Alt+B only the camera." } }); text = "Polish"; localization.AddTranslation(ref text, new Dictionary<string, string> { { "bcp_hammer", "Młot Wielozadaniowy" }, { "bcp_hammer_desc", "Młot, który się nie zużywa. B leci kamerą razem z postacią, Alt+B tylko kamerą." } }); } private static void CreateHammer() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown PrefabManager.OnVanillaPrefabsAvailable -= CreateHammer; ItemConfig val = new ItemConfig(); val.Enabled = hammerEnabled.Value; val.Name = "$bcp_hammer"; val.Description = "$bcp_hammer_desc"; val.CraftingStation = CraftingStations.Workbench; val.Requirements = (RequirementConfig[])(object)new RequirementConfig[1] { new RequirementConfig { Item = "Wood", Amount = 1, Recover = true } }; ItemConfig val2 = val; CustomItem val3 = new CustomItem("BuildCameraPlus_Hammer", "Hammer", val2); if ((Object)(object)val3.ItemPrefab == (Object)null) { Logger.LogWarning((object)"Could not clone the vanilla hammer."); return; } SharedData shared = val3.ItemDrop.m_itemData.m_shared; shared.m_useDurability = false; Sprite val4 = LoadIcon(); if ((Object)(object)val4 != (Object)null) { shared.m_icons = (Sprite[])(object)new Sprite[1] { val4 }; } ItemManager.Instance.AddItem(val3); } private static Sprite LoadIcon() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "hammer.png"); if (!File.Exists(path)) { return null; } MethodInfo methodInfo = AccessTools.Method("UnityEngine.ImageConversion:LoadImage", new Type[2] { typeof(Texture2D), typeof(byte[]) }, (Type[])null); Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (methodInfo == null || !(bool)methodInfo.Invoke(null, new object[2] { val, File.ReadAllBytes(path) })) { return null; } return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } } [HarmonyPatch] internal static class AreaRepair { private static readonly FieldRef<Player, Piece> Hovering = AccessTools.FieldRefAccess<Player, Piece>("m_hoveringPiece"); private static int mask; private static bool repairing; private static bool Wanted(Player p) { if (Plugin.modEnabled.Value && Plugin.repairEnabled.Value && (Object)(object)p == (Object)(object)Player.m_localPlayer) { return Plugin.HoldsHammer(p); } return false; } [HarmonyPatch(typeof(Player), "Repair")] [HarmonyPrefix] private static void Before(Player __instance) { repairing = Wanted(__instance); } [HarmonyPatch(typeof(Player), "Repair")] [HarmonyFinalizer] private static void After() { repairing = false; } [HarmonyPatch(typeof(Player), "CheckCanRemovePiece")] [HarmonyPrefix] private static bool NoStation(ref bool __result) { if (!repairing) { return true; } __result = true; return false; } [HarmonyPatch(typeof(Player), "Repair")] [HarmonyPostfix] private static void Around(Player __instance, ItemData toolItem) { //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) if (!Wanted(__instance) || toolItem == null || !((Character)__instance).InPlaceMode()) { return; } Piece val = Hovering.Invoke(__instance); if ((Object)(object)val == (Object)null) { return; } if (mask == 0) { mask = LayerMask.GetMask(new string[6] { "Default", "static_solid", "Default_small", "piece", "piece_nonsolid", "vehicle" }); } Vector3 centre = ((Component)val).transform.position; HashSet<WearNTear> hashSet = new HashSet<WearNTear>(); List<WearNTear> list = new List<WearNTear>(); Collider[] array = Physics.OverlapSphere(centre, Plugin.repairRadius.Value, mask); for (int i = 0; i < array.Length; i++) { WearNTear componentInParent = ((Component)array[i]).GetComponentInParent<WearNTear>(); if (!((Object)(object)componentInParent == (Object)null) && hashSet.Add(componentInParent) && !((Object)(object)((Component)componentInParent).gameObject == (Object)(object)((Component)val).gameObject)) { ZNetView component = ((Component)componentInParent).GetComponent<ZNetView>(); if ((Object)(object)component != (Object)null && component.IsValid() && componentInParent.GetHealthPercentage() < 1f) { list.Add(componentInParent); } } } int num = 0; foreach (WearNTear item in list.OrderBy(delegate(WearNTear w) { //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_0016: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = ((Component)w).transform.position - centre; return ((Vector3)(ref val2)).sqrMagnitude; })) { if (PrivateArea.CheckAccess(((Component)item).transform.position, 0f, false, false) && item.Repair()) { num++; } } if (num > 0) { ((Character)__instance).Message((MessageType)1, "Repaired around: " + num, 0, (Sprite)null, false); } } } [HarmonyPatch] internal static class Rules { private static ConfigEntry<bool> restrictionsEnabled; private static ConfigEntry<bool> extensionEnabled; private static ConfigEntry<bool> allowClose; private static ConfigEntry<bool> unbreakable; private static ConfigEntry<bool> buildRangeEnabled; private static ConfigEntry<bool> freeBuildStamina; private static ConfigEntry<bool> freeRemoveStamina; private static ConfigEntry<bool> noWorkbench; private static ConfigEntry<bool> noStonecutter; private static ConfigEntry<bool> noForge; private static ConfigEntry<bool> autoRemove; private static ConfigEntry<float> buildRange; private static ConfigEntry<float> extensionDistance; private static readonly Dictionary<PlacementStatus, ConfigEntry<bool>> ignored = new Dictionary<PlacementStatus, ConfigEntry<bool>>(); private static CraftingStation anyStation; private const float VanillaDistance = 5f; private static readonly FieldRef<Player, GameObject> Ghost = AccessTools.FieldRefAccess<Player, GameObject>("m_placementGhost"); private static readonly FieldRef<Player, PlacementStatus> Status = AccessTools.FieldRefAccess<Player, PlacementStatus>("m_placementStatus"); private static readonly Action<Player, bool> SetGhostValid = AccessTools.MethodDelegate<Action<Player, bool>>(AccessTools.Method(typeof(Player), "SetPlacementGhostValid", (Type[])null, (Type[])null), (object)null, true); private static readonly FieldRef<List<StationExtension>> AllExtensions = AccessTools.StaticFieldRefAccess<List<StationExtension>>(AccessTools.Field(typeof(StationExtension), "m_allExtensions")); private static ConfigEntry<bool> missingStation; private static readonly FieldRef<CraftingStation, float> BuiltRange = AccessTools.FieldRefAccess<CraftingStation, float>("m_buildRange"); private static readonly FieldRef<CraftingStation, CircleProjector> RangeCircle = AccessTools.FieldRefAccess<CraftingStation, CircleProjector>("m_areaMarkerCircle"); private static readonly FieldRef<Player, float> RemovePressed = AccessTools.FieldRefAccess<Player, float>("m_removePressedTime"); private static int removedFrame = -1; private static float removeKeyTime = -10f; private static bool Master { get { if (Plugin.modEnabled.Value) { return restrictionsEnabled.Value; } return false; } } private static float Distance { get { if (!Plugin.modEnabled.Value || !extensionEnabled.Value) { return 5f; } return extensionDistance.Value; } } internal static void Bind(ConfigFile c) { restrictionsEnabled = Cfg.Add(c, "10 Build Restrictions", "Enabled", value: false, "Build where the game normally refuses. Only the rules you switch on below are ignored."); Rule(c, "10 Build Restrictions", (PlacementStatus)1, "IgnoreInvalidPlacement", "Place pieces where the game says \"Invalid placement\": overlapping pieces, a campfire on a wooden floor, steep slopes."); Rule(c, "10 Build Restrictions", (PlacementStatus)2, "IgnorePlayerInTheWay", "Build even when a player stands where the piece goes."); Rule(c, "10 Build Restrictions", (PlacementStatus)3, "IgnoreNoBuildZones", "Build in protected places like the trader's camp and boss altars."); Rule(c, "10 Build Restrictions", (PlacementStatus)5, "IgnoreSpaceNeeded", "Build pieces that need free space around them (beds, portals) in tight spots."); Rule(c, "10 Build Restrictions", (PlacementStatus)6, "IgnoreTeleportAreas", "Place pieces that are normally only allowed in special teleport areas anywhere."); Rule(c, "10 Build Restrictions", (PlacementStatus)7, "IgnoreExtensionWithoutStation", "Build station upgrades without their crafting station nearby."); Rule(c, "10 Build Restrictions", (PlacementStatus)8, "IgnoreBiomeRestrictions", "Build pieces that are limited to certain biomes anywhere."); Rule(c, "10 Build Restrictions", (PlacementStatus)9, "IgnoreCultivatedGround", "Plant crops and saplings without cultivated ground."); Rule(c, "10 Build Restrictions", (PlacementStatus)10, "IgnoreDirtRequirement", "Place pieces that need dirt or grass on any ground."); Rule(c, "10 Build Restrictions", (PlacementStatus)11, "IgnoreDungeonRestrictions", "Build inside dungeons and crypts."); missingStation = Cfg.Add(c, "10 Build Restrictions", "IgnoreMissingWorkbench", value: false, "Build without a workbench (or other station a piece needs) nearby."); extensionEnabled = Cfg.Add(c, "11 Station Extension Range", "Enabled", value: true, "Station upgrades (chopping block, tanning rack, bellows...) may be further from their crafting station."); extensionDistance = Cfg.Add(c, "11 Station Extension Range", "Distance", 30f, "How far (metres) an upgrade may be from its station. Normal is 5.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 100f)); allowClose = Cfg.Add(c, "11 Station Extension Range", "AllowExtensionsNextToEachOther", value: true, "Upgrades of the same kind can be built close together (normally blocked)."); extensionEnabled.SettingChanged += delegate { ApplyExtensions(); }; extensionDistance.SettingChanged += delegate { ApplyExtensions(); }; buildRangeEnabled = Cfg.Add(c, "12 Station Build Range", "Enabled", value: true, "Crafting stations (stonecutter, workbench, forge...) count for building from further away."); buildRange = Cfg.Add(c, "12 Station Build Range", "Distance", 100f, "How far (metres) from a station you can still build the pieces that need it, e.g. stone walls near the stonecutter. Never less than the station's own range.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 500f)); noWorkbench = Cfg.Add(c, "13 Station Requirement", "NoWorkbenchNeeded", value: false, "Pieces that need a workbench (wood) can be built and removed without one nearby. Off: the workbench is required."); noStonecutter = Cfg.Add(c, "13 Station Requirement", "NoStonecutterNeeded", value: false, "Pieces that need a stonecutter (stone) can be built and removed without one nearby. Off: the stonecutter is required."); noForge = Cfg.Add(c, "13 Station Requirement", "NoForgeNeeded", value: false, "Pieces that need a forge (iron) can be built and removed without one nearby. Off: the forge is required."); freeBuildStamina = Cfg.Add(c, "14 Building Helpers", "NoStaminaWhenBuilding", value: false, "Building and repairing cost no stamina."); freeRemoveStamina = Cfg.Add(c, "14 Building Helpers", "NoStaminaWhenRemoving", value: false, "Removing (destroying) pieces costs no stamina."); autoRemove = Cfg.Add(c, "14 Building Helpers", "AutoRemove", value: false, "Hold the middle mouse button (the remove button) with a building tool and pieces under the crosshair are removed one after another, no repeated clicking."); unbreakable = Cfg.Add(c, "14 Building Helpers", "UnbreakableStructures", value: false, "Structures never collapse from lack of support: build stone floors and beams in mid-air."); } private static void Rule(ConfigFile c, string section, PlacementStatus status, string key, string description) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ignored[status] = Cfg.Add(c, section, key, value: false, description); } private static bool Ignores(PlacementStatus status) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (Master && ignored.TryGetValue(status, out var value)) { return value.Value; } return false; } [HarmonyPatch(typeof(Player), "UpdatePlacementGhost")] [HarmonyPostfix] private static void Ghosts(Player __instance) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Ghost.Invoke(__instance) == (Object)null)) { PlacementStatus val = Status.Invoke(__instance); if ((int)val != 0 && Ignores(val)) { Status.Invoke(__instance) = (PlacementStatus)0; SetGhostValid(__instance, arg2: true); } } } [HarmonyPatch(typeof(Location), "IsInsideNoBuildLocation")] [HarmonyPostfix] private static void NoBuildLocation(ref bool __result) { if (__result && Ignores((PlacementStatus)3)) { __result = false; } } [HarmonyPatch(typeof(CraftingStation), "HaveBuildStationInRange")] [HarmonyPostfix] private static void AnyStation(string name, ref CraftingStation __result) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown if (!((Object)(object)__result != (Object)null) && Plugin.modEnabled.Value && ((Master && missingStation.Value) || (name == "$piece_workbench" && noWorkbench.Value) || (name == "$piece_stonecutter" && noStonecutter.Value) || (name == "$piece_forge" && noForge.Value))) { if ((Object)(object)anyStation == (Object)null) { GameObject val = new GameObject("BuildCameraPlus_AnyStation"); val.SetActive(false); Object.DontDestroyOnLoad((Object)val); anyStation = val.AddComponent<CraftingStation>(); } __result = anyStation; } } private static void ApplyExtensions() { List<StationExtension> list = AllExtensions.Invoke(); if (list == null) { return; } foreach (StationExtension item in list) { if ((Object)(object)item != (Object)null) { item.m_maxStationDistance = Distance; } } } [HarmonyPatch(typeof(StationExtension), "Awake")] [HarmonyPrefix] private static void ExtensionAwake(StationExtension __instance) { __instance.m_maxStationDistance = Distance; } [HarmonyPatch(typeof(StationExtension), "OtherExtensionInRange")] [HarmonyPostfix] private static void OtherExtension(ref bool __result) { if (Plugin.modEnabled.Value && extensionEnabled.Value && allowClose.Value) { __result = false; } } [HarmonyPatch(typeof(CraftingStation), "GetExtensions")] [HarmonyPostfix] private static void WiderRange(CraftingStation __instance) { if (Plugin.modEnabled.Value && buildRangeEnabled.Value) { float num = Mathf.Max(BuiltRange.Invoke(__instance), buildRange.Value); BuiltRange.Invoke(__instance) = num; CircleProjector val = RangeCircle.Invoke(__instance); if ((Object)(object)val != (Object)null) { val.m_radius = num; } } } [HarmonyPatch(typeof(Player), "RemovePiece")] [HarmonyPostfix] private static void Removed(bool __result) { if (__result) { removedFrame = Time.frameCount; } } [HarmonyPatch(typeof(Player), "GetBuildStamina")] [HarmonyPostfix] private static void NoBuildStamina(ref float __result) { if (Plugin.modEnabled.Value && ((Time.frameCount == removedFrame) ? freeRemoveStamina.Value : freeBuildStamina.Value)) { __result = 0f; } } internal static void Tick(Player p) { if (Plugin.modEnabled.Value && !((Object)(object)p == (Object)null) && ((Character)p).InPlaceMode()) { if (ZInput.GetButton("Remove") || ZInput.GetButtonUp("Remove")) { removeKeyTime = Time.time; } if ((Time.time - removeKeyTime < 0.5f) ? freeRemoveStamina.Value : freeBuildStamina.Value) { ((Character)p).AddStamina(((Character)p).GetMaxStamina()); } if (autoRemove.Value && !AreaDestroy.Held() && ZInput.GetButton("Remove") && !ZInput.GetButton("AltPlace") && !Cam.Typing() && !Hud.IsPieceSelectionVisible() && !InventoryGui.IsVisible()) { RemovePressed.Invoke(p) = Time.time; } } } [HarmonyPatch(typeof(WearNTear), "HaveSupport")] [HarmonyPostfix] private static void Supported(ref bool __result) { if (Plugin.modEnabled.Value && unbreakable.Value) { __result = true; } } } }