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 Odins Drunk Cam v0.1.1
plugins/OdinsDrunkCam.dll
Decompiled 17 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using UnityEngine; using UnityEngine.PostProcessing; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("OdinsDrunkCam")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.1.0")] [assembly: AssemblyInformationalVersion("0.1.1+b492ac54fc9a98cad1d68e239cec6f9028af156d")] [assembly: AssemblyProduct("OdinsDrunkCam")] [assembly: AssemblyTitle("OdinsDrunkCam")] [assembly: AssemblyVersion("0.1.1.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 OdinsDrunkCam { internal class DrunkCam : MonoBehaviour { private const float MaxRoll = 18f; private const float MaxPitch = 5f; private const float MaxYaw = 7f; private const float MaxFovPulse = 6f; private const float RollHz = 0.22f; private const float PitchHz = 0.3f; private const float YawHz = 0.17f; private const float FovHz = 0.12f; private const float RiseSeconds = 2.5f; private const float FallSeconds = 4f; private const float HideSeconds = 0.15f; private const float ShowSeconds = 1f; private const float MaxVignette = 0.5f; private static DrunkCam s_instance; private float _level; private float _visible; private float _swayTime; private Transform _swayed; private Quaternion _sober; private Quaternion _drunk; private Camera _fovCam; private Camera _fovSky; private float _soberFov; private float _soberSkyFov; private float _drunkFov; private readonly VignetteControl _vignette = new VignetteControl(); private readonly WaitForEndOfFrame _endOfFrame = new WaitForEndOfFrame(); private float Amount => _level * _visible; private void Awake() { s_instance = this; } private void OnEnable() { ((MonoBehaviour)this).StartCoroutine(RestoreAtEndOfFrame()); } private void OnDisable() { Restore(); _vignette.Release(); } private void OnDestroy() { if ((Object)(object)s_instance == (Object)(object)this) { s_instance = null; } } private void Update() { Restore(); if (ToggleKeyDown()) { Toggle(); } float unscaledDeltaTime = Time.unscaledDeltaTime; Player localPlayer = Player.m_localPlayer; float num = 0f; if (Plugin.Enabled.Value && (Object)(object)localPlayer != (Object)null) { num = Mathf.Min(Plugin.MaxIntensity.Value, Plugin.Intensity.Value * Meads.Drunkenness(localPlayer)); } _level = Approach(_level, num, (num > _level) ? 2.5f : 4f, Time.deltaTime); bool flag = Plugin.Enabled.Value && (Object)(object)localPlayer != (Object)null && CanSway(localPlayer); _visible = Approach(_visible, flag ? 1f : 0f, flag ? 1f : 0.15f, unscaledDeltaTime); if (_level < 0.001f && num <= 0f) { _level = 0f; } if (Amount > 0f) { _swayTime += Time.deltaTime; } _vignette.Apply(Plugin.Vignette.Value ? (Amount * 0.5f) : 0f); } private void Toggle() { bool flag = !Plugin.Enabled.Value; Plugin.Enabled.Value = flag; if (!flag) { _level = 0f; _visible = 0f; Restore(); _vignette.Apply(0f); } MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)1, flag ? "Odin's Drunk Cam: on" : "Odin's Drunk Cam: off. The world holds still.", 0, (Sprite)null, false, true); } } private static bool CanSway(Player player) { if (((Character)player).IsDead() || ((Character)player).InCutscene() || ((Character)player).InIntro() || player.IsSleeping()) { return false; } if (((Character)player).InPlaceMode() || Hud.IsPieceSelectionVisible() || Hud.InRadial()) { return false; } if (GameCamera.InFreeFly()) { return false; } if (!Minimap.IsOpen() && !Menu.IsVisible() && !InventoryGui.IsVisible() && !StoreGui.IsVisible() && !TextInput.IsVisible() && !Console.IsVisible()) { if ((Object)(object)Chat.instance != (Object)null) { return !Chat.instance.HasFocus(); } return true; } return false; } internal static void AfterCameraUpdate(GameCamera camera) { if ((Object)(object)s_instance != (Object)null) { s_instance.Sway(camera); } } private void Sway(GameCamera gameCamera) { //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) //IL_00a2: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) float amount = Amount; if (amount <= 0f || !Plugin.Enabled.Value || GameCamera.InFreeFly()) { return; } Restore(); float swayTime = _swayTime; float num = Wave(swayTime, 0.22f, 0f) * 18f; float num2 = Wave(swayTime, 0.3f, 31.7f) * 5f; float num3 = Wave(swayTime, 0.17f, 77.3f) * 7f; float num4 = Wave(swayTime, 0.12f, 53.9f) * 6f; Transform transform = ((Component)gameCamera).transform; _sober = transform.rotation; _drunk = _sober * Quaternion.Euler(num2 * amount, num3 * amount, num * amount); transform.rotation = _drunk; _swayed = transform; _fovCam = ((Component)gameCamera).GetComponent<Camera>(); _fovSky = gameCamera.m_skyCamera; if ((Object)(object)_fovCam != (Object)null) { _soberFov = _fovCam.fieldOfView; _drunkFov = Mathf.Clamp(_soberFov + num4 * amount, 20f, 140f); _fovCam.fieldOfView = _drunkFov; if ((Object)(object)_fovSky != (Object)null) { _soberSkyFov = _fovSky.fieldOfView; _fovSky.fieldOfView = _drunkFov; } } } private void Restore() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_swayed == (Object)null) { return; } if (_swayed.rotation == _drunk) { _swayed.rotation = _sober; } _swayed = null; if ((Object)(object)_fovCam != (Object)null && Mathf.Approximately(_fovCam.fieldOfView, _drunkFov)) { _fovCam.fieldOfView = _soberFov; if ((Object)(object)_fovSky != (Object)null && Mathf.Approximately(_fovSky.fieldOfView, _drunkFov)) { _fovSky.fieldOfView = _soberSkyFov; } } _fovCam = null; _fovSky = null; } private IEnumerator RestoreAtEndOfFrame() { while (true) { yield return _endOfFrame; Restore(); } } private static float Wave(float t, float hz, float seed) { float num = Mathf.Sin((t * hz + seed) * 2f * (float)Math.PI); float num2 = Mathf.PerlinNoise(t * hz * 0.7f, seed) * 2f - 1f; return Mathf.Clamp(num * 0.65f + num2 * 0.35f, -1f, 1f); } private static float Approach(float from, float to, float seconds, float dt) { if (seconds <= 0f) { return to; } return Mathf.Lerp(from, to, 1f - Mathf.Exp((0f - dt) / seconds)); } private static bool ToggleKeyDown() { //IL_002e: 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_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (TextInput.IsVisible() || Console.IsVisible() || ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())) { return false; } KeyboardShortcut value = Plugin.ToggleKey.Value; if ((int)((KeyboardShortcut)(ref value)).MainKey == 0 || !ZInput.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey, false)) { return false; } foreach (KeyCode modifier in ((KeyboardShortcut)(ref value)).Modifiers) { if (!ZInput.GetKey(modifier, false)) { return false; } } return true; } } [HarmonyPatch(typeof(GameCamera), "UpdateCamera")] internal static class GameCameraUpdatePatch { private static void Postfix(GameCamera __instance) { DrunkCam.AfterCameraUpdate(__instance); } } internal static class Meads { private const float PerMead = 0.4f; private const float FadeOutSeconds = 30f; private static readonly HashSet<int> s_meadEffects = new HashSet<int>(); private static ZNetScene s_builtFor; public static float Drunkenness(Player player) { if (!EnsureBuilt()) { return 0f; } float num = 0f; foreach (StatusEffect statusEffect in ((Character)player).GetSEMan().GetStatusEffects()) { if (!((Object)(object)statusEffect == (Object)null) && s_meadEffects.Contains(statusEffect.NameHash())) { float num2 = ((statusEffect.m_ttl > 0f) ? Mathf.Clamp01(statusEffect.GetRemaningTime() / 30f) : 1f); num += num2; } } return num * 0.4f; } private static bool EnsureBuilt() { ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null) { return false; } if ((Object)(object)s_builtFor == (Object)(object)instance) { return true; } s_meadEffects.Clear(); List<string> list = new List<string>(); foreach (GameObject prefab in instance.m_prefabs) { Fermenter val = (((Object)(object)prefab != (Object)null) ? prefab.GetComponent<Fermenter>() : null); if ((Object)(object)val == (Object)null) { continue; } foreach (ItemConversion item in val.m_conversion) { Add(item?.m_to, list); } } if ((Object)(object)ObjectDB.instance != (Object)null) { foreach (GameObject item2 in ObjectDB.instance.m_items) { if ((Object)(object)item2 != (Object)null && ((Object)item2).name.StartsWith("Mead")) { Add(item2.GetComponent<ItemDrop>(), list); } } } s_builtFor = instance; Plugin.Log.LogInfo((object)string.Format("Found {0} mead effects: {1}", s_meadEffects.Count, string.Join(", ", list))); return true; } private static void Add(ItemDrop drop, List<string> names) { StatusEffect val = ((!((Object)(object)drop != (Object)null)) ? null : drop.m_itemData?.m_shared?.m_consumeStatusEffect); if ((Object)(object)val != (Object)null && s_meadEffects.Add(val.NameHash())) { names.Add(((Object)drop).name + " (" + ((Object)val).name + ")"); } } } [BepInPlugin("hevyh2o.valheim.odinsdrunkcam", "Odin's Drunk Cam", "0.1.1")] public class Plugin : BaseUnityPlugin { public const string Guid = "hevyh2o.valheim.odinsdrunkcam"; public const string Name = "Odin's Drunk Cam"; public const string Version = "0.1.1"; internal static ManualLogSource Log; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<KeyboardShortcut> ToggleKey; internal static ConfigEntry<float> Intensity; internal static ConfigEntry<float> MaxIntensity; internal static ConfigEntry<bool> Vignette; private Harmony _harmony; private DrunkCam _cam; private void Awake() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master switch. When off, the camera is never touched. ToggleKey flips this too."); ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "ToggleKey", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), "Quick-disable: turns the whole effect off at once (no fade-out), or back on. Saved to this file. Can be rebound in game with Configuration Manager (F1)."); Intensity = ((BaseUnityPlugin)this).Config.Bind<float>("Comfort", "Intensity", 1f, new ConfigDescription("How strongly each mead sways the camera. 0.5 = half as much, 3 = three times. Lower it if you get motion sick.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3f), Array.Empty<object>())); MaxIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Comfort", "MaxIntensity", 1f, new ConfigDescription("Hard cap on the effect, however many meads are active. 1 = up to about 18 degrees of roll (three meads at default Intensity). 2 = up to about 36 degrees: properly legless.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 2f), Array.Empty<object>())); Vignette = ((BaseUnityPlugin)this).Config.Bind<bool>("Comfort", "Vignette", true, "Darken the edges of the screen a little while drunk."); _harmony = new Harmony("hevyh2o.valheim.odinsdrunkcam"); _harmony.PatchAll(typeof(Plugin).Assembly); _cam = ((Component)this).gameObject.AddComponent<DrunkCam>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Odin's Drunk Cam 0.1.1 loaded. Odin raises a horn; the horizon raises an eyebrow."); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)_cam != (Object)null) { Object.Destroy((Object)(object)_cam); } } } internal class VignetteControl { private PostProcessingProfile _profile; private bool _wasEnabled; private Settings _original; public void Apply(float strength) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (strength <= 0.001f) { Release(); return; } PostProcessingProfile val = CurrentProfile(); if ((Object)(object)val != (Object)(object)_profile) { Release(); if ((Object)(object)val == (Object)null) { return; } _profile = val; _wasEnabled = ((PostProcessingModel)val.vignette).enabled; _original = val.vignette.settings; } Settings settings = _original; float num = (_wasEnabled ? _original.intensity : 0f); if (!_wasEnabled) { settings = Settings.defaultSettings; settings.smoothness = 0.45f; } settings.intensity = Mathf.Clamp01(num + strength); _profile.vignette.settings = settings; ((PostProcessingModel)_profile.vignette).enabled = true; } public void Release() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_profile != (Object)null) { _profile.vignette.settings = _original; ((PostProcessingModel)_profile.vignette).enabled = _wasEnabled; } _profile = null; } private static PostProcessingProfile CurrentProfile() { CameraEffects instance = CameraEffects.instance; if ((Object)(object)instance == (Object)null) { return null; } PostProcessingBehaviour component = ((Component)instance).GetComponent<PostProcessingBehaviour>(); if (!((Object)(object)component != (Object)null)) { return null; } return component.profile; } } internal static class BuildInfo { public const string Version = "0.1.1"; } }