Move many mods to Deprecated folder, fix spelling

This commit is contained in:
NotAKidoS 2025-04-03 02:57:35 -05:00
parent 5e822cec8d
commit 0042590aa6
539 changed files with 7475 additions and 3120 deletions

View file

@ -0,0 +1,94 @@
using System.Reflection;
using UnityEngine;
namespace NAK.Blackout;
/*
Kindly stolen from SDraw's leap motion mod. (MIT)
https://github.com/SDraw/ml_mods_cvr/blob/master/ml_lme/AssetsHandler.cs
*thank u sdraw, i wont be murderer now*
*/
internal static class AssetsHandler
{
private static readonly List<string> ms_assets = new List<string>()
{
"blackout_controller.asset"
};
private static Dictionary<string, AssetBundle> ms_loadedAssets = new Dictionary<string, AssetBundle>();
private static Dictionary<string, GameObject> ms_loadedObjects = new Dictionary<string, GameObject>();
public static void Load()
{
Assembly l_assembly = Assembly.GetExecutingAssembly();
string l_assemblyName = l_assembly.GetName().Name;
foreach (string l_assetName in ms_assets)
{
try
{
Stream l_assetStream = l_assembly.GetManifestResourceStream(l_assemblyName + ".resources." + l_assetName);
if (l_assetStream != null)
{
MemoryStream l_memorySteam = new MemoryStream((int)l_assetStream.Length);
l_assetStream.CopyTo(l_memorySteam);
AssetBundle l_assetBundle = AssetBundle.LoadFromMemory(l_memorySteam.ToArray(), 0);
if (l_assetBundle != null)
{
l_assetBundle.hideFlags |= HideFlags.DontUnloadUnusedAsset;
ms_loadedAssets.Add(l_assetName, l_assetBundle);
}
else
Blackout.Logger.Warning("Unable to load bundled '" + l_assetName + "' asset");
}
else
Blackout.Logger.Warning("Unable to get bundled '" + l_assetName + "' asset stream");
}
catch (System.Exception e)
{
Blackout.Logger.Warning("Unable to load bundled '" + l_assetName + "' asset, reason: " + e.Message);
}
}
}
public static GameObject GetAsset(string p_name)
{
GameObject l_result = null;
if (ms_loadedObjects.ContainsKey(p_name))
{
l_result = UnityEngine.Object.Instantiate(ms_loadedObjects[p_name]);
l_result.SetActive(true);
l_result.hideFlags |= HideFlags.DontUnloadUnusedAsset;
}
else
{
foreach (var l_pair in ms_loadedAssets)
{
if (l_pair.Value.Contains(p_name))
{
GameObject l_bundledObject = (GameObject)l_pair.Value.LoadAsset(p_name, typeof(GameObject));
if (l_bundledObject != null)
{
ms_loadedObjects.Add(p_name, l_bundledObject);
l_result = UnityEngine.Object.Instantiate(l_bundledObject);
l_result.SetActive(true);
l_result.hideFlags |= HideFlags.DontUnloadUnusedAsset;
}
break;
}
}
}
return l_result;
}
public static void Unload()
{
foreach (var l_pair in ms_loadedAssets)
UnityEngine.Object.Destroy(l_pair.Value);
ms_loadedAssets.Clear();
}
}

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<EmbeddedResource Include="resources\blackout_controller.asset"/>
</ItemGroup>
<ItemGroup>
<Compile Update="Resource1.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Resource1.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resource1.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource1.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
</Project>

View file

