using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("squarepatchmod")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("squarepatchmod")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("0a889f29-f468-4803-b8f9-663f72777b5c")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace BuildModeNoAutoZoom;
[BepInPlugin("nekogod.dsp.buildmode.noautozoom", "DSP Build Mode No AutoZoom", "1.0.3")]
public class BuildModeNoAutoZoomPlugin : BaseUnityPlugin
{
public const string PluginGuid = "nekogod.dsp.buildmode.noautozoom";
public const string PluginName = "DSP Build Mode No AutoZoom";
public const string PluginVersion = "1.0.3";
internal static ConfigEntry<bool> Enabled;
internal static ConfigEntry<float> ExtraMaxZoomOut;
internal static ConfigEntry<int> ShiftClickPinFrames;
private void Awake()
{
//IL_0069: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: Expected O, but got Unknown
Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable mod.");
ExtraMaxZoomOut = ((BaseUnityPlugin)this).Config.Bind<float>("General", "ExtraMaxZoomOut", 2f, "Permanent extra max zoom-out distance (meters). 0 disables.");
ShiftClickPinFrames = ((BaseUnityPlugin)this).Config.Bind<int>("General", "ShiftClickPinFrames", 8, "How many frames to enforce the non-build camera pose after Shift+LMB (covers shift-click entry path). -Shouldn't need changing, but increase if you still see auto zooming when shift+clicking.");
Harmony val = new Harmony("nekogod.dsp.buildmode.noautozoom");
MethodInfo methodInfo = AccessTools.Method(typeof(CameraPoseBlender), "Calculate", (Type[])null, (Type[])null);
if (methodInfo != null)
{
HarmonyMethod val2 = new HarmonyMethod(typeof(BlenderPinPatches), "CameraPoseBlender_Calculate_Prefix", (Type[])null);
val.Patch((MethodBase)methodInfo, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
PatchPoserByExactTypeNameFromAssemblyCSharp(val, "RTSPoser");
PatchPoserByExactTypeNameFromAssemblyCSharp(val, "PRTSPoser");
}
private void Update()
{
if (Enabled.Value && Input.GetMouseButtonDown(0) && (Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && !BlenderPinPatches.IsBlueprintToolActive_Public())
{
BlenderPinPatches.OnShiftClick_Public();
}
}
private static void PatchPoserByExactTypeNameFromAssemblyCSharp(Harmony h, string typeName)
{
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0127: Expected O, but got Unknown
try
{
Assembly assembly = FindAssembly("Assembly-CSharp");
if (assembly == null)
{
return;
}
Type type = assembly.GetType(typeName, throwOnError: false);
if (type == null)
{
return;
}
MethodInfo methodInfo = AccessTools.Method(type, "Calculate", (Type[])null, (Type[])null);
if (!(methodInfo == null))
{
FieldInfo fieldInfo = AccessTools.Field(type, "distMax");
FieldInfo fieldInfo2 = AccessTools.Field(type, "distMin");
FieldInfo fieldInfo3 = AccessTools.Field(type, "dist");
FieldInfo fieldInfo4 = AccessTools.Field(type, "distCoef");
if (!(fieldInfo == null) && !(fieldInfo.FieldType != typeof(float)) && !(fieldInfo2 == null) && !(fieldInfo2.FieldType != typeof(float)) && !(fieldInfo3 == null) && !(fieldInfo3.FieldType != typeof(float)) && !(fieldInfo4 == null) && !(fieldInfo4.FieldType != typeof(float)))
{
HarmonyMethod val = new HarmonyMethod(typeof(PermanentZoomPatches), "Calculate_Prefix", (Type[])null);
h.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
}
catch
{
}
}
private static Assembly FindAssembly(string simpleName)
{
try
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
if (!(assembly == null) && string.Equals(assembly.GetName().Name, simpleName, StringComparison.OrdinalIgnoreCase))
{
return assembly;
}
}
}
catch
{
}
return null;
}
}
internal static class BlenderPinPatches
{
private sealed class RefEq<T> : IEqualityComparer<T> where T : class
{
public static readonly RefEq<T> Instance = new RefEq<T>();
public bool Equals(T x, T y)
{
return x == y;
}
public int GetHashCode(T obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
}
private sealed class BlenderState
{
public int LastNonBuildIndex;
public bool HasNonBuild;
public int Baseline;
public bool PinActive;
public int BuildEpochApplied;
public int ShiftEpochApplied;
}
private static readonly FieldRef<CameraPoseBlender, int> IndexRef = AccessTools.FieldRefAccess<CameraPoseBlender, int>("index");
private static readonly Dictionary<CameraPoseBlender, BlenderState> _states = new Dictionary<CameraPoseBlender, BlenderState>(RefEq<CameraPoseBlender>.Instance);
private static bool _lastBuildActive;
private static int _buildEpoch;
private static int _forcedPinFrames;
private static int _shiftEpoch;
private static int _pruneCountdown = 600;
private static readonly List<CameraPoseBlender> _pruneKeys = new List<CameraPoseBlender>(64);
private static readonly Dictionary<Type, bool> _blueprintTypeCache = new Dictionary<Type, bool>(16);
internal static void OnShiftClick_Public()
{
_shiftEpoch++;
SnapshotAllBlendersAsNonBuildAndArmShiftEpoch(_shiftEpoch);
_forcedPinFrames = Math.Max(1, BuildModeNoAutoZoomPlugin.ShiftClickPinFrames.Value);
}
internal static bool IsBlueprintToolActive_Public()
{
return IsBlueprintToolActive();
}
private static void SnapshotAllBlendersAsNonBuildAndArmShiftEpoch(int shiftEpoch)
{
try
{
CameraPoseBlender[] array = Resources.FindObjectsOfTypeAll<CameraPoseBlender>();
if (array == null)
{
return;
}
foreach (CameraPoseBlender val in array)
{
if (!((Object)(object)val == (Object)null))
{
if (!_states.TryGetValue(val, out var value))
{
value = new BlenderState();
_states[val] = value;
}
int baseline = (value.LastNonBuildIndex = IndexRef.Invoke(val));
value.HasNonBuild = true;
value.Baseline = baseline;
value.PinActive = true;
value.ShiftEpochApplied = shiftEpoch;
}
}
}
catch
{
}
}
public static void CameraPoseBlender_Calculate_Prefix(CameraPoseBlender __instance)
{
if ((Object)(object)__instance == (Object)null)
{
return;
}
PruneDeadOccasionally();
if (!BuildModeNoAutoZoomPlugin.Enabled.Value)
{
return;
}
bool flag = IsBuild();
if (flag != _lastBuildActive)
{
_lastBuildActive = flag;
if (flag)
{
_buildEpoch++;
}
}
if (!_states.TryGetValue(__instance, out var value))
{
value = new BlenderState();
_states[__instance] = value;
}
int num = IndexRef.Invoke(__instance);
if (!flag && _forcedPinFrames <= 0)
{
value.LastNonBuildIndex = num;
value.HasNonBuild = true;
value.PinActive = false;
return;
}
if ((flag || _forcedPinFrames > 0) && IsBlueprintToolActive())
{
if (_forcedPinFrames > 0)
{
_forcedPinFrames--;
}
return;
}
if (flag && value.BuildEpochApplied != _buildEpoch)
{
value.BuildEpochApplied = _buildEpoch;
value.Baseline = (value.HasNonBuild ? value.LastNonBuildIndex : num);
value.PinActive = true;
}
if (!flag && _forcedPinFrames > 0 && !value.PinActive)
{
value.Baseline = (value.HasNonBuild ? value.LastNonBuildIndex : num);
value.PinActive = true;
}
if ((flag || _forcedPinFrames > 0) && value.PinActive && num != value.Baseline)
{
IndexRef.Invoke(__instance) = value.Baseline;
}
if (_forcedPinFrames > 0)
{
_forcedPinFrames--;
}
if (_forcedPinFrames <= 0 && !flag)
{
value.PinActive = false;
}
}
private static void PruneDeadOccasionally()
{
if (--_pruneCountdown > 0)
{
return;
}
_pruneCountdown = 600;
_pruneKeys.Clear();
foreach (KeyValuePair<CameraPoseBlender, BlenderState> state in _states)
{
if ((Object)(object)state.Key == (Object)null)
{
_pruneKeys.Add(state.Key);
}
}
for (int i = 0; i < _pruneKeys.Count; i++)
{
_states.Remove(_pruneKeys[i]);
}
}
private static bool IsBuild()
{
Player mainPlayer = GameMain.mainPlayer;
PlayerAction_Build val = ((mainPlayer == null) ? null : mainPlayer.controller?.actionBuild);
if (val != null)
{
return val.active;
}
return false;
}
private static bool IsBlueprintToolActive()
{
Player mainPlayer = GameMain.mainPlayer;
object obj;
if (mainPlayer == null)
{
obj = null;
}
else
{
PlayerController controller = mainPlayer.controller;
if (controller == null)
{
obj = null;
}
else
{
PlayerAction_Build actionBuild = controller.actionBuild;
obj = ((actionBuild != null) ? actionBuild.activeTool : null);
}
}
BuildTool val = (BuildTool)obj;
if (val == null)
{
return false;
}
Type type = ((object)val).GetType();
if (_blueprintTypeCache.TryGetValue(type, out var value))
{
return value;
}
bool flag = type.Name.IndexOf("Blueprint", StringComparison.OrdinalIgnoreCase) >= 0;
_blueprintTypeCache[type] = flag;
return flag;
}
}
internal static class PermanentZoomPatches
{
private sealed class RefEq<T> : IEqualityComparer<T> where T : class
{
public static readonly RefEq<T> Instance = new RefEq<T>();
public bool Equals(T x, T y)
{
return x == y;
}
public int GetHashCode(T obj)
{
return RuntimeHelpers.GetHashCode(obj);
}
}
private static readonly HashSet<object> Done = new HashSet<object>(RefEq<object>.Instance);
[HarmonyPrefix]
public static void Calculate_Prefix(object __instance)
{
if (!BuildModeNoAutoZoomPlugin.Enabled.Value)
{
return;
}
float value = BuildModeNoAutoZoomPlugin.ExtraMaxZoomOut.Value;
if (value <= 0.0001f || !Done.Add(__instance))
{
return;
}
try
{
Type type = __instance.GetType();
FieldInfo fieldInfo = AccessTools.Field(type, "distMin");
FieldInfo fieldInfo2 = AccessTools.Field(type, "distMax");
FieldInfo fieldInfo3 = AccessTools.Field(type, "dist");
FieldInfo fieldInfo4 = AccessTools.Field(type, "distCoef");
FieldInfo fieldInfo5 = AccessTools.Field(type, "distCoefWanted");
FieldInfo fieldInfo6 = AccessTools.Field(type, "distCoefBegin");
if (fieldInfo == null || fieldInfo2 == null || fieldInfo3 == null || fieldInfo4 == null)
{
return;
}
float num = (float)fieldInfo.GetValue(__instance);
float num2 = (float)fieldInfo2.GetValue(__instance);
float num3 = (float)fieldInfo3.GetValue(__instance);
float num4 = num2 + value;
fieldInfo2.SetValue(__instance, num4);
float num5 = num4 - num;
if (!(num5 <= 0.0001f))
{
float num6 = (num3 - num) / num5;
if (num6 < 0f)
{
num6 = 0f;
}
else if (num6 > 1f)
{
num6 = 1f;
}
fieldInfo4.SetValue(__instance, num6);
if (fieldInfo5 != null && fieldInfo5.FieldType == typeof(float))
{
fieldInfo5.SetValue(__instance, num6);
}
if (fieldInfo6 != null && fieldInfo6.FieldType == typeof(float))
{
fieldInfo6.SetValue(__instance, num6);
}
}
}
catch
{
}
}
}