using System;
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("Memories")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Riintouge")]
[assembly: AssemblyProduct("Memories")]
[assembly: AssemblyCopyright("Copyright © 2024")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8feb5558-d229-48a5-b282-45680131f27d")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.1.0.0")]
namespace Memories;
[BepInPlugin("com.riintouge.memories", "Memories", "1.1.0")]
[BepInProcess("valheim.exe")]
public class Memories : BaseUnityPlugin
{
[HarmonyPatch(typeof(GameCamera))]
private class GameCameraPatch
{
public enum CameraContext
{
Generic,
Saddle,
Ship
}
private const float HalfPI = (float)Math.PI / 2f;
private static CameraContext LastCameraContext = CameraContext.Generic;
private static float FrameInitialCameraDistance = 4f;
private static InterpolationTypeEnum LerpType = InterpolationTypeEnum.Immediate;
private static float LerpFrom = 4f;
private static float LerpTo = 4f;
private static float LerpElapsed = 0f;
private static float LerpDuration = 0f;
private static float LerpDistanceOverride = 4f;
private static bool IsInterpolating = false;
private static CameraContext GetCameraContext(Player player)
{
if ((Object)(object)player != (Object)null)
{
if ((Object)(object)player.GetControlledShip() != (Object)null)
{
return CameraContext.Ship;
}
if (((Character)player).IsRiding())
{
return CameraContext.Saddle;
}
}
return CameraContext.Generic;
}
private static void UpdateCameraCore(CameraContext context, ref float targetZoom, ref float ___m_distance, float ___m_minDistance, float ___m_maxDistance)
{
if (LastCameraContext != context)
{
if (InterpolationType.Value != 0 && InterpolationDuration.Value > 0f)
{
LerpType = InterpolationType.Value;
LerpFrom = FrameInitialCameraDistance;
LerpTo = targetZoom;
LerpElapsed = 0f;
LerpDuration = Mathf.Max(0f, InterpolationDuration.Value);
LerpDistanceOverride = FrameInitialCameraDistance;
IsInterpolating = true;
}
else
{
___m_distance = Mathf.Clamp(targetZoom, ___m_minDistance, ___m_maxDistance);
}
}
else if (!IsInterpolating && targetZoom != ___m_distance)
{
targetZoom = Mathf.Clamp(___m_distance, ___m_minDistance, ___m_maxDistance);
}
}
[HarmonyPatch("ApplySettings")]
[HarmonyPrefix]
private static void ApplySettingsPrefix(ref float ___m_distance, ref float ___m_minDistance, ref float ___m_maxDistance, ref float ___m_maxDistanceBoat)
{
if (IsEnabled.Value)
{
LastCameraContext = GetCameraContext(Player.m_localPlayer);
if (LastCameraContext == CameraContext.Saddle)
{
___m_distance = Mathf.Clamp(LastSaddleZoom, ___m_minDistance, ___m_maxDistance);
}
else if (LastCameraContext == CameraContext.Ship)
{
___m_distance = Mathf.Clamp(LastShipZoom, ___m_minDistance, ___m_maxDistanceBoat);
}
else
{
___m_distance = Mathf.Clamp(LastCameraZoom, ___m_minDistance, ___m_maxDistance);
}
}
}
[HarmonyPatch("GetCameraPosition")]
[HarmonyPrefix]
private static void GetCameraPositionPrefix(ref float ___m_distance)
{
if (IsEnabled.Value)
{
if (IsInterpolating)
{
___m_distance = LerpDistanceOverride;
}
else if (LastCameraContext != GetCameraContext(Player.m_localPlayer))
{
___m_distance = FrameInitialCameraDistance;
}
}
}
[HarmonyPatch("OnDestroy")]
[HarmonyPrefix]
private static void OnDestroyPrefix(ref float ___m_distance)
{
IsInterpolating = false;
LerpFrom = 4f;
LerpTo = 4f;
LerpElapsed = 0f;
LerpDistanceOverride = 4f;
FrameInitialCameraDistance = 4f;
LastCameraContext = CameraContext.Generic;
}
[HarmonyPatch("UpdateCamera")]
[HarmonyPrefix]
private static void UpdateCameraPrefix(ref float ___m_distance)
{
FrameInitialCameraDistance = ___m_distance;
}
[HarmonyPatch("UpdateCamera")]
[HarmonyPostfix]
private static void UpdateCameraPostfix(ref float dt, ref float ___m_distance, ref float ___m_minDistance, ref float ___m_maxDistance, ref float ___m_maxDistanceBoat)
{
if (!IsEnabled.Value)
{
return;
}
if (IsInterpolating)
{
LerpElapsed = Mathf.Clamp(LerpElapsed + dt, 0f, LerpDuration);
float num = LerpElapsed / LerpDuration;
if (LerpType == InterpolationTypeEnum.Linear)
{
___m_distance = Mathf.Lerp(LerpFrom, LerpTo, num);
}
else if (LerpType == InterpolationTypeEnum.Accelerate)
{
___m_distance = Mathf.Lerp(LerpFrom, LerpTo, 1f - Mathf.Cos((float)Math.PI / 2f * num));
}
else if (LerpType == InterpolationTypeEnum.Decelerate)
{
___m_distance = Mathf.Lerp(LerpFrom, LerpTo, Mathf.Sin((float)Math.PI / 2f * num));
}
LerpDistanceOverride = ___m_distance;
IsInterpolating = LerpElapsed < LerpDuration;
}
CameraContext cameraContext = GetCameraContext(Player.m_localPlayer);
switch (cameraContext)
{
case CameraContext.Saddle:
UpdateCameraCore(cameraContext, ref LastSaddleZoom, ref ___m_distance, ___m_minDistance, ___m_maxDistance);
break;
case CameraContext.Ship:
UpdateCameraCore(cameraContext, ref LastShipZoom, ref ___m_distance, ___m_minDistance, ___m_maxDistanceBoat);
break;
default:
UpdateCameraCore(cameraContext, ref LastCameraZoom, ref ___m_distance, ___m_minDistance, ___m_maxDistance);
break;
}
LastCameraContext = cameraContext;
}
}
public enum InterpolationTypeEnum
{
Immediate,
Linear,
Accelerate,
Decelerate
}
public const float VanillaDefaultZoom = 4f;
public static ConfigEntry<bool> IsEnabled;
public static ConfigEntry<bool> LoadOnStart;
public static ConfigEntry<float> CameraZoom;
public static float LastCameraZoom;
public static ConfigEntry<float> ShipZoom;
public static float LastShipZoom;
public static ConfigEntry<float> SaddleZoom;
public static float LastSaddleZoom;
public static ConfigEntry<float> InterpolationDuration;
public static ConfigEntry<InterpolationTypeEnum> InterpolationType;
private readonly Harmony Harmony = new Harmony("com.riintouge.memories");
private void Awake()
{
IsEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "Enable", true, "Whether this plugin has any effect when loaded.");
LoadOnStart = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Core", "LoadOnStart", true, "Whether this plugin loads on game start.");
CameraZoom = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "CameraZoom", 4f, "Normal camera distance. This value is not updated in real-time to avoid frivolous disk I/O.");
SaddleZoom = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "SaddleCameraZoom", 4f, "Saddle camera distance. This value is not updated in real-time to avoid frivolous disk I/O.");
ShipZoom = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "ShipCameraZoom", 4f, "Ship camera distance. This value is not updated in real-time to avoid frivolous disk I/O.");
InterpolationDuration = ((BaseUnityPlugin)this).Config.Bind<float>("2 - Interpolation", "InterpolationDuration", 1.5f, "How long it takes the camera to reposition, in seconds.");
InterpolationType = ((BaseUnityPlugin)this).Config.Bind<InterpolationTypeEnum>("2 - Interpolation", "InterpolationType", InterpolationTypeEnum.Decelerate, "How the camera moves when repositioning.");
if (LoadOnStart.Value)
{
Harmony.PatchAll();
LastCameraZoom = CameraZoom.Value;
LastSaddleZoom = SaddleZoom.Value;
LastShipZoom = ShipZoom.Value;
((BaseUnityPlugin)this).Config.SettingChanged += Config_SettingChanged;
}
}
private void OnDestroy()
{
((BaseUnityPlugin)this).Config.SettingChanged -= Config_SettingChanged;
CameraZoom.Value = LastCameraZoom;
SaddleZoom.Value = LastSaddleZoom;
ShipZoom.Value = LastShipZoom;
Harmony.UnpatchSelf();
}
private void Config_SettingChanged(object sender, SettingChangedEventArgs e)
{
if (e.ChangedSetting == InterpolationDuration)
{
if (InterpolationDuration.Value < 0f)
{
InterpolationDuration.Value = 0f;
}
else if (InterpolationDuration.Value > 5f)
{
InterpolationDuration.Value = 5f;
}
}
else if (e.ChangedSetting == CameraZoom)
{
CameraZoom.Value = LastCameraZoom;
}
else if (e.ChangedSetting == SaddleZoom)
{
SaddleZoom.Value = LastSaddleZoom;
}
else if (e.ChangedSetting == ShipZoom)
{
ShipZoom.Value = LastShipZoom;
}
}
}