@ -0,0 +1,323 @@
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using ABI_RC.Core.UI;
using MelonLoader;
using System.Text;
using UnityEngine;
namespace NAK.Blackout;
/*
Functionality heavily inspired by VRSleeper on Booth: https://booth.pm/ja/items/2151940
There are three states of "blackout":
0 - Awake (no effect)
1 - Drowsy (partial effect)
2 - Sleep (full effect)
After staying still for DrowsyModeTimer (minutes), you enter DrowsyMode.
This mode dims the screen to your selected dimming strength.
After continuing to stay still for SleepModeTimer (seconds), you enter SleepMode.
This mode overrenders mostly everything with black.
Slight movement while in SleepMode will place you in DrowsyMode until SleepModeTimer is reached again.
Hard movement once entering DrowsyMode will fully wake you and return complete vision.
*/
public class BlackoutController : MonoBehaviour
{
public static BlackoutController Instance;
// The current state of the player's consciousness.
public BlackoutState CurrentState = BlackoutState.Awake;
// Should the states automatically change based on time?
public bool AutomaticStateChange = true;
// Should the sleep state be automatically transitioned to? Some may prefer drowsy state only due to dimming.
public bool AutoSleepState = true;
// The minimum amount of movement required to partially restore vision.
public float drowsyThreshold = 2f;
// The minimum amount of movement required to fully restore vision.
public float wakeThreshold = 4f;
// The amount of time the player must remain still to enter drowsy state (in minutes).
public float DrowsyModeTimer = 3f;
// The amount of time the player must remain in drowsy state before entering sleep state (in seconds).
public float SleepModeTimer = 10f;
// The amount by which DrowsyMode affects the screen.
public float DrowsyDimStrength = 0.6f;
// Should DrowsyDimStrength be affected by velocity?
public bool DrowsyVelocityMultiplier = true;
// Whether to display HUD messages.
public bool HudMessages = true;
// Whether to lower the frame rate while in sleep mode.
public bool DropFPSOnSleep = false;
// The available states of consciousness.
public enum BlackoutState
{
Awake = 0,
Drowsy,
Sleeping,
}
private Camera activeModeCam;
private Vector3 headVelocity = Vector3.zero;
private Vector3 lastHeadPos = Vector3.zero;
private float curTime = 0f;
private float lastAwakeTime = 0f;
private Animator blackoutAnimator;
private int targetFPS;
public void ChangeBlackoutStateFromInt(int state) => ChangeBlackoutState((BlackoutState)state);
// Changes the player's state of consciousness.
public void ChangeBlackoutState(BlackoutState newState)
{
if (!blackoutAnimator) return;
if (newState == CurrentState) return;
lastAwakeTime = curTime;
// Update the blackout animator based on the new state.
switch (newState)
{
case BlackoutState.Awake:
blackoutAnimator.SetBool("BlackoutState.Drowsy", false);
blackoutAnimator.SetBool("BlackoutState.Sleeping", false);
drowsyMagnitude = 0f;
break;
case BlackoutState.Drowsy:
blackoutAnimator.SetBool("BlackoutState.Drowsy", true);
blackoutAnimator.SetBool("BlackoutState.Sleeping", false);
drowsyMagnitude = 0f;
break;
case BlackoutState.Sleeping:
blackoutAnimator.SetBool("BlackoutState.Drowsy", false);
blackoutAnimator.SetBool("BlackoutState.Sleeping", true);
drowsyMagnitude = 1f;
break;
default:
break;
}
// Update the current state and send a HUD message if enabled.
BlackoutState prevState = CurrentState;
CurrentState = newState;
SendHUDMessage($"Exiting {prevState} and entering {newState} state.");
ChangeTargetFPS();
}
public void AdjustDrowsyDimStrength(float multiplier = 1f)
{
blackoutAnimator.SetFloat("BlackoutSetting.DrowsyStrength", DrowsyDimStrength * multiplier);
}
// Initialize the BlackoutInstance object.
private void Start()
{
Instance = this;
// Get the blackout asset and instantiate it.
GameObject blackoutAsset = AssetsHandler.GetAsset("Assets/BundledAssets/Blackout/Blackout.prefab");
GameObject blackoutGO = Instantiate(blackoutAsset, new Vector3(0, 0, 0), Quaternion.identity);
blackoutGO.name = "BlackoutInstance";
// Get the blackout animator component.
blackoutAnimator = blackoutGO.GetComponent<Animator>();
if (!blackoutAnimator)
{
Blackout.Logger.Error("Blackout: Could not find blackout animator component!");
return;
}
SetupBlackoutInstance();
//we dont want this to ever disable
Camera.onPreRender += OnPreRender;
Camera.onPostRender += OnPostRender;
}
//Automatic State Change
private void Update()
{
//get the current position of the player's head
Vector3 curHeadPos = activeModeCam.transform.position;
//calculate the player's head velocity by taking the difference in position
headVelocity = (curHeadPos - lastHeadPos) / Time.deltaTime;
//store the current head position for use in the next frame
lastHeadPos = curHeadPos;
if (AutomaticStateChange)
{
curTime = Time.time;
//handle current state
switch (CurrentState)
{
case BlackoutState.Awake:
HandleAwakeState();
break;
case BlackoutState.Drowsy:
HandleDrowsyState();
break;
case BlackoutState.Sleeping:
HandleSleepingState();
break;
default:
break;
}
}
else
{
CalculateDimmingMultiplier();
}
}
public void OnEnable()
{
curTime = Time.time;
lastAwakeTime = curTime;
}
public void OnDisable()
{
ChangeBlackoutState(BlackoutState.Awake);
}
private void OnPreRender(Camera cam)
{
if (cam == activeModeCam) return;
blackoutAnimator.transform.localScale = Vector3.zero;
}
private void OnPostRender(Camera cam)
{
blackoutAnimator.transform.localScale = Vector3.one;
}
public void SetupBlackoutInstance()
{
activeModeCam = PlayerSetup.Instance.GetActiveCamera().GetComponent<Camera>();
blackoutAnimator.transform.parent = activeModeCam.transform;
blackoutAnimator.transform.localPosition = Vector3.zero;
blackoutAnimator.transform.localRotation = Quaternion.identity;
blackoutAnimator.transform.localScale = Vector3.one;
}
private float GetNextStateTimer()
{
switch (CurrentState)
{
case BlackoutState.Awake:
return (lastAwakeTime + DrowsyModeTimer * 60 - curTime);
case BlackoutState.Drowsy:
return (lastAwakeTime + SleepModeTimer - curTime);
case BlackoutState.Sleeping:
return 0f;
default:
return 0f;
}
}
//broken, needs to run next frame
private void SendHUDMessage(string message)
{
Blackout.Logger.Msg(message);
if (!CohtmlHud.Instance || !HudMessages) return;
StringBuilder secondmessage = new StringBuilder();
if (AutomaticStateChange)
{
if (CurrentState == BlackoutState.Drowsy && !AutoSleepState)
{
secondmessage = new StringBuilder("AutoSleepState is disabled. Staying in Drowsy State.");
}
else
{
secondmessage = new StringBuilder(GetNextStateTimer().ToString() + " seconds till next state change.");
}
}
CohtmlHud.Instance.ViewDropTextImmediate("Blackout", message, secondmessage.ToString());
}
private void ChangeTargetFPS()
{
if (!DropFPSOnSleep) return;
//store target FPS to restore, i check each time just in case it changed
targetFPS = MetaPort.Instance.settings.GetSettingInt("GraphicsFramerateTarget", 0);
Application.targetFrameRate = (CurrentState == BlackoutState.Sleeping) ? 5 : targetFPS;
}
private void HandleAwakeState()
{
//small movement should reset sleep timer
if (headVelocity.magnitude > drowsyThreshold)
{
lastAwakeTime = curTime;
}
//enter drowsy mode after few minutes
if (curTime > lastAwakeTime + DrowsyModeTimer * 60)
{
ChangeBlackoutState(BlackoutState.Drowsy);
}
}
public float fadeSpeed = 0.8f; // The speed at which the value fades back to 0 or increases
public float minimumThreshold = 0.5f; // The minimum value that the drowsy magnitude can have
public float drowsyMagnitude = 0f;
private void CalculateDimmingMultiplier()
{
if (!DrowsyVelocityMultiplier)
{
AdjustDrowsyDimStrength();
return;
}
float normalizedMagnitude = headVelocity.magnitude / wakeThreshold;
float targetMagnitude = 1f - normalizedMagnitude;
targetMagnitude = Mathf.Max(targetMagnitude, minimumThreshold);
drowsyMagnitude = Mathf.Lerp(drowsyMagnitude, targetMagnitude, fadeSpeed * Time.deltaTime);
AdjustDrowsyDimStrength(drowsyMagnitude);
}
private void HandleDrowsyState()
{
//hard movement should exit drowsy state
if (headVelocity.magnitude > wakeThreshold)
{
ChangeBlackoutState(BlackoutState.Awake);
return;
}
//small movement should reset sleep timer
if (headVelocity.magnitude > drowsyThreshold)
{
lastAwakeTime = curTime;
}
//enter full sleep mode
if (AutoSleepState && curTime > lastAwakeTime + SleepModeTimer)
{
ChangeBlackoutState(BlackoutState.Sleeping);
}
CalculateDimmingMultiplier();
}
private void HandleSleepingState()
{
//small movement should enter drowsy state
if (headVelocity.magnitude > drowsyThreshold)
{
ChangeBlackoutState(BlackoutState.Drowsy);
}
}
}

View file

@ -0,0 +1,23 @@
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using HarmonyLib;
namespace NAK.Blackout.HarmonyPatches;
[HarmonyPatch]
internal class HarmonyPatches
{
//Support for changing VRMode during runtime.
[HarmonyPostfix]
[HarmonyPatch(typeof(PlayerSetup), nameof(PlayerSetup.CalibrateAvatar))]
private static void CheckVRModeOnSwitch()
{
if (Blackout.inVR != MetaPort.Instance.isUsingVr)
{
Blackout.Logger.Msg("VRMode change detected! Reinitializing Blackout Instance...");
Blackout.inVR = MetaPort.Instance.isUsingVr;
BlackoutController.Instance.SetupBlackoutInstance();
BlackoutController.Instance.ChangeBlackoutState(BlackoutController.BlackoutState.Awake);
}
}
}

View file

@ -0,0 +1,63 @@
using BTKUILib;
using BTKUILib.UIObjects;
using System.Runtime.CompilerServices;
namespace NAK.Blackout;
public static class BTKUIAddon
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Init()
{
//Add myself to the Misc Menu
Page miscPage = QuickMenuAPI.MiscTabPage;
Category miscCategory = miscPage.AddCategory(Blackout.SettingsCategory);
AddMelonToggle(ref miscCategory, Blackout.EntryEnabled);
//Add my own page to not clog up Misc Menu
Page blackoutPage = miscCategory.AddPage("Blackout Settings", "", "Configure the settings for Blackout.", "Blackout");
blackoutPage.MenuTitle = "Blackout Settings";
blackoutPage.MenuSubtitle = "Dim screen after set time of sitting still, or configure with manual control. Should be nice for VR sleeping.";
Category blackoutCategory = blackoutPage.AddCategory("Blackout");
AddMelonToggle(ref blackoutCategory, Blackout.EntryEnabled);
//manual state changing
var state_Awake = blackoutCategory.AddButton("Awake State", null, "Enter the Awake State.");
state_Awake.OnPress += () => BlackoutController.Instance?.ChangeBlackoutState(BlackoutController.BlackoutState.Awake);
var state_Drowsy = blackoutCategory.AddButton("Drowsy State", null, "Enter the Drowsy State.");
state_Drowsy.OnPress += () => BlackoutController.Instance?.ChangeBlackoutState(BlackoutController.BlackoutState.Drowsy);
var state_Sleeping = blackoutCategory.AddButton("Sleeping State", null, "Enter the Sleeping State.");
state_Sleeping.OnPress += () => BlackoutController.Instance?.ChangeBlackoutState(BlackoutController.BlackoutState.Sleeping);
//dimming strength
AddMelonSlider(ref blackoutPage, Blackout.EntryDrowsyDimStrength, 0f, 1f);
//velocity dim multiplier
AddMelonToggle(ref blackoutCategory, Blackout.EntryDrowsyVelocityMultiplier);
//hud messages
AddMelonToggle(ref blackoutCategory, Blackout.EntryHudMessages);
//lower fps while sleep (desktop)
AddMelonToggle(ref blackoutCategory, Blackout.EntryDropFPSOnSleep);
//auto sleep state
AddMelonToggle(ref blackoutCategory, Blackout.EntryAutoSleepState);
//i will add the rest of the settings once BTKUILib supports int input
}
private static void AddMelonToggle(ref Category category, MelonLoader.MelonPreferences_Entry<bool> entry)
{
category.AddToggle(entry.DisplayName, entry.Description, entry.Value).OnValueUpdated += b => entry.Value = b;
}
private static void AddMelonSlider(ref Page page, MelonLoader.MelonPreferences_Entry<float> entry, float min, float max)
{
page.AddSlider(entry.DisplayName, entry.Description, entry.Value, min, max).OnValueUpdated += f => entry.Value = f;
}
}

View file

@ -0,0 +1,28 @@
using System.Runtime.CompilerServices;
using UIExpansionKit.API;
namespace NAK.Blackout;
public static class UIExpansionKitAddon
{
[MethodImpl(MethodImplOptions.NoInlining)]
public static void Init()
{
/**
ive spent hours debugging this, and no matter what the buttons wont actually call the actions
from logging shit to straight up closing the game, nothing
implementing btkuilib support, but gonna leave this shit as a reminder why to not use uiexpansionkit
also because it **used to work**... a game update broke it and uiexpansionkit hasnt updated since
what pisses me off more, is that DesktopVRSwitch works, and that was originally copied from Blackout -_-
**/
var settings = ExpansionKitApi.GetSettingsCategory(Blackout.SettingsCategory);
settings.AddSimpleButton("Awake State", AwakeState);
settings.AddSimpleButton("Drowsy State", DrowsyState);
settings.AddSimpleButton("Sleep State", SleepingState);
}
//UIExpansionKit actions
internal static void AwakeState() => BlackoutController.Instance?.ChangeBlackoutState(BlackoutController.BlackoutState.Awake);
internal static void DrowsyState() => BlackoutController.Instance?.ChangeBlackoutState(BlackoutController.BlackoutState.Drowsy);
internal static void SleepingState() => BlackoutController.Instance?.ChangeBlackoutState(BlackoutController.BlackoutState.Sleeping);
}

View file

@ -0,0 +1,124 @@
using ABI_RC.Core.Player;
using ABI_RC.Core.Savior;
using MelonLoader;
namespace NAK.Blackout;
public class Blackout : MelonMod
{
internal static bool inVR;
internal static MelonLogger.Instance Logger;
internal const string SettingsCategory = nameof(Blackout);
public static readonly MelonPreferences_Category CategoryBlackout =
MelonPreferences.CreateCategory(SettingsCategory);
public static readonly MelonPreferences_Entry<bool> EntryEnabled =
CategoryBlackout.CreateEntry("Automatic State Change", true, description: "Should the screen automatically dim if head is still for enough time?");
public static readonly MelonPreferences_Entry<bool> EntryHudMessages =
CategoryBlackout.CreateEntry("Hud Messages", true, description: "Notify on state change.");
public static readonly MelonPreferences_Entry<bool> EntryDropFPSOnSleep =
CategoryBlackout.CreateEntry("Limit FPS While Sleep", false, description: "Limits FPS to 5 while in Sleep State. This only works in Desktop, as SteamVR/HMD handles VR FPS.");
public static readonly MelonPreferences_Entry<bool> EntryDrowsyVelocityMultiplier =
CategoryBlackout.CreateEntry("Drowsy Velocity Multiplier", true, description: "Should head velocity act as a multiplier to Drowsy Dim Strength?");
public static readonly MelonPreferences_Entry<bool> EntryAutoSleepState =
CategoryBlackout.CreateEntry("Auto Sleep State", true, description: "Should the sleep state be used during Automatic State Change?");
public static readonly MelonPreferences_Entry<float> EntryDrowsyThreshold =
CategoryBlackout.CreateEntry("Drowsy Threshold", 2f, description: "Velocity to return partial vision.");
public static readonly MelonPreferences_Entry<float> EntryAwakeThreshold =
CategoryBlackout.CreateEntry("Awake Threshold", 4f, description: "Velocity to return full vision.");
public static readonly MelonPreferences_Entry<float> EntryDrowsyModeTimer =
CategoryBlackout.CreateEntry("Enter Drowsy Time (Minutes)", 3f, description: "How many minutes without movement until enter drowsy mode.");
public static readonly MelonPreferences_Entry<float> EntrySleepModeTimer =
CategoryBlackout.CreateEntry("Enter Sleep Time (Seconds)", 10f, description: "How many seconds without movement until enter sleep mode.");
public static readonly MelonPreferences_Entry<float> EntryDrowsyDimStrength =
CategoryBlackout.CreateEntry("Drowsy Dim Strength", 0.6f, description: "How strong of a dimming effect should drowsy mode have.");
public override void OnInitializeMelon()
{
Logger = LoggerInstance;
EntryEnabled.OnEntryValueChangedUntyped.Subscribe(OnUpdateEnabled);
foreach (var entry in CategoryBlackout.Entries)
{
if (entry != EntryEnabled && !entry.OnEntryValueChangedUntyped.GetSubscribers().Any())
{
entry.OnEntryValueChangedUntyped.Subscribe(OnUpdateSettings);
}
}
//UIExpansionKit addon
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "UI Expansion Kit"))
{
Logger.Msg("Initializing UIExpansionKit support.");
UIExpansionKitAddon.Init();
}
//BTKUILib addon
if (MelonMod.RegisteredMelons.Any(it => it.Info.Name == "BTKUILib"))
{
Logger.Msg("Initializing BTKUILib support.");
BTKUIAddon.Init();
}
MelonLoader.MelonCoroutines.Start(WaitForLocalPlayer());
}
private System.Collections.IEnumerator WaitForLocalPlayer()
{
//load blackout_controller.asset
AssetsHandler.Load();
while (PlayerSetup.Instance == null)
yield return null;
inVR = MetaPort.Instance.isUsingVr;
PlayerSetup.Instance.gameObject.AddComponent<BlackoutController>();
//update BlackoutController settings after it initializes
while (BlackoutController.Instance == null)
yield return null;
UpdateAllSettings();
OnEnabled();
}
private void OnEnabled()
{
if (!BlackoutController.Instance) return;
if (EntryEnabled.Value)
{
BlackoutController.Instance.OnEnable();
}
else
{
BlackoutController.Instance.OnDisable();
}
BlackoutController.Instance.AutomaticStateChange = EntryEnabled.Value;
}
private void UpdateAllSettings()
{
if (!BlackoutController.Instance) return;
BlackoutController.Instance.HudMessages = EntryHudMessages.Value;
BlackoutController.Instance.AutoSleepState = EntryAutoSleepState.Value;
BlackoutController.Instance.DropFPSOnSleep = EntryDropFPSOnSleep.Value;
BlackoutController.Instance.drowsyThreshold = EntryDrowsyThreshold.Value;
BlackoutController.Instance.wakeThreshold = EntryAwakeThreshold.Value;
BlackoutController.Instance.DrowsyModeTimer = EntryDrowsyModeTimer.Value;
BlackoutController.Instance.SleepModeTimer = EntrySleepModeTimer.Value;
BlackoutController.Instance.DrowsyDimStrength = EntryDrowsyDimStrength.Value;
BlackoutController.Instance.DrowsyVelocityMultiplier = EntryDrowsyVelocityMultiplier.Value;
}
private void OnUpdateEnabled(object arg1, object arg2) => OnEnabled();
private void OnUpdateSettings(object arg1, object arg2) => UpdateAllSettings();
}

View file

@ -0,0 +1,31 @@
using MelonLoader;
using NAK.Blackout.Properties;
using System.Reflection;
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
[assembly: AssemblyTitle(nameof(NAK.Blackout))]
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
[assembly: AssemblyProduct(nameof(NAK.Blackout))]
[assembly: MelonInfo(
typeof(NAK.Blackout.Blackout),
nameof(NAK.Blackout),
AssemblyInfoParams.Version,
AssemblyInfoParams.Author,
downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/Blackout"
)]
[assembly: MelonGame("Alpha Blend Interactive", "ChilloutVR")]
[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]
[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)]
[assembly: MelonOptionalDependencies("UIExpansionKit", "BTKUILib")]
namespace NAK.Blackout.Properties;
internal static class AssemblyInfoParams
{
public const string Version = "2.0.0";
public const string Author = "NotAKidoS";
}

View file

@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace NAK.Blackout {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resource1 {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resource1() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Blackout.Resource1", typeof(Resource1).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Looks up a localized resource of type System.Byte[].
/// </summary>
internal static byte[] blackout_controller {
get {
object obj = ResourceManager.GetObject("blackout_controller", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View file

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="blackout_controller" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\blackout_controller.asset;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View file

@ -0,0 +1,24 @@
{
"_id": 106,
"name": "Blackout",
"modversion": "2.0.0",
"gameversion": "2022r170p1",
"loaderversion": "0.6.1",
"modtype": "Mod",
"author": "NotAKidoS",
"description": "Dim screen after set time of sitting still. Should be nice for VR sleeping.\n\nNotable Options:\n Cap FPS while sleeping.\nManual control via BTKUILib\nConfigurable dimming strength.",
"searchtags": [
"black",
"dimmer",
"sleeping",
"sleeper"
],
"requirements": [
"BTKUILib",
"UIExpansionKit"
],
"downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r3/Blackout.dll",
"sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/Blackout/",
"changelog": "- Added BTKUILib support.\n- Added dimming strength velocity multiplier option.\n- Added option to not use Automatic Sleep State.\n- Dimming strengh now updates in realtime when configuring.",
"embedcolor": "#161b22"
}