diff --git a/.Deprecated/ComfortAlignment/ComfortAlignment.csproj b/.Deprecated/ComfortAlignment/ComfortAlignment.csproj new file mode 100644 index 0000000..fa113da --- /dev/null +++ b/.Deprecated/ComfortAlignment/ComfortAlignment.csproj @@ -0,0 +1,12 @@ + + + + ASTExtension + + + + ..\.ManagedLibs\BTKUILib.dll + False + + + diff --git a/.Deprecated/ComfortAlignment/Main.cs b/.Deprecated/ComfortAlignment/Main.cs new file mode 100644 index 0000000..248b316 --- /dev/null +++ b/.Deprecated/ComfortAlignment/Main.cs @@ -0,0 +1,166 @@ +using System.Reflection; +using ABI_RC.Core; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Systems.Movement; +using ABI_RC.Systems.PersonalPen; +using ABI_RC.Systems.UI.UILib; +using ABI_RC.Systems.UI.UILib.UIObjects; +using ABI_RC.Systems.UI.UILib.UIObjects.Components; +using ABI_RC.Systems.XRManagement; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace NAK.ComfortAlignment; + +public class ComfortAlignmentMod : MelonMod +{ + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(ComfortAlignment)); + + private static readonly MelonPreferences_Entry HiddenAcceptedMotionSicknessWarning = + Category.CreateEntry( + identifier: "accepted_warning", + false, + display_name: "Motion Sickness Warning", + description: string.Empty, + is_hidden: true); + + private static readonly MelonPreferences_Entry EntrySnapAlignment = + Category.CreateEntry( + identifier: "snap_alignment", + false, + display_name: "Snap Alignment", + description: "Should the alignment be locked to 90 degrees."); + + public override void OnInitializeMelon() + { + HarmonyInstance.Patch( + typeof(PenManager).GetMethod(nameof(PenManager.SetupUILib), + BindingFlags.Public | BindingFlags.Static), + postfix: new HarmonyMethod(typeof(ComfortAlignmentMod).GetMethod(nameof(OnSetupUILib), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + XRDeviceEvents.OnPostXRModeSwitch.AddListener(OnPostXRModeSwitch); + } + + private static Category _category; + private static ToggleButton _enableToggle; + private static Button _alignToHorizon; + private static Button _resetHorizon; + private static ToggleButton _snappingToggle; + + private static void OnSetupUILib() + { + _category = QuickMenuAPI.CVRUtilsPage.AddCategory("Comfort Alignment", true, true); + _category.Hidden = !MetaPort.Instance.isUsingVr; + + _enableToggle = _category.AddToggle("Accepted Warning", "Enables the comfort alignment feature.", HiddenAcceptedMotionSicknessWarning.Value); + _enableToggle.OnValueUpdated += OnEnableToggled; + + _alignToHorizon = _category.AddButton("Align To Horizon", "Visibility", "Aligns your view to the horizon"); + _alignToHorizon.OnPress += () => RootLogic.RunInMainThread(AlignHorizon); // scheduled to apply early next frame, to avoid visual jitter + _alignToHorizon.Disabled = !HiddenAcceptedMotionSicknessWarning.Value; + + _resetHorizon = _category.AddButton("Reset Horizon", "Visibility", "Resets your view"); + _resetHorizon.OnPress += () => RootLogic.RunInMainThread(ResetHorizon); // scheduled to apply early next frame, to avoid visual jitter + _resetHorizon.Disabled = true; + + _snappingToggle = _category.AddToggle(EntrySnapAlignment.DisplayName, EntrySnapAlignment.Description, EntrySnapAlignment.Value); + _snappingToggle.OnValueUpdated += (t) => EntrySnapAlignment.Value = t; + _snappingToggle.Disabled = !HiddenAcceptedMotionSicknessWarning.Value; + } + + private static void OnEnableToggled(bool enabled) + { + if (enabled) + { + QuickMenuAPI.ShowConfirm( + "Motion Sickness Warning", + "This feature adjusts your playspace orientation to align your view with the world horizon, improving accessibility when playing while reclining or lying down. It may cause motion sickness, dizziness, disorientation, or vertigo, particularly for users sensitive to motion or those new to virtual reality. Enable anyway?", + () => SetFeatureEnabled(true), + () => _enableToggle.ToggleValue = false); + } + else + { + SetFeatureEnabled(false); + } + } + + private static void SetFeatureEnabled(bool enabled) + { + _alignToHorizon.Disabled = !enabled; + _snappingToggle.Disabled = !enabled; + HiddenAcceptedMotionSicknessWarning.Value = enabled; + if (!enabled && !_resetHorizon.Disabled) ResetHorizon(); + } + + private static void OnPostXRModeSwitch(XRModeSwitchEventArgs events) + { + _category.Hidden = !events.IsUsingVr; + if (events.WasUsingVr) ResetHorizonWithoutTeleport(); + } + + private static void AlignHorizon() + { + _resetHorizon.Disabled = false; + + // cache original pos to reapply after offsetting vr rig + Vector3 playerPos = PlayerSetup.Instance.GetPlayerPosition(); + Quaternion playerRot = PlayerSetup.Instance.GetPlayerRotation(); + + bool snapAlignment = EntrySnapAlignment.Value; + + // pivot point + Vector3 camPos = PlayerSetup.Instance.vrCam.transform.position; + + // what we are aligning from + Vector3 camUp = PlayerSetup.Instance.vrCam.transform.up; + Vector3 camForward = PlayerSetup.Instance.vrCam.transform.forward; + + // what we're aligning to + Vector3 playerUp = PlayerSetup.Instance.transform.up; + Vector3 playerForward = PlayerSetup.Instance.GetPlayerForward(); + + Quaternion correction = Quaternion.FromToRotation(camUp, playerUp); + + if (snapAlignment) + { + Vector3 refForward = Vector3.ProjectOnPlane(playerForward, playerUp); + Vector3 flatForward = Vector3.ProjectOnPlane(correction * camForward, playerUp); + if (refForward.sqrMagnitude > 1e-6f && flatForward.sqrMagnitude > 1e-6f) + { + float yaw = Vector3.SignedAngle(refForward, flatForward, playerUp); + float deltaYaw = Mathf.DeltaAngle(yaw, Mathf.Round(yaw / 90f) * 90f); + correction = Quaternion.AngleAxis(deltaYaw, playerUp) * correction; + } + } + + correction.ToAngleAxis(out float angle, out Vector3 axis); + if (angle != 0f) PlayerSetup.Instance.vrCameraRig.transform.RotateAround(camPos, axis, angle); + + // reapply player positions (internally re-centers and whatever) + BetterBetterCharacterController.Instance.TeleportPlayerTo(playerPos, playerRot.eulerAngles, false, false); + } + + private static void ResetHorizon() + { + _resetHorizon.Disabled = true; + + // cache original pos to reapply after offsetting vr rig + Vector3 playerPos = PlayerSetup.Instance.GetPlayerPosition(); + Quaternion playerRot = PlayerSetup.Instance.GetPlayerRotation(); + + PlayerSetup.Instance.vrCameraRig.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); + + // reapply player positions (internally re-centers and whatever) + BetterBetterCharacterController.Instance.TeleportPlayerTo(playerPos, playerRot.eulerAngles, false, false); + } + + private static void ResetHorizonWithoutTeleport() + { + _resetHorizon.Disabled = true; + PlayerSetup.Instance.vrCameraRig.transform.SetLocalPositionAndRotation(Vector3.zero, Quaternion.identity); + } +} \ No newline at end of file diff --git a/.Deprecated/ComfortAlignment/Properties/AssemblyInfo.cs b/.Deprecated/ComfortAlignment/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f5479c8 --- /dev/null +++ b/.Deprecated/ComfortAlignment/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.ComfortAlignment.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.ComfortAlignment))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.ComfortAlignment))] + +[assembly: MelonInfo( + typeof(NAK.ComfortAlignment.ComfortAlignmentMod), + nameof(NAK.ComfortAlignment), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ComfortAlignment" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.ComfortAlignment.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/ComfortAlignment/README.md b/.Deprecated/ComfortAlignment/README.md new file mode 100644 index 0000000..399e70a --- /dev/null +++ b/.Deprecated/ComfortAlignment/README.md @@ -0,0 +1,54 @@ +# ASTExtension + +Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool): +- VR Gesture to scale +- Persistent height +- Copy height from others + +Best used with Avatar Scale Tool, but will attempt to work with found scaling setups. +Requires already having Avatar Scaling on the avatar. This is **not** Universal Scaling. + +## Supported Setups + +ASTExtension will attempt to work with the following setups: + +**Parameter Names:** +- AvatarScale +- Scale +- Scaler +- Scale/Scale +- Height +- LoliModifier +- AvatarSize +- Size +- SizeScale +- Scaling + +These parameter names are not case sensitive and have been gathered from polling the community for common parameter names. + +Assuming the parameter is a float, ASTExtension will attempt to use it as the height parameter. Will automatically calibrate to the height range of the found parameter, assuming the scaling animation is in a blend tree / state using motion time & is linear. The scaling animation state **must be active** at time of avatar load. + +The max value ASTExtension will drive the parameter to is 100. As the mod is having to guess the max height, it may not be accurate if the max height is not capped at a multiple of 10. + +Examples: +- `AvatarScale` - 0 to 1 (slider) + - This is the default setup for Avatar Scale Tool and will work perfectly. +- `Scale` - 0 to 100 (input single) + - This will also work perfectly as the max height is a multiple of 10. +- `Height` - 0 to 2 (input single) + - This will not work properly. The max value to drive the parameter to is not a multiple of 10, and as such ASTExtension will believe the parameter range is 0 to 1. +- `BurntToast` - 0 to 10 (input single) + - This will not work properly. The parameter name is not recognized by ASTExtension. + +If your setup is theoretically supported but not working, it is likely the scaling animation is not linear or has loop enabled if using Motion Time, making the first and last frame identical height. In this case, you will need to fix your animation clip curves / blend tree to be linear &|| not loop, or use Avatar Scale Tool to generate a new scaling animation. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/ComfortAlignment/format.json b/.Deprecated/ComfortAlignment/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/.Deprecated/ComfortAlignment/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/ConfigureCalibrationPose/ConfigureCalibrationPose.csproj b/.Deprecated/ConfigureCalibrationPose/ConfigureCalibrationPose.csproj similarity index 100% rename from ConfigureCalibrationPose/ConfigureCalibrationPose.csproj rename to .Deprecated/ConfigureCalibrationPose/ConfigureCalibrationPose.csproj diff --git a/ConfigureCalibrationPose/Main.cs b/.Deprecated/ConfigureCalibrationPose/Main.cs similarity index 100% rename from ConfigureCalibrationPose/Main.cs rename to .Deprecated/ConfigureCalibrationPose/Main.cs diff --git a/ConfigureCalibrationPose/Properties/AssemblyInfo.cs b/.Deprecated/ConfigureCalibrationPose/Properties/AssemblyInfo.cs similarity index 100% rename from ConfigureCalibrationPose/Properties/AssemblyInfo.cs rename to .Deprecated/ConfigureCalibrationPose/Properties/AssemblyInfo.cs diff --git a/ConfigureCalibrationPose/README.md b/.Deprecated/ConfigureCalibrationPose/README.md similarity index 100% rename from ConfigureCalibrationPose/README.md rename to .Deprecated/ConfigureCalibrationPose/README.md diff --git a/ConfigureCalibrationPose/format.json b/.Deprecated/ConfigureCalibrationPose/format.json similarity index 100% rename from ConfigureCalibrationPose/format.json rename to .Deprecated/ConfigureCalibrationPose/format.json diff --git a/.Deprecated/DefaultDynamicBoneWind/DefaultDynamicBoneWind.csproj b/.Deprecated/DefaultDynamicBoneWind/DefaultDynamicBoneWind.csproj new file mode 100644 index 0000000..1543f45 --- /dev/null +++ b/.Deprecated/DefaultDynamicBoneWind/DefaultDynamicBoneWind.csproj @@ -0,0 +1,14 @@ + + + + YouAreMineNow + + + + + + + Plugins\Tomlet.dll + + + diff --git a/.Deprecated/DefaultDynamicBoneWind/Main.cs b/.Deprecated/DefaultDynamicBoneWind/Main.cs new file mode 100644 index 0000000..873e785 --- /dev/null +++ b/.Deprecated/DefaultDynamicBoneWind/Main.cs @@ -0,0 +1,30 @@ +using ABI_RC.Core.Savior; +using MelonLoader; +using UnityEngine; + +namespace NAK.DefaultDynamicBoneWind; + +public class DefaultDynamicBoneWindMod : MelonMod +{ + internal static MelonLogger.Instance Logger; + + public override void OnInitializeMelon() + { + Logger = LoggerInstance; + + CVRGameSettings.Init(); + + CVRGameSettings.CoolBool.OnChanged += ShitChanged; + CVRGameSettings.Microphone.OnChanged += ShitChanged; + } + + private static void ShitChanged(Color old, Color now) => Logger.Msg($"Shit changed: {old} has now become {now}"); + private static void ShitChanged(string old, string now) => Logger.Msg($"ShitAudio changed: {old} has now become {now}"); + + public override void OnUpdate() + { + if (Input.GetKeyDown(KeyCode.P)) CVRGameSettings.CoolBool.Value = CVRGameSettings.CoolBool.Value == Color.white ? Color.black : Color.white; + if (Input.GetKeyDown(KeyCode.C)) CVRGameSettings.TestSettingsCategory.ResetAll(); + if (Input.GetKeyDown(KeyCode.O)) Logger.Msg($"Setting value: {CVRGameSettings.CoolBool}"); + } +} \ No newline at end of file diff --git a/.Deprecated/DefaultDynamicBoneWind/Plugins/Tomlet.dll b/.Deprecated/DefaultDynamicBoneWind/Plugins/Tomlet.dll new file mode 100644 index 0000000..b84de52 Binary files /dev/null and b/.Deprecated/DefaultDynamicBoneWind/Plugins/Tomlet.dll differ diff --git a/.Deprecated/DefaultDynamicBoneWind/Properties/AssemblyInfo.cs b/.Deprecated/DefaultDynamicBoneWind/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..bde1b73 --- /dev/null +++ b/.Deprecated/DefaultDynamicBoneWind/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.DefaultDynamicBoneWind.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.DefaultDynamicBoneWind))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.DefaultDynamicBoneWind))] + +[assembly: MelonInfo( + typeof(NAK.DefaultDynamicBoneWind.DefaultDynamicBoneWindMod), + nameof(NAK.DefaultDynamicBoneWind), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/DefaultDynamicBoneWind" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.DefaultDynamicBoneWind.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.3"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/DefaultDynamicBoneWind/README.md b/.Deprecated/DefaultDynamicBoneWind/README.md new file mode 100644 index 0000000..1ab0d99 --- /dev/null +++ b/.Deprecated/DefaultDynamicBoneWind/README.md @@ -0,0 +1,14 @@ +# DefaultDynamicBoneWind + +Makes wind influence default enabled for Dynamic Bones. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/DefaultDynamicBoneWind/Settings/CVRGameSettings.cs b/.Deprecated/DefaultDynamicBoneWind/Settings/CVRGameSettings.cs new file mode 100644 index 0000000..f3492fe --- /dev/null +++ b/.Deprecated/DefaultDynamicBoneWind/Settings/CVRGameSettings.cs @@ -0,0 +1,65 @@ +using ABI_RC.Core.Networking.GameServer; +using ABI_RC.Core.Networking.IO.Instancing; +using ABI_RC.Systems.XRManagement; +using UnityEngine; + +namespace ABI_RC.Core.Savior +{ + public static class CVRGameSettings + { + public static readonly CVRSettingsFile GameSettingsFile = new("GameSettings"); + + public static readonly CVRSettingsCategory TestSettingsCategory = + GameSettingsFile.CreateCategory("General", comment: "Test settings") + .WithUI(sortOrder: 0, new UIFilters{ Platform = UIFilters.PlatformType.PCVR }); + + public static readonly CVRSetting CoolBool = + TestSettingsCategory.Create("Setting", Color.white, comment: "A cool toggle") + .WithUI(sortOrder: 0, tooltip: "Pick a color", + filters: new UIFilters { Level = UIFilters.SettingsLevel.Basic }); + + public static readonly CVRSetting NotABool = + TestSettingsCategory.Create("Setting 2", defaultValue: false, comment: "A really cool toggle"); + + public static readonly CVRSettingsCategory Audio = + GameSettingsFile.CreateCategory("Audio", comment: "Audio volume levels", page: "Audio") + .WithUI(sortOrder: 2); + + public static readonly CVRSetting Microphone = + Audio.Create("Microphone", "default", comment: "Active microphone device") + .WithVariant("VR", string.Empty) + .WithUI(sortOrder: 0, tooltip: "Select your microphone device"); + + /// + /// Settings with .WithVariant("VR", ...) or [Category.VR] in TOML respond to this. + /// + public static readonly CVRSettingsContext DeviceMode = new("DeviceMode"); + public static readonly CVRSettingsContext InstancePrivacy = new("InstancePrivacy"); + + public static void Init() + { + GameSettingsFile.SetPath(Path.Combine(Application.persistentDataPath, "GameSettings.toml")); + GameSettingsFile.RegisterContext(DeviceMode); // Listen for .VR setting variants + GameSettingsFile.RegisterContext(InstancePrivacy); // Listen for .Public/.Private setting variants + GameSettingsFile.Load(); + + SetDeviceModeActive(false); + XRDeviceEvents.OnPostXRModeSwitch.AddListener(OnPostXRModeSwitch); + GSInfoHandler.OnGSInfoUpdate += OnGSInfoUpdate; + } + + private static void OnPostXRModeSwitch(XRModeSwitchEventArgs eventArgs) + => SetDeviceModeActive(eventArgs.IsUsingVr); + + private static void OnGSInfoUpdate(GSInfoUpdate gsInfoUpdate, GSInfoChanged gsInfoChanged) + { + if (gsInfoChanged != GSInfoChanged.InstancePrivacy) return; + SetInstancePrivateActive(Instances.IsInPrivateInstance()); + } + + private static void SetDeviceModeActive(bool isUsingVr) + => DeviceMode.Active = isUsingVr ? "VR" : null; + private static void SetInstancePrivateActive(bool isPrivate) + => InstancePrivacy.Active = isPrivate ? "Private" : "Public"; + } +} \ No newline at end of file diff --git a/.Deprecated/DefaultDynamicBoneWind/Settings/CVRSettings.cs b/.Deprecated/DefaultDynamicBoneWind/Settings/CVRSettings.cs new file mode 100644 index 0000000..e4de4bc --- /dev/null +++ b/.Deprecated/DefaultDynamicBoneWind/Settings/CVRSettings.cs @@ -0,0 +1,564 @@ +using ABI_RC.Core.IO; +using ABI_RC.Core.Logger; +using Tomlet; +using Tomlet.Models; + +namespace ABI_RC.Core.Savior +{ + /// + /// A named runtime context. The game sets Active at runtime. + /// Settings with matching variant names update automatically. + /// + public sealed class CVRSettingsContext + { + public readonly string Name; + + private string _active; + + public event Action OnChanged; + + public CVRSettingsContext(string name) => Name = name; + + public string Active + { + get => _active; + set + { + if (_active == value) return; + var old = _active; + _active = value; + OnChanged?.Invoke(old, value); + } + } + } + + /// + /// A .toml file on disk. Contains categories, each a [section]. + /// Variant sub-tables like [Category.VR] are stored within category tables. + /// + public sealed class CVRSettingsFile + { + public readonly string Name; + + internal readonly Dictionary Categories = new(); + internal readonly List Contexts = new(); + internal readonly HashSet VariantSettings = new(); + + private string _path; + private TomlDocument _cached; + private bool _failed; + private bool _threwOnce; + private bool _savePending; + + public bool HasFailed => _failed; + + public CVRSettingsFile(string name) + { + Name = name; + CVRSettingsRegistry.Register(this); + } + + public void SetPath(string filePath) => _path = filePath; + + public CVRSettingsCategory CreateCategory(string name, string comment = null, string page = null) + { + var cat = new CVRSettingsCategory(name, comment, page, this); + Categories[name] = cat; + return cat; + } + + /// + /// Register a context. When Active changes, only settings with variants are notified. + /// + public void RegisterContext(CVRSettingsContext context) + { + if (Contexts.Contains(context)) return; + Contexts.Add(context); + context.OnChanged += (_, _) => + { + foreach (var setting in VariantSettings) + setting.OnContextChanged(); + }; + } + + public void Load() + { + if (_path == null || !File.Exists(_path)) return; + + try + { + var content = File.ReadAllText(_path); + if (string.IsNullOrWhiteSpace(content)) return; + + _cached = new TomlParser().Parse(content); + + foreach (var cat in Categories.Values) + cat.PopulateFromDocument(_cached); + } + catch (Exception e) + { + _failed = true; + CVRLogger.LogError($"[CVRSettings] Failed to load '{_path}': {e}. " + + "Settings will not be saved this session."); + } + } + + public void Save() + { + if (_path == null || _failed) return; + + var doc = TomlDocument.CreateEmpty(); + + foreach (var cat in Categories.Values) + { + var table = new TomlTable(); + if (cat.Comment != null) + table.Comments.PrecedingComment = cat.Comment; + + foreach (var setting in cat.Settings.Values) + { + if (setting.SkipWrite) continue; + var val = setting.ToTomlValue(); + if (val == null) continue; + if (setting.Comment != null) + val.Comments.PrecedingComment = setting.Comment; + table.PutValue(setting.Name, val); + } + + var variantNames = new HashSet(); + foreach (var setting in cat.Settings.Values) + setting.CollectVariantNames(variantNames); + + foreach (var variantName in variantNames) + { + var variantTable = new TomlTable { ForceNoInline = true }; + variantTable.Comments.PrecedingComment = $"Active when context is: {variantName}"; + + foreach (var setting in cat.Settings.Values) + { + var val = setting.GetVariantToml(variantName); + if (val != null) + variantTable.PutValue(setting.Name, val); + } + + if (variantTable.Entries.Count > 0) + table.PutValue(variantName, variantTable); + } + + doc.PutValue(cat.Name, table); + } + + File.WriteAllText(_path, doc.SerializedValue); + _cached = null; + } + + public void SaveImmediate() => Save(); + + public void ResetAll() + { + foreach (var cat in Categories.Values) + cat.ResetAll(); + } + + internal void GetActiveVariants(List results) + { + results.Clear(); + foreach (var ctx in Contexts) + if (ctx.Active != null) + results.Add(ctx.Active); + } + + internal TomlValue GetCachedValue(string category, string key) + { + if (_cached == null) return null; + if (!_cached.ContainsKey(category)) return null; + var table = _cached.GetSubTable(category); + return table.ContainsKey(key) ? table.GetValue(key) : null; + } + + internal TomlTable GetCachedCategoryTable(string category) + { + if (_cached == null) return null; + return _cached.ContainsKey(category) ? _cached.GetSubTable(category) : null; + } + + internal void MarkDirty() + { + if (_path == null || _savePending || _failed) return; + _savePending = true; + BetterScheduleSystem.AddJob(() => { _savePending = false; Save(); }, 5f, 0f, 0); + } + + internal void ThrowIfFailed() + { + if (!_failed || _threwOnce) return; + _threwOnce = true; + throw new InvalidOperationException( + $"[CVRSettings] File '{Name}' failed to load. " + + "Subsequent access returns defaults."); + } + } + + /// + /// A [section] within a .toml file. + /// + public sealed class CVRSettingsCategory + { + public readonly string Name; + public readonly string Comment; + public readonly string Page; + + internal readonly CVRSettingsFile File; + internal readonly Dictionary Settings = new(); + + public CVRCategoryUI UI; + + internal CVRSettingsCategory(string name, string comment, string page, CVRSettingsFile file) + { + Name = name; + Comment = comment; + Page = page ?? file.Name; + File = file; + CVRSettingsRegistry.Register(this); + } + + public CVRSetting Create(string key, T defaultValue, string comment = null, bool writeDefault = true) + { + var s = new CVRSetting(key, defaultValue, comment, writeDefault, this); + + var cached = File.GetCachedValue(Name, key); + if (cached != null) + s.LoadFromToml(cached); + + s.LoadVariantsFromCache(); + + Settings[key] = s; + return s; + } + + public CVRSettingsCategory WithUI(int sortOrder = 0, UIFilters filters = null) + { + UI = new CVRCategoryUI { SortOrder = sortOrder, Filters = filters }; + return this; + } + + public void ResetAll() + { + foreach (var s in Settings.Values) + s.ResetToDefault(); + } + + internal void PopulateFromDocument(TomlDocument doc) + { + if (!doc.ContainsKey(Name)) return; + var table = doc.GetSubTable(Name); + + foreach (var setting in Settings.Values) + { + if (table.ContainsKey(setting.Name)) + setting.LoadFromToml(table.GetValue(setting.Name)); + setting.LoadVariantsFromCache(); + } + } + } + + /// + /// Base class for settings. + /// + public abstract class CVRSettingBase + { + public readonly string Name; + public readonly string Comment; + public readonly bool WriteDefault; + + internal readonly CVRSettingsCategory Category; + + public CVRSettingUI UI; + + protected CVRSettingBase(string name, string comment, bool writeDefault, CVRSettingsCategory category) + { + Name = name; + Comment = comment; + WriteDefault = writeDefault; + Category = category; + } + + internal abstract bool SkipWrite { get; } + internal abstract TomlValue ToTomlValue(); + internal abstract void LoadFromToml(TomlValue value); + internal abstract void LoadVariantsFromCache(); + internal abstract void ResetToDefault(); + internal abstract void OnContextChanged(); + internal abstract void CollectVariantNames(HashSet names); + internal abstract TomlValue GetVariantToml(string variantName); + } + + /// + /// Typed setting. Supports any type Tomlet can serialize. + /// Optionally has named variants that activate based on context state. + /// + public sealed class CVRSetting : CVRSettingBase + { + public readonly T Default; + + private T _value; + private T _lastEffective; + private Dictionary _variants; + + // ReSharper disable once StaticMemberInGenericType + private static readonly List ActiveBuffer = new(); + + public event Action OnChanged; + + internal CVRSetting(string name, T defaultValue, string comment, bool writeDefault, + CVRSettingsCategory category) : base(name, comment, writeDefault, category) + { + Default = defaultValue; + _value = defaultValue; + _lastEffective = defaultValue; + } + + public T Value + { + get + { + Category.File.ThrowIfFailed(); + return Resolve(); + } + set + { + Category.File.ThrowIfFailed(); + var activeVariant = FindActiveVariant(); + if (activeVariant != null) + { + SetVariant(activeVariant, value); + return; + } + SetBase(value); + } + } + + public T BaseValue + { + get => _value; + set => SetBase(value); + } + + public void SetSilent(T value) => _value = value; + + public static implicit operator T(CVRSetting s) => s.Value; + + public override string ToString() => Resolve()?.ToString() ?? ""; + + // UI + + public CVRSetting WithUI(int sortOrder = 0, string tooltip = null, UIFilters filters = null) + { + UI = new CVRSettingUI { SortOrder = sortOrder, Tooltip = tooltip, Filters = filters }; + return this; + } + + // Variants + + /// + /// Provide a code-default variant value. TOML values take precedence. + /// Returns self for chaining. + /// + public CVRSetting WithVariant(string variantName, T value) + { + _variants ??= new Dictionary(); + _variants.TryAdd(variantName, value); + Category.File.VariantSettings.Add(this); + return this; + } + + public void SetVariant(string variantName, T value) + { + _variants ??= new Dictionary(); + if (_variants.TryGetValue(variantName, out var existing) + && EqualityComparer.Default.Equals(existing, value)) + return; + + var oldEffective = Resolve(); + _variants[variantName] = value; + Category.File.VariantSettings.Add(this); + var newEffective = Resolve(); + FireIfChanged(oldEffective, newEffective); + Category.File.MarkDirty(); + } + + public T GetVariant(string variantName) + { + if (_variants != null && _variants.TryGetValue(variantName, out var val)) + return val; + return _value; + } + + public bool HasVariant(string variantName) + => _variants != null && _variants.ContainsKey(variantName); + + // Resolution + + private T Resolve() + { + if (_variants != null) + { + Category.File.GetActiveVariants(ActiveBuffer); + foreach (var name in ActiveBuffer) + if (_variants.TryGetValue(name, out var val)) + return val; + } + return _value; + } + + private string FindActiveVariant() + { + if (_variants == null) return null; + Category.File.GetActiveVariants(ActiveBuffer); + foreach (var name in ActiveBuffer) + if (_variants.ContainsKey(name)) + return name; + return null; + } + + private void SetBase(T value) + { + if (EqualityComparer.Default.Equals(_value, value)) return; + var oldEffective = Resolve(); + _value = value; + var newEffective = Resolve(); + FireIfChanged(oldEffective, newEffective); + Category.File.MarkDirty(); + } + + private void FireIfChanged(T oldEffective, T newEffective) + { + if (EqualityComparer.Default.Equals(oldEffective, newEffective)) return; + _lastEffective = newEffective; + OnChanged?.Invoke(oldEffective, newEffective); + } + + internal override void OnContextChanged() + { + var newEffective = Resolve(); + if (EqualityComparer.Default.Equals(_lastEffective, newEffective)) return; + var old = _lastEffective; + _lastEffective = newEffective; + OnChanged?.Invoke(old, newEffective); + } + + // Serialization + + internal override bool SkipWrite + => !WriteDefault && EqualityComparer.Default.Equals(_value, Default); + + internal override void ResetToDefault() + { + var oldEffective = Resolve(); + _value = Default; + _variants?.Clear(); + var newEffective = Resolve(); + FireIfChanged(oldEffective, newEffective); + Category.File.MarkDirty(); + } + + internal override TomlValue ToTomlValue() => TomletMain.ValueFrom(_value); + + internal override void LoadFromToml(TomlValue val) + { + try { _value = TomletMain.To(val); _lastEffective = _value; } + catch { /* keep default */ } + } + + internal override void LoadVariantsFromCache() + { + var categoryTable = Category.File.GetCachedCategoryTable(Category.Name); + if (categoryTable == null) return; + + foreach (var key in categoryTable.Keys) + { + TomlValue entry; + try { entry = categoryTable.GetValue(key); } + catch { continue; } + + if (entry is not TomlTable variantTable) continue; + if (!variantTable.ContainsKey(Name)) continue; + + try + { + _variants ??= new Dictionary(); + _variants[key] = TomletMain.To(variantTable.GetValue(Name)); + Category.File.VariantSettings.Add(this); + } + catch { /* skip bad values */ } + } + } + + internal override void CollectVariantNames(HashSet names) + { + if (_variants == null) return; + foreach (var name in _variants.Keys) + names.Add(name); + } + + internal override TomlValue GetVariantToml(string variantName) + { + if (_variants == null || !_variants.TryGetValue(variantName, out var val)) + return null; + return TomletMain.ValueFrom(val); + } + } + + // UI metadata shit for ui lib + + public sealed class CVRCategoryUI + { + public int SortOrder; + public UIFilters Filters; + } + + public sealed class CVRSettingUI + { + public int SortOrder; + public string Tooltip; + public UIFilters Filters; + } + + public sealed class UIFilters + { + [Flags] public enum SettingsLevel { None = 0, Basic = 1, Advanced = 2, Niche = 4 } + [Flags] public enum PlatformType { None = 0, PCVR = 1, PCDesktop = 2, AndroidVR = 4 } + [Flags] public enum ContextType { None = 0, Player = 1, Editor = 2 } + [Flags] public enum LoaderType { None = 0, OpenVR = 1, OpenXR = 2, MetaSDK = 4, PicoSDK = 8 } + [Flags] public enum ControllerType { None = 0, Others = 1, Index = 2, ViveWands = 4 } + [Flags] public enum ContentType { None = 0, Default = 1, Mature = 2 } + [Flags] public enum AccountRank { None = 0, User = 1, Moderator = 2, Developer = 4 } + + // None means no filter applied, ignore + public SettingsLevel Level = SettingsLevel.None; + public PlatformType Platform = PlatformType.None; + public ContextType Context = ContextType.None; + public LoaderType Loader = LoaderType.None; + public ControllerType Controller = ControllerType.None; + public ContentType Content = ContentType.None; + public AccountRank Rank = AccountRank.None; + } + + public static class CVRSettingsRegistry + { + public static readonly Dictionary Files = new(); + public static readonly Dictionary> Pages = new(); + + internal static void Register(CVRSettingsFile file) => Files[file.Name] = file; + + internal static void Register(CVRSettingsCategory category) + { + if (!Pages.TryGetValue(category.Page, out var list)) + { + list = new List(); + Pages[category.Page] = list; + } + list.Add(category); + } + } +} \ No newline at end of file diff --git a/.Deprecated/DefaultDynamicBoneWind/format.json b/.Deprecated/DefaultDynamicBoneWind/format.json new file mode 100644 index 0000000..2a249d3 --- /dev/null +++ b/.Deprecated/DefaultDynamicBoneWind/format.json @@ -0,0 +1,23 @@ +{ + "_id": -1, + "name": "DefaultDynamicBoneWind", + "modversion": "1.0.0", + "gameversion": "2025r181-hf2", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Enables Wind Zone influence on Dynamic Bones by default.", + "searchtags": [ + "dynamic", + "bone", + "wind", + "zone" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/DefaultDynamicBoneWind.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/DefaultDynamicBoneWind/", + "changelog": "- Initial release", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Deprecated/FastStartup/FastStartup.csproj b/.Deprecated/FastStartup/FastStartup.csproj new file mode 100644 index 0000000..78195e6 --- /dev/null +++ b/.Deprecated/FastStartup/FastStartup.csproj @@ -0,0 +1,6 @@ + + + + ASTExtension + + diff --git a/.Deprecated/FastStartup/Main.cs b/.Deprecated/FastStartup/Main.cs new file mode 100644 index 0000000..8c4d4d7 --- /dev/null +++ b/.Deprecated/FastStartup/Main.cs @@ -0,0 +1,237 @@ +using System.Collections; +using System.Reflection; +using System.Text; +using System.Xml.Serialization; +using ABI_RC.Core.Base; +using ABI_RC.Core.EventSystem; +using ABI_RC.Core.Networking; +using ABI_RC.Core.Networking.API; +using ABI_RC.Core.Networking.API.Responses; +using ABI_RC.Core.Player; +using ABI_RC.Core.Savior; +using ABI_RC.Core.Savior.SceneManagers; +using ABI_RC.Systems.InputManagement; +using ABI_RC.Systems.UI; +using HarmonyLib; +using MelonLoader; +using Newtonsoft.Json; +using UnityEngine; +using UnityEngine.SceneManagement; + +namespace NAK.FastStartup; + +public class FastStartupMod : MelonMod +{ + private const string APIAddress = "https://api.chilloutvr.net"; + private const string APIVersion = "1"; + + private static MelonLogger.Instance Logger; + private static LoginProfile _profile; + private static Task> _pendingAuth; + + public override void OnInitializeMelon() + { + Logger = LoggerInstance; + + LoginRoom.IsPlayerIn = true; + + // Load profile and fire auth request as early as possible + _profile = LoadFirstProfile(); + if (_profile != null) + { + Logger.Msg($"Firing early auth for {_profile.Username}..."); + _pendingAuth = AuthenticateAsync(_profile.Username, _profile.AccessKey); + } + else + { + Logger.Error("No valid profile found."); + } + + HarmonyInstance.Patch( + typeof(Preparation).GetMethod(nameof(Preparation.Start), + BindingFlags.NonPublic | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(FastStartupMod).GetMethod(nameof(OnPrePreparationStart), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + + HarmonyInstance.Patch( + typeof(Init).GetMethod(nameof(Init.Start), + BindingFlags.NonPublic | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(FastStartupMod).GetMethod(nameof(OnMethodWeDontCareAboutAndWantToFuckOff), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( + typeof(IntroManager).GetMethod(nameof(IntroManager.Start), + BindingFlags.NonPublic | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(FastStartupMod).GetMethod(nameof(OnMethodWeDontCareAboutAndWantToFuckOff), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( + typeof(IntroManager).GetMethod(nameof(IntroManager.OnDestroy), + BindingFlags.NonPublic | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(FastStartupMod).GetMethod(nameof(OnMethodWeDontCareAboutAndWantToFuckOff), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + + HarmonyInstance.Patch( + typeof(LoginRoom).GetMethod(nameof(LoginRoom.Start), + BindingFlags.NonPublic | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(FastStartupMod).GetMethod(nameof(OnLoginRoomStart), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + + Logger.Msg("FastStartup initialized"); + } + + private static bool OnPrePreparationStart() + { + MelonCoroutines.Start(WaitForAuthAndContinue()); + return false; + } + + private static bool OnMethodWeDontCareAboutAndWantToFuckOff() => false; + + private static void OnLoginRoomStart() => WorldTransitionSystem.Instance.ContinueTransition(); + + private static IEnumerator WaitForAuthAndContinue() + { + Logger.Msg("Waiting for early auth to complete..."); + + // Load init scene + SceneManager.LoadScene("Init"); + yield return null; + + PlayerSetup.Instance.ToggleCameras(true, true); + WorldTransitionSystem.Instance.StartTransition(true); + CursorLockManager.Instance.UpdateCursorState(); + + if (_pendingAuth == null) + { + MelonCoroutines.Start(LoginRoom.LoadScene()); + yield break; + } + + while (!_pendingAuth.IsCompleted) + yield return null; + + if (_pendingAuth.IsFaulted || _pendingAuth.Result?.Data == null) + { + Logger.Error($"Early auth failed: {_pendingAuth.Exception?.Message ?? "null response"}"); + MelonCoroutines.Start(LoginRoom.LoadScene()); + yield break; + } + + var authData = _pendingAuth.Result.Data; + Logger.Msg($"Early auth succeeded: {authData.Username} ({authData.UserId})"); + + MelonCoroutines.Start(AuthManager.AuthenticationSucceeded(_pendingAuth.Result, AuthManager.AuthEntity.ABIProfile)); + MelonCoroutines.Start(LoadOurContent()); + } + + private static IEnumerator LoadOurContent() + { + yield return null; + Content.LoadIntoWorld(MetaPort.Instance.homeWorldGuid, true); + AssetManagement.Instance.LoadLocalAvatar(MetaPort.Instance.currentAvatarGuid); + } + + #region Profile Loading + + private static LoginProfile LoadFirstProfile() + { + try + { + /*var profileFiles = Directory.GetFiles(Application.dataPath, "*.profile"); + if (profileFiles.Length == 0) + { + Logger.Warning("No .profile files found"); + return null; + } + + // Load first valid profile found + foreach (var file in profileFiles) + {*/ + string file = Path.Combine(Application.dataPath, "autologin.profile"); + if (File.Exists(file)) + { + try + { + using var reader = new StreamReader(file); + var serializer = new XmlSerializer(typeof(LoginProfile)); + var profile = (LoginProfile)serializer.Deserialize(reader); + + if (!string.IsNullOrEmpty(profile?.Username) && !string.IsNullOrEmpty(profile?.AccessKey)) + { + Logger.Msg($"Loaded profile: {profile.Username}"); + return profile; + } + } + catch (Exception ex) + { + Logger.Warning($"Failed to load {Path.GetFileName(file)}: {ex.Message}"); + } + } + // } + } + catch (Exception ex) + { + Logger.Error($"Profile loading failed: {ex.Message}"); + } + + return null; + } + + #endregion Profile Loading + + #region Auth Request + + private static async Task> AuthenticateAsync(string username, string accessKey) + { + using var client = new HttpClient(); + client.Timeout = TimeSpan.FromSeconds(30); + + client.DefaultRequestHeaders.Add(ApiConnection.HeaderUsername, username); + client.DefaultRequestHeaders.Add(ApiConnection.HeaderAccessKey, accessKey); + client.DefaultRequestHeaders.Add(ApiConnection.HeaderUserAgent, $"ChilloutVR/{Application.version} (fuck you)"); + client.DefaultRequestHeaders.Add(ApiConnection.HeaderPlatform, MetaPort.Platform); + client.DefaultRequestHeaders.Add(ApiConnection.HeaderCompatibleVersions, MetaPort.CompatibleVersions); + + var payload = JsonConvert.SerializeObject(new + { + Username = username, + Password = accessKey, + AuthType = 1, + get = "?acceptTOS=true" + }); + + var url = $"{APIAddress}/{APIVersion}/users/auth?acceptTOS=true"; + + try + { + var response = await client.PostAsync(url, new StringContent(payload, Encoding.UTF8, "application/json")); + + if (!response.IsSuccessStatusCode) + { + Logger.Error($"Auth failed: {response.StatusCode}"); + return null; + } + + var body = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject>(body); + } + catch (Exception ex) + { + Logger.Error($"Auth request failed: {ex.Message}"); + return null; + } + } + + #endregion Auth Request +} + +[XmlRoot("LoginProfile")] +public class LoginProfile +{ + [XmlElement("Username")] public string Username { get; set; } + [XmlElement("AccessKey")] public string AccessKey { get; set; } +} \ No newline at end of file diff --git a/.Deprecated/FastStartup/Properties/AssemblyInfo.cs b/.Deprecated/FastStartup/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..56b7628 --- /dev/null +++ b/.Deprecated/FastStartup/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.FastStartup.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.FastStartup))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.FastStartup))] + +[assembly: MelonInfo( + typeof(NAK.FastStartup.FastStartupMod), + nameof(NAK.FastStartup), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/FastStartup" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.FastStartup.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.5"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/FastStartup/README.md b/.Deprecated/FastStartup/README.md new file mode 100644 index 0000000..399e70a --- /dev/null +++ b/.Deprecated/FastStartup/README.md @@ -0,0 +1,54 @@ +# ASTExtension + +Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool): +- VR Gesture to scale +- Persistent height +- Copy height from others + +Best used with Avatar Scale Tool, but will attempt to work with found scaling setups. +Requires already having Avatar Scaling on the avatar. This is **not** Universal Scaling. + +## Supported Setups + +ASTExtension will attempt to work with the following setups: + +**Parameter Names:** +- AvatarScale +- Scale +- Scaler +- Scale/Scale +- Height +- LoliModifier +- AvatarSize +- Size +- SizeScale +- Scaling + +These parameter names are not case sensitive and have been gathered from polling the community for common parameter names. + +Assuming the parameter is a float, ASTExtension will attempt to use it as the height parameter. Will automatically calibrate to the height range of the found parameter, assuming the scaling animation is in a blend tree / state using motion time & is linear. The scaling animation state **must be active** at time of avatar load. + +The max value ASTExtension will drive the parameter to is 100. As the mod is having to guess the max height, it may not be accurate if the max height is not capped at a multiple of 10. + +Examples: +- `AvatarScale` - 0 to 1 (slider) + - This is the default setup for Avatar Scale Tool and will work perfectly. +- `Scale` - 0 to 100 (input single) + - This will also work perfectly as the max height is a multiple of 10. +- `Height` - 0 to 2 (input single) + - This will not work properly. The max value to drive the parameter to is not a multiple of 10, and as such ASTExtension will believe the parameter range is 0 to 1. +- `BurntToast` - 0 to 10 (input single) + - This will not work properly. The parameter name is not recognized by ASTExtension. + +If your setup is theoretically supported but not working, it is likely the scaling animation is not linear or has loop enabled if using Motion Time, making the first and last frame identical height. In this case, you will need to fix your animation clip curves / blend tree to be linear &|| not loop, or use Avatar Scale Tool to generate a new scaling animation. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Deprecated/FastStartup/format.json b/.Deprecated/FastStartup/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/.Deprecated/FastStartup/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Deprecated/MirroredReflection/Main.cs b/.Deprecated/MirroredReflection/Main.cs new file mode 100644 index 0000000..29f05d3 --- /dev/null +++ b/.Deprecated/MirroredReflection/Main.cs @@ -0,0 +1,78 @@ +using System.Reflection; +using ABI_RC.Core; +using ABI_RC.Core.Player; +using ABI_RC.Systems.ContentClones; +using ABI_RC.Systems.GameEventSystem; +using ABI.CCK.Components; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace NAK.MirroredReflection; + +public class MirroredReflectionMod : MelonMod +{ + public override void OnInitializeMelon() + { + CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(OnLocalAvatarLoad); + CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(OnLocalAvatarClear); + CVRGameEventSystem.Avatar.OnLocalAvatarHeightScale.AddListener(OnLocalAvatarHeightScale); + HarmonyInstance.Patch( + typeof(CVRMirror).GetMethod(nameof(CVRMirror.Start), + BindingFlags.NonPublic | BindingFlags.Instance), + postfix: new HarmonyMethod(typeof(MirroredReflectionMod).GetMethod(nameof(OnPostCVRMirrorStart), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + } + + private static readonly ContentCloneManager.CloneOptions PlayerClone = new() + { + SyncTransforms = true, + SyncRootPosition = true, + SyncRootScale = false, + SyncMaterialSwaps = true, + SyncProbeAnchors = false, + OverrideLayers = true, + CloneLayer = CVRLayers.PlayerClone, + OnlyRenderIfOriginalNotInCamera = true, + ShowCameraTypes = CVRCameraTypeFlags.UserGeneratedContent | CVRCameraTypeFlags.PortableCamera | CVRCameraTypeFlags.MirrorCamera | CVRCameraTypeFlags.CaptureCamera + }; + + private static ContentCloneManager.CloneData _mirrorClone; + + private static void OnLocalAvatarLoad(CVRAvatar avatar) + { + if (!avatar) return; + _mirrorClone = ContentCloneManager.CreateClone(avatar.gameObject, PlayerClone); + if (_mirrorClone != null) + { + _mirrorClone.CloneRootTransform.localScale = new Vector3(-1f, 1f, 1f); + _mirrorClone.LastSourceRootScale = avatar.transform.localScale; + } + } + + private static void OnLocalAvatarClear(CVRAvatar avatar) + { + if (_mirrorClone is { IsDestroyed: false }) + { + UnityEngine.Object.Destroy(_mirrorClone.CloneRoot); + _mirrorClone = null; + } + } + + private static void OnLocalAvatarHeightScale(float height, float scale) + { + if (_mirrorClone is { IsDestroyed: false }) + { + Vector3 localScale = PlayerSetup.Instance.AvatarTransform.localScale; + localScale.x *= -1f; + _mirrorClone.CloneRootTransform.localScale = localScale; + } + } + + private static void OnPostCVRMirrorStart(CVRMirror __instance) + { + __instance.m_ReflectLayers &= ~(1 << CVRLayers.PlayerLocal); // remove PlayerLocal + __instance.m_ReflectLayers |= (1 << CVRLayers.PlayerClone); // add PlayerClone + } +} \ No newline at end of file diff --git a/.Deprecated/MirroredReflection/MirroredReflection.csproj b/.Deprecated/MirroredReflection/MirroredReflection.csproj new file mode 100644 index 0000000..78195e6 --- /dev/null +++ b/.Deprecated/MirroredReflection/MirroredReflection.csproj @@ -0,0 +1,6 @@ + + + + ASTExtension + + diff --git a/.Deprecated/MirroredReflection/Properties/AssemblyInfo.cs b/.Deprecated/MirroredReflection/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..c5be541 --- /dev/null +++ b/.Deprecated/MirroredReflection/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.MirroredReflection.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.MirroredReflection))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.MirroredReflection))] + +[assembly: MelonInfo( + typeof(NAK.MirroredReflection.MirroredReflectionMod), + nameof(NAK.MirroredReflection), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/MirroredReflection" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.MirroredReflection.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Deprecated/MirroredReflection/README.md b/.Deprecated/MirroredReflection/README.md new file mode 100644 index 0000000..5ed44c4 --- /dev/null +++ b/.Deprecated/MirroredReflection/README.md @@ -0,0 +1,54 @@ +# ASTExtension + +Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool): +- VR Gesture to scale +- Persistent height +- Copy height from others + +Best used with Avatar Scale Tool, but will attempt to work with found scaling setups. +Requires already having Avatar Scaling on the avatar. This is **not** Universal Scaling. + +## Supported Setups + +ASTExtension will attempt to work with the following setups: + +**Parameter Names:** +- AvatarScale +- Scale +- Scaler +- Scale/Scale +- Height +- LoliModifier +- AvatarSize +- Size +- SizeScale +- Scaling + +These parameter names are not case sensitive and have been gathered from polling the community for common parameter names. + +Assuming the parameter is a float, ASTExtension will attempt to use it as the height parameter. Will automatically calibrate to the height range of the found parameter, assuming the scaling animation is in a blend tree / state using motion time & is linear. The scaling animation state **must be active** at time of avatar load. + +The max value ASTExtension will drive the parameter to is 100. As the mod is having to guess the max height, it may not be accurate if the max height is not capped at a multiple of 10. + +Examples: +- `AvatarScale` - 0 to 1 (slider) + - This is the default setup for Avatar Scale Tool and will work perfectly. +- `Scale` - 0 to 100 (input single) + - This will also work perfectly as the max height is a multiple of 10. +- `Height` - 0 to 2 (input single) + - This will not work properly. The max value to drive the parameter to is not a multiple of 10, and as such ASTExtension will believe the parameter range is 0 to 1. +- `BurntToast` - 0 to 10 (input single) + - This will not work properly. The parameter name is not recognized by ASTExtension. + +If your setup is theoretically supported but not working, it is likely the scaling animation is not linear or has loop enabled if using Motion Time, making the first and last frame identical height. In this case, you will need to fix your animation clip curves / blend tree to be linear &|| not loop, or use Avatar Scale Tool to generate a new scaling animation. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game + +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/.Deprecated/MirroredReflection/format.json b/.Deprecated/MirroredReflection/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/.Deprecated/MirroredReflection/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/PropLoadingHexagon/Components/LoadingHexagonController.cs b/.Deprecated/PropLoadingHexagon/Components/LoadingHexagonController.cs similarity index 100% rename from PropLoadingHexagon/Components/LoadingHexagonController.cs rename to .Deprecated/PropLoadingHexagon/Components/LoadingHexagonController.cs diff --git a/PropLoadingHexagon/Integrations/ClappableLoadingHex.cs b/.Deprecated/PropLoadingHexagon/Integrations/ClappableLoadingHex.cs similarity index 100% rename from PropLoadingHexagon/Integrations/ClappableLoadingHex.cs rename to .Deprecated/PropLoadingHexagon/Integrations/ClappableLoadingHex.cs diff --git a/PropLoadingHexagon/Main.cs b/.Deprecated/PropLoadingHexagon/Main.cs similarity index 100% rename from PropLoadingHexagon/Main.cs rename to .Deprecated/PropLoadingHexagon/Main.cs diff --git a/PropLoadingHexagon/PropLoadingHexagon.csproj b/.Deprecated/PropLoadingHexagon/PropLoadingHexagon.csproj similarity index 100% rename from PropLoadingHexagon/PropLoadingHexagon.csproj rename to .Deprecated/PropLoadingHexagon/PropLoadingHexagon.csproj diff --git a/PropLoadingHexagon/Properties/AssemblyInfo.cs b/.Deprecated/PropLoadingHexagon/Properties/AssemblyInfo.cs similarity index 100% rename from PropLoadingHexagon/Properties/AssemblyInfo.cs rename to .Deprecated/PropLoadingHexagon/Properties/AssemblyInfo.cs diff --git a/PropLoadingHexagon/README.md b/.Deprecated/PropLoadingHexagon/README.md similarity index 76% rename from PropLoadingHexagon/README.md rename to .Deprecated/PropLoadingHexagon/README.md index c07c464..9f3b652 100644 --- a/PropLoadingHexagon/README.md +++ b/.Deprecated/PropLoadingHexagon/README.md @@ -8,11 +8,11 @@ Can use Delete Mode ~~& The Clapper~~ on loading hexagons to cancel stuck downlo --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/PropLoadingHexagon/Resources/loading_hexagon.assets b/.Deprecated/PropLoadingHexagon/Resources/loading_hexagon.assets similarity index 100% rename from PropLoadingHexagon/Resources/loading_hexagon.assets rename to .Deprecated/PropLoadingHexagon/Resources/loading_hexagon.assets diff --git a/PropLoadingHexagon/format.json b/.Deprecated/PropLoadingHexagon/format.json similarity index 100% rename from PropLoadingHexagon/format.json rename to .Deprecated/PropLoadingHexagon/format.json diff --git a/PropsButBetter/Main.cs b/.Deprecated/PropsButBetter/Main.cs similarity index 100% rename from PropsButBetter/Main.cs rename to .Deprecated/PropsButBetter/Main.cs diff --git a/PropsButBetter/ModSettings.cs b/.Deprecated/PropsButBetter/ModSettings.cs similarity index 100% rename from PropsButBetter/ModSettings.cs rename to .Deprecated/PropsButBetter/ModSettings.cs diff --git a/PropsButBetter/Properties/AssemblyInfo.cs b/.Deprecated/PropsButBetter/Properties/AssemblyInfo.cs similarity index 100% rename from PropsButBetter/Properties/AssemblyInfo.cs rename to .Deprecated/PropsButBetter/Properties/AssemblyInfo.cs diff --git a/PropsButBetter/PropsButBetter.csproj b/.Deprecated/PropsButBetter/PropsButBetter.csproj similarity index 100% rename from PropsButBetter/PropsButBetter.csproj rename to .Deprecated/PropsButBetter/PropsButBetter.csproj diff --git a/PropsButBetter/PropsButBetter/API/PedestalInfoBatchProcessor.cs b/.Deprecated/PropsButBetter/PropsButBetter/API/PedestalInfoBatchProcessor.cs similarity index 100% rename from PropsButBetter/PropsButBetter/API/PedestalInfoBatchProcessor.cs rename to .Deprecated/PropsButBetter/PropsButBetter/API/PedestalInfoBatchProcessor.cs diff --git a/PropsButBetter/PropsButBetter/API/SpawnablesMeta.cs b/.Deprecated/PropsButBetter/PropsButBetter/API/SpawnablesMeta.cs similarity index 100% rename from PropsButBetter/PropsButBetter/API/SpawnablesMeta.cs rename to .Deprecated/PropsButBetter/PropsButBetter/API/SpawnablesMeta.cs diff --git a/PropsButBetter/PropsButBetter/Extensions/CVRSpawnableExtensions.cs b/.Deprecated/PropsButBetter/PropsButBetter/Extensions/CVRSpawnableExtensions.cs similarity index 100% rename from PropsButBetter/PropsButBetter/Extensions/CVRSpawnableExtensions.cs rename to .Deprecated/PropsButBetter/PropsButBetter/Extensions/CVRSpawnableExtensions.cs diff --git a/PropsButBetter/PropsButBetter/Extensions/PlayerSetupExtensions.cs b/.Deprecated/PropsButBetter/PropsButBetter/Extensions/PlayerSetupExtensions.cs similarity index 100% rename from PropsButBetter/PropsButBetter/Extensions/PlayerSetupExtensions.cs rename to .Deprecated/PropsButBetter/PropsButBetter/Extensions/PlayerSetupExtensions.cs diff --git a/.Deprecated/PropsButBetter/PropsButBetter/Extensions/PropDataExtensions.cs b/.Deprecated/PropsButBetter/PropsButBetter/Extensions/PropDataExtensions.cs new file mode 100644 index 0000000..82d7044 --- /dev/null +++ b/.Deprecated/PropsButBetter/PropsButBetter/Extensions/PropDataExtensions.cs @@ -0,0 +1,43 @@ +using ABI_RC.Core.Networking; +using ABI_RC.Core.Util; +using ABI.CCK.Components; + +namespace NAK.PropsButBetter; + +public static class PropDataExtensions +{ + public static bool IsSpawnedByMe(this CVRSyncHelper.PropData prop) + => prop.SpawnedBy == AuthManager.UserId; + + public static bool IsSpawnedByAdmin(this CVRSyncHelper.PropData prop) + => prop.SpawnedBy is CVRSyncHelper.OWNERID_LOCALSERVER or CVRSyncHelper.OWNERID_SYSTEM; + + public static void CopyFrom(this CVRSyncHelper.PropData prop, CVRSyncHelper.PropData sourceData) + { + prop.ObjectId = sourceData.ObjectId; + prop.InstanceId = sourceData.InstanceId; + prop.PositionX = sourceData.PositionX; + prop.PositionY = sourceData.PositionY; + prop.PositionZ = sourceData.PositionZ; + prop.RotationX = sourceData.RotationX; + prop.RotationY = sourceData.RotationY; + prop.RotationZ = sourceData.RotationZ; + prop.ScaleX = sourceData.ScaleX; + prop.ScaleY = sourceData.ScaleY; + prop.ScaleZ = sourceData.ScaleZ; + prop.CustomFloatsAmount = sourceData.CustomFloatsAmount; + prop.CustomFloats = sourceData.CustomFloats; + prop.SpawnedBy = sourceData.SpawnedBy; + prop.syncedBy = sourceData.syncedBy; + prop.syncType = sourceData.syncType; + prop.ContentMetadata = sourceData.ContentMetadata; + prop.CanFireDecommissionEvents = sourceData.CanFireDecommissionEvents; + } + + public static void RecycleSafe(this CVRSyncHelper.PropData prop) + { + if (prop.IsSpawnedByMe()) + CVRSyncHelper.DeleteMyPropByInstanceIdOverNetwork(prop.InstanceId); + prop.Recycle(); + } +} \ No newline at end of file diff --git a/PropsButBetter/PropsButBetter/Extensions/TextBlockExtensions.cs b/.Deprecated/PropsButBetter/PropsButBetter/Extensions/TextBlockExtensions.cs similarity index 100% rename from PropsButBetter/PropsButBetter/Extensions/TextBlockExtensions.cs rename to .Deprecated/PropsButBetter/PropsButBetter/Extensions/TextBlockExtensions.cs diff --git a/PropsButBetter/PropsButBetter/Helpers/BoundsUtility.cs b/.Deprecated/PropsButBetter/PropsButBetter/Helpers/BoundsUtility.cs similarity index 100% rename from PropsButBetter/PropsButBetter/Helpers/BoundsUtility.cs rename to .Deprecated/PropsButBetter/PropsButBetter/Helpers/BoundsUtility.cs diff --git a/PropsButBetter/PropsButBetter/Helpers/PropHelper.cs b/.Deprecated/PropsButBetter/PropsButBetter/Helpers/PropHelper.cs similarity index 99% rename from PropsButBetter/PropsButBetter/Helpers/PropHelper.cs rename to .Deprecated/PropsButBetter/PropsButBetter/Helpers/PropHelper.cs index 1905506..c91d83f 100644 --- a/PropsButBetter/PropsButBetter/Helpers/PropHelper.cs +++ b/.Deprecated/PropsButBetter/PropsButBetter/Helpers/PropHelper.cs @@ -151,6 +151,7 @@ public static class PropHelper for (int i = propsCount - 1; i >= 0; i--) { CVRSyncHelper.PropData prop = CVRSyncHelper.Props[i]; + if (prop.IsSpawnedByAdmin()) continue; if (!prop.IsSpawnedByMe()) prop.RecycleSafe(); } @@ -169,6 +170,7 @@ public static class PropHelper for (int i = propsCount - 1; i >= 0; i--) { CVRSyncHelper.PropData prop = CVRSyncHelper.Props[i]; + if (prop.IsSpawnedByAdmin()) continue; prop.RecycleSafe(); } diff --git a/PropsButBetter/PropsButBetter/Helpers/RendererHelper.cs b/.Deprecated/PropsButBetter/PropsButBetter/Helpers/RendererHelper.cs similarity index 100% rename from PropsButBetter/PropsButBetter/Helpers/RendererHelper.cs rename to .Deprecated/PropsButBetter/PropsButBetter/Helpers/RendererHelper.cs diff --git a/PropsButBetter/PropsButBetter/Helpers/UILibHelper.cs b/.Deprecated/PropsButBetter/PropsButBetter/Helpers/UILibHelper.cs similarity index 100% rename from PropsButBetter/PropsButBetter/Helpers/UILibHelper.cs rename to .Deprecated/PropsButBetter/PropsButBetter/Helpers/UILibHelper.cs diff --git a/PropsButBetter/PropsButBetter/PropDistanceHider.cs b/.Deprecated/PropsButBetter/PropsButBetter/PropDistanceHider.cs similarity index 100% rename from PropsButBetter/PropsButBetter/PropDistanceHider.cs rename to .Deprecated/PropsButBetter/PropsButBetter/PropDistanceHider.cs diff --git a/PropsButBetter/PropsButBetter/QuickMenuPropList.cs b/.Deprecated/PropsButBetter/PropsButBetter/QuickMenuPropList.cs similarity index 100% rename from PropsButBetter/PropsButBetter/QuickMenuPropList.cs rename to .Deprecated/PropsButBetter/PropsButBetter/QuickMenuPropList.cs diff --git a/PropsButBetter/PropsButBetter/QuickMenuPropSelect.cs b/.Deprecated/PropsButBetter/PropsButBetter/QuickMenuPropSelect.cs similarity index 100% rename from PropsButBetter/PropsButBetter/QuickMenuPropSelect.cs rename to .Deprecated/PropsButBetter/PropsButBetter/QuickMenuPropSelect.cs diff --git a/PropsButBetter/PropsButBetter/UIElements/ContentDisplay.cs b/.Deprecated/PropsButBetter/PropsButBetter/UIElements/ContentDisplay.cs similarity index 100% rename from PropsButBetter/PropsButBetter/UIElements/ContentDisplay.cs rename to .Deprecated/PropsButBetter/PropsButBetter/UIElements/ContentDisplay.cs diff --git a/PropsButBetter/PropsButBetter/UIElements/GlobalButton.cs b/.Deprecated/PropsButBetter/PropsButBetter/UIElements/GlobalButton.cs similarity index 100% rename from PropsButBetter/PropsButBetter/UIElements/GlobalButton.cs rename to .Deprecated/PropsButBetter/PropsButBetter/UIElements/GlobalButton.cs diff --git a/PropsButBetter/PropsButBetter/UIElements/PropListEntry.cs b/.Deprecated/PropsButBetter/PropsButBetter/UIElements/PropListEntry.cs similarity index 100% rename from PropsButBetter/PropsButBetter/UIElements/PropListEntry.cs rename to .Deprecated/PropsButBetter/PropsButBetter/UIElements/PropListEntry.cs diff --git a/PropsButBetter/PropsButBetter/UIElements/UndoRedoButtons.cs b/.Deprecated/PropsButBetter/PropsButBetter/UIElements/UndoRedoButtons.cs similarity index 100% rename from PropsButBetter/PropsButBetter/UIElements/UndoRedoButtons.cs rename to .Deprecated/PropsButBetter/PropsButBetter/UIElements/UndoRedoButtons.cs diff --git a/PropsButBetter/README.md b/.Deprecated/PropsButBetter/README.md similarity index 100% rename from PropsButBetter/README.md rename to .Deprecated/PropsButBetter/README.md diff --git a/PropUndoButton/SFX/sfx_deny.wav b/.Deprecated/PropsButBetter/Resources/SFX/sfx_deny.wav similarity index 100% rename from PropUndoButton/SFX/sfx_deny.wav rename to .Deprecated/PropsButBetter/Resources/SFX/sfx_deny.wav diff --git a/PropUndoButton/SFX/sfx_redo.wav b/.Deprecated/PropsButBetter/Resources/SFX/sfx_redo.wav similarity index 100% rename from PropUndoButton/SFX/sfx_redo.wav rename to .Deprecated/PropsButBetter/Resources/SFX/sfx_redo.wav diff --git a/PropUndoButton/SFX/sfx_spawn.wav b/.Deprecated/PropsButBetter/Resources/SFX/sfx_spawn.wav similarity index 100% rename from PropUndoButton/SFX/sfx_spawn.wav rename to .Deprecated/PropsButBetter/Resources/SFX/sfx_spawn.wav diff --git a/PropUndoButton/SFX/sfx_undo.wav b/.Deprecated/PropsButBetter/Resources/SFX/sfx_undo.wav similarity index 100% rename from PropUndoButton/SFX/sfx_undo.wav rename to .Deprecated/PropsButBetter/Resources/SFX/sfx_undo.wav diff --git a/PropUndoButton/SFX/sfx_warn.wav b/.Deprecated/PropsButBetter/Resources/SFX/sfx_warn.wav similarity index 100% rename from PropUndoButton/SFX/sfx_warn.wav rename to .Deprecated/PropsButBetter/Resources/SFX/sfx_warn.wav diff --git a/PropsButBetter/Resources/placeholder.png b/.Deprecated/PropsButBetter/Resources/placeholder.png similarity index 100% rename from PropsButBetter/Resources/placeholder.png rename to .Deprecated/PropsButBetter/Resources/placeholder.png diff --git a/PropsButBetter/Resources/redo.png b/.Deprecated/PropsButBetter/Resources/redo.png similarity index 100% rename from PropsButBetter/Resources/redo.png rename to .Deprecated/PropsButBetter/Resources/redo.png diff --git a/PropsButBetter/Resources/reload.png b/.Deprecated/PropsButBetter/Resources/reload.png similarity index 100% rename from PropsButBetter/Resources/reload.png rename to .Deprecated/PropsButBetter/Resources/reload.png diff --git a/PropsButBetter/Resources/remove.png b/.Deprecated/PropsButBetter/Resources/remove.png similarity index 100% rename from PropsButBetter/Resources/remove.png rename to .Deprecated/PropsButBetter/Resources/remove.png diff --git a/PropsButBetter/Resources/rubiks-cube-calender.png b/.Deprecated/PropsButBetter/Resources/rubiks-cube-calender.png similarity index 100% rename from PropsButBetter/Resources/rubiks-cube-calender.png rename to .Deprecated/PropsButBetter/Resources/rubiks-cube-calender.png diff --git a/PropsButBetter/Resources/rubiks-cube-clock.png b/.Deprecated/PropsButBetter/Resources/rubiks-cube-clock.png similarity index 100% rename from PropsButBetter/Resources/rubiks-cube-clock.png rename to .Deprecated/PropsButBetter/Resources/rubiks-cube-clock.png diff --git a/PropsButBetter/Resources/rubiks-cube-eye.png b/.Deprecated/PropsButBetter/Resources/rubiks-cube-eye.png similarity index 100% rename from PropsButBetter/Resources/rubiks-cube-eye.png rename to .Deprecated/PropsButBetter/Resources/rubiks-cube-eye.png diff --git a/PropsButBetter/Resources/rubiks-cube-star.png b/.Deprecated/PropsButBetter/Resources/rubiks-cube-star.png similarity index 100% rename from PropsButBetter/Resources/rubiks-cube-star.png rename to .Deprecated/PropsButBetter/Resources/rubiks-cube-star.png diff --git a/PropsButBetter/Resources/rubiks-cube.png b/.Deprecated/PropsButBetter/Resources/rubiks-cube.png similarity index 100% rename from PropsButBetter/Resources/rubiks-cube.png rename to .Deprecated/PropsButBetter/Resources/rubiks-cube.png diff --git a/PropsButBetter/Resources/select.png b/.Deprecated/PropsButBetter/Resources/select.png similarity index 100% rename from PropsButBetter/Resources/select.png rename to .Deprecated/PropsButBetter/Resources/select.png diff --git a/PropsButBetter/Resources/undo.png b/.Deprecated/PropsButBetter/Resources/undo.png similarity index 100% rename from PropsButBetter/Resources/undo.png rename to .Deprecated/PropsButBetter/Resources/undo.png diff --git a/PropsButBetter/Resources/wand.png b/.Deprecated/PropsButBetter/Resources/wand.png similarity index 100% rename from PropsButBetter/Resources/wand.png rename to .Deprecated/PropsButBetter/Resources/wand.png diff --git a/PropsButBetter/format.json b/.Deprecated/PropsButBetter/format.json similarity index 100% rename from PropsButBetter/format.json rename to .Deprecated/PropsButBetter/format.json diff --git a/Stickers/Integrations/BTKUI/UIAddon.Category.MiscOptions.cs b/.Deprecated/Stickers/Integrations/BTKUI/UIAddon.Category.MiscOptions.cs similarity index 100% rename from Stickers/Integrations/BTKUI/UIAddon.Category.MiscOptions.cs rename to .Deprecated/Stickers/Integrations/BTKUI/UIAddon.Category.MiscOptions.cs diff --git a/Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs b/.Deprecated/Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs similarity index 100% rename from Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs rename to .Deprecated/Stickers/Integrations/BTKUI/UIAddon.Category.StickersMod.cs diff --git a/Stickers/Integrations/BTKUI/UIAddon.Main.cs b/.Deprecated/Stickers/Integrations/BTKUI/UIAddon.Main.cs similarity index 100% rename from Stickers/Integrations/BTKUI/UIAddon.Main.cs rename to .Deprecated/Stickers/Integrations/BTKUI/UIAddon.Main.cs diff --git a/Stickers/Integrations/BTKUI/UIAddon.Page.PlayerOptions.cs b/.Deprecated/Stickers/Integrations/BTKUI/UIAddon.Page.PlayerOptions.cs similarity index 100% rename from Stickers/Integrations/BTKUI/UIAddon.Page.PlayerOptions.cs rename to .Deprecated/Stickers/Integrations/BTKUI/UIAddon.Page.PlayerOptions.cs diff --git a/Stickers/Integrations/BTKUI/UIAddon.Page.StickerSelect.cs b/.Deprecated/Stickers/Integrations/BTKUI/UIAddon.Page.StickerSelect.cs similarity index 100% rename from Stickers/Integrations/BTKUI/UIAddon.Page.StickerSelect.cs rename to .Deprecated/Stickers/Integrations/BTKUI/UIAddon.Page.StickerSelect.cs diff --git a/Stickers/Main.cs b/.Deprecated/Stickers/Main.cs similarity index 100% rename from Stickers/Main.cs rename to .Deprecated/Stickers/Main.cs diff --git a/Stickers/ModSettings.cs b/.Deprecated/Stickers/ModSettings.cs similarity index 100% rename from Stickers/ModSettings.cs rename to .Deprecated/Stickers/ModSettings.cs diff --git a/Stickers/Patches.cs b/.Deprecated/Stickers/Patches.cs similarity index 100% rename from Stickers/Patches.cs rename to .Deprecated/Stickers/Patches.cs diff --git a/Stickers/Properties/AssemblyInfo.cs b/.Deprecated/Stickers/Properties/AssemblyInfo.cs similarity index 100% rename from Stickers/Properties/AssemblyInfo.cs rename to .Deprecated/Stickers/Properties/AssemblyInfo.cs diff --git a/Stickers/README.md b/.Deprecated/Stickers/README.md similarity index 93% rename from Stickers/README.md rename to .Deprecated/Stickers/README.md index ae0f4ae..8fb53b8 100644 --- a/Stickers/README.md +++ b/.Deprecated/Stickers/README.md @@ -39,11 +39,11 @@ If you are looking for a similar open-source asset to generate decals at runtime --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-alphabet.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-alphabet.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-alphabet.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-alphabet.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-eraser.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-eraser.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-eraser.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-eraser.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-folder.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-folder.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-folder.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-folder.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-headset.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-headset.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-headset.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-headset.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand-broken.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand-broken.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand-broken.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand-broken.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magic-wand.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magnifying-glass.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magnifying-glass.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-magnifying-glass.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-magnifying-glass.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-mouse.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-mouse.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-mouse.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-mouse.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle-disabled.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle-disabled.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle-disabled.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle-disabled.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-puzzle.png diff --git a/Stickers/Resources/Gohsantosadrive_Icons/Stickers-rubbish-bin.png b/.Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-rubbish-bin.png similarity index 100% rename from Stickers/Resources/Gohsantosadrive_Icons/Stickers-rubbish-bin.png rename to .Deprecated/Stickers/Resources/Gohsantosadrive_Icons/Stickers-rubbish-bin.png diff --git a/Stickers/Resources/decalery_shaders.assets b/.Deprecated/Stickers/Resources/decalery_shaders.assets similarity index 100% rename from Stickers/Resources/decalery_shaders.assets rename to .Deprecated/Stickers/Resources/decalery_shaders.assets diff --git a/Stickers/Stickers.csproj b/.Deprecated/Stickers/Stickers.csproj similarity index 100% rename from Stickers/Stickers.csproj rename to .Deprecated/Stickers/Stickers.csproj diff --git a/Stickers/Stickers/Enums/StickerKeyBinds.cs b/.Deprecated/Stickers/Stickers/Enums/StickerKeyBinds.cs similarity index 100% rename from Stickers/Stickers/Enums/StickerKeyBinds.cs rename to .Deprecated/Stickers/Stickers/Enums/StickerKeyBinds.cs diff --git a/Stickers/Stickers/Enums/StickerSFXType.cs b/.Deprecated/Stickers/Stickers/Enums/StickerSFXType.cs similarity index 100% rename from Stickers/Stickers/Enums/StickerSFXType.cs rename to .Deprecated/Stickers/Stickers/Enums/StickerSFXType.cs diff --git a/Stickers/Stickers/Enums/StickerSize.cs b/.Deprecated/Stickers/Stickers/Enums/StickerSize.cs similarity index 100% rename from Stickers/Stickers/Enums/StickerSize.cs rename to .Deprecated/Stickers/Stickers/Enums/StickerSize.cs diff --git a/Stickers/Stickers/Enums/StickerTabDoubleClick.cs b/.Deprecated/Stickers/Stickers/Enums/StickerTabDoubleClick.cs similarity index 100% rename from Stickers/Stickers/Enums/StickerTabDoubleClick.cs rename to .Deprecated/Stickers/Stickers/Enums/StickerTabDoubleClick.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Constants.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Constants.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Constants.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Constants.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Enums.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Enums.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Enums.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Enums.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Events.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Events.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Events.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Events.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Helpers.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Helpers.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Helpers.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Helpers.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Inbound.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Inbound.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Inbound.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Inbound.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Logging.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Logging.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Logging.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Logging.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Main.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Main.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Main.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Main.cs diff --git a/Stickers/Stickers/Networking/ModNetwork.Outbound.cs b/.Deprecated/Stickers/Stickers/Networking/ModNetwork.Outbound.cs similarity index 100% rename from Stickers/Stickers/Networking/ModNetwork.Outbound.cs rename to .Deprecated/Stickers/Stickers/Networking/ModNetwork.Outbound.cs diff --git a/Stickers/Stickers/StickerData.cs b/.Deprecated/Stickers/Stickers/StickerData.cs similarity index 100% rename from Stickers/Stickers/StickerData.cs rename to .Deprecated/Stickers/Stickers/StickerData.cs diff --git a/Stickers/Stickers/StickerSystem.ImageLoading.cs b/.Deprecated/Stickers/Stickers/StickerSystem.ImageLoading.cs similarity index 100% rename from Stickers/Stickers/StickerSystem.ImageLoading.cs rename to .Deprecated/Stickers/Stickers/StickerSystem.ImageLoading.cs diff --git a/Stickers/Stickers/StickerSystem.Main.cs b/.Deprecated/Stickers/Stickers/StickerSystem.Main.cs similarity index 100% rename from Stickers/Stickers/StickerSystem.Main.cs rename to .Deprecated/Stickers/Stickers/StickerSystem.Main.cs diff --git a/Stickers/Stickers/StickerSystem.PlayerCallbacks.cs b/.Deprecated/Stickers/Stickers/StickerSystem.PlayerCallbacks.cs similarity index 100% rename from Stickers/Stickers/StickerSystem.PlayerCallbacks.cs rename to .Deprecated/Stickers/Stickers/StickerSystem.PlayerCallbacks.cs diff --git a/Stickers/Stickers/StickerSystem.StickerLifecycle.cs b/.Deprecated/Stickers/Stickers/StickerSystem.StickerLifecycle.cs similarity index 100% rename from Stickers/Stickers/StickerSystem.StickerLifecycle.cs rename to .Deprecated/Stickers/Stickers/StickerSystem.StickerLifecycle.cs diff --git a/Stickers/Stickers/Utilities/ImageUtility.cs b/.Deprecated/Stickers/Stickers/Utilities/ImageUtility.cs similarity index 100% rename from Stickers/Stickers/Utilities/ImageUtility.cs rename to .Deprecated/Stickers/Stickers/Utilities/ImageUtility.cs diff --git a/Stickers/Stickers/Utilities/StickerCache.cs b/.Deprecated/Stickers/Stickers/Utilities/StickerCache.cs similarity index 100% rename from Stickers/Stickers/Utilities/StickerCache.cs rename to .Deprecated/Stickers/Stickers/Utilities/StickerCache.cs diff --git a/Stickers/format.json b/.Deprecated/Stickers/format.json similarity index 100% rename from Stickers/format.json rename to .Deprecated/Stickers/format.json diff --git a/.Deprecated/SuperAwesomeMod/README.md b/.Deprecated/SuperAwesomeMod/README.md index 399e70a..5ed44c4 100644 --- a/.Deprecated/SuperAwesomeMod/README.md +++ b/.Deprecated/SuperAwesomeMod/README.md @@ -44,11 +44,11 @@ If your setup is theoretically supported but not working, it is likely the scali --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/.Deprecated/SuperAwesomeMod/SuperAwesomeMod.csproj b/.Deprecated/SuperAwesomeMod/SuperAwesomeMod.csproj index e64907b..90cbafc 100644 --- a/.Deprecated/SuperAwesomeMod/SuperAwesomeMod.csproj +++ b/.Deprecated/SuperAwesomeMod/SuperAwesomeMod.csproj @@ -3,10 +3,4 @@ SuperAwesomeMod - - - ..\.ManagedLibs\BTKUILib.dll - False - - diff --git a/ThirdPerson/CameraLogic.cs b/.Deprecated/ThirdPerson/CameraLogic.cs similarity index 100% rename from ThirdPerson/CameraLogic.cs rename to .Deprecated/ThirdPerson/CameraLogic.cs diff --git a/ThirdPerson/Patches.cs b/.Deprecated/ThirdPerson/Patches.cs similarity index 100% rename from ThirdPerson/Patches.cs rename to .Deprecated/ThirdPerson/Patches.cs diff --git a/ThirdPerson/Properties/AssemblyInfo.cs b/.Deprecated/ThirdPerson/Properties/AssemblyInfo.cs similarity index 100% rename from ThirdPerson/Properties/AssemblyInfo.cs rename to .Deprecated/ThirdPerson/Properties/AssemblyInfo.cs diff --git a/ThirdPerson/README.md b/.Deprecated/ThirdPerson/README.md similarity index 100% rename from ThirdPerson/README.md rename to .Deprecated/ThirdPerson/README.md diff --git a/ThirdPerson/ThirdPerson.cs b/.Deprecated/ThirdPerson/ThirdPerson.cs similarity index 100% rename from ThirdPerson/ThirdPerson.cs rename to .Deprecated/ThirdPerson/ThirdPerson.cs diff --git a/ThirdPerson/ThirdPerson.csproj b/.Deprecated/ThirdPerson/ThirdPerson.csproj similarity index 100% rename from ThirdPerson/ThirdPerson.csproj rename to .Deprecated/ThirdPerson/ThirdPerson.csproj diff --git a/ThirdPerson/format.json b/.Deprecated/ThirdPerson/format.json similarity index 100% rename from ThirdPerson/format.json rename to .Deprecated/ThirdPerson/format.json diff --git a/.Experimental/BullshitWatcher/BullshitWatcher.csproj b/.Experimental/BullshitWatcher/BullshitWatcher.csproj new file mode 100644 index 0000000..fa113da --- /dev/null +++ b/.Experimental/BullshitWatcher/BullshitWatcher.csproj @@ -0,0 +1,12 @@ + + + + ASTExtension + + + + ..\.ManagedLibs\BTKUILib.dll + False + + + diff --git a/.Experimental/BullshitWatcher/Main.cs b/.Experimental/BullshitWatcher/Main.cs new file mode 100644 index 0000000..1fe66f2 --- /dev/null +++ b/.Experimental/BullshitWatcher/Main.cs @@ -0,0 +1,457 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using ABI_RC.Core.Player; +using HarmonyLib; +using MelonLoader; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace NAK.BullshitWatcher; + +public class BullshitWatcherMod : MelonMod +{ + private const float MaxAllowedValueTop = 3.402823E+7f; + private const float MaxAllowedValueBottom = -3.402823E+7f; + private const float MinAvatarHeight = 0.005f; + + public override void OnInitializeMelon() + { + PatchSetterVector3(typeof(Transform), nameof(Transform.position)); + PatchSetterVector3(typeof(Transform), nameof(Transform.localPosition)); + PatchSetterVector3(typeof(Transform), nameof(Transform.localScale)); + PatchSetterVector3(typeof(Transform), nameof(Transform.right)); + PatchSetterVector3(typeof(Transform), nameof(Transform.up)); + PatchSetterVector3(typeof(Transform), nameof(Transform.forward)); + PatchSetterQuaternion(typeof(Transform), nameof(Transform.rotation)); + PatchSetterQuaternion(typeof(Transform), nameof(Transform.localRotation)); + + PatchMethod(typeof(Transform), nameof(Transform.SetPositionAndRotation), + nameof(OnTransformSetPositionAndRotation), + typeof(Vector3), typeof(Quaternion)); + + PatchMethod(typeof(Transform), nameof(Transform.SetLocalPositionAndRotation), + nameof(OnTransformSetLocalPositionAndRotation), + typeof(Vector3), typeof(Quaternion)); + + PatchMethod(typeof(Transform), nameof(Transform.Translate), + nameof(OnTransformTranslateVector3Space), + typeof(Vector3), typeof(Space)); + + PatchMethod(typeof(Transform), nameof(Transform.Translate), + nameof(OnTransformTranslateVector3), + typeof(Vector3)); + + PatchMethod(typeof(Transform), nameof(Transform.Translate), + nameof(OnTransformTranslateVector3Transform), + typeof(Vector3), typeof(Transform)); + + PatchMethod(typeof(Transform), nameof(Transform.Rotate), + nameof(OnTransformRotateVector3Space), + typeof(Vector3), typeof(Space)); + + PatchMethod(typeof(Transform), nameof(Transform.Rotate), + nameof(OnTransformRotateVector3), + typeof(Vector3)); + + PatchMethod(typeof(Transform), nameof(Transform.Rotate), + nameof(OnTransformRotateAxisAngleSpace), + typeof(Vector3), typeof(float), typeof(Space)); + + PatchMethod(typeof(Transform), nameof(Transform.RotateAround), + nameof(OnTransformRotateAround), + typeof(Vector3), typeof(Vector3), typeof(float)); + + PatchMethod(typeof(Transform), nameof(Transform.LookAt), + nameof(OnTransformLookAt), + typeof(Vector3), typeof(Vector3)); + + PatchSetterVector3(typeof(Rigidbody), nameof(Rigidbody.position)); + PatchSetterVector3(typeof(Rigidbody), nameof(Rigidbody.velocity)); + PatchSetterVector3(typeof(Rigidbody), nameof(Rigidbody.angularVelocity)); + PatchSetterVector3(typeof(Rigidbody), nameof(Rigidbody.centerOfMass)); + PatchSetterQuaternion(typeof(Rigidbody), nameof(Rigidbody.rotation)); + + PatchMethod(typeof(Rigidbody), nameof(Rigidbody.MovePosition), + nameof(OnRigidbodyMovePosition), + typeof(Vector3)); + + PatchMethod(typeof(Rigidbody), nameof(Rigidbody.MoveRotation), + nameof(OnRigidbodyMoveRotation), + typeof(Quaternion)); + + PatchMethod(typeof(Rigidbody), nameof(Rigidbody.AddForce), + nameof(OnRigidbodyAddForce), + typeof(Vector3), typeof(ForceMode)); + + PatchMethod(typeof(Rigidbody), nameof(Rigidbody.AddRelativeForce), + nameof(OnRigidbodyAddRelativeForce), + typeof(Vector3), typeof(ForceMode)); + + PatchMethod(typeof(Rigidbody), nameof(Rigidbody.AddTorque), + nameof(OnRigidbodyAddTorque), + typeof(Vector3), typeof(ForceMode)); + + PatchMethod(typeof(Rigidbody), nameof(Rigidbody.AddRelativeTorque), + nameof(OnRigidbodyAddRelativeTorque), + typeof(Vector3), typeof(ForceMode)); + + PatchMethod(typeof(Rigidbody), nameof(Rigidbody.AddForceAtPosition), + nameof(OnRigidbodyAddForceAtPosition), + typeof(Vector3), typeof(Vector3), typeof(ForceMode)); + + PatchMethod(typeof(Object), nameof(Object.Instantiate), + nameof(OnInstantiatePositionRotation), + typeof(Object), typeof(Vector3), typeof(Quaternion)); + + PatchMethod(typeof(Object), nameof(Object.Instantiate), + nameof(OnInstantiatePositionRotationParent), + typeof(Object), typeof(Vector3), typeof(Quaternion), typeof(Transform)); + + PatchSetterAvatarHeight(typeof(PlayerSetup), nameof(PlayerSetup.AvatarHeight)); + } + + private void PatchSetterVector3(Type type, string propertyName) + => HarmonyInstance.Patch( + AccessTools.Property(type, propertyName).SetMethod, + new HarmonyMethod(GetPrefix(nameof(OnSetVector3)))); + + private void PatchSetterQuaternion(Type type, string propertyName) + => HarmonyInstance.Patch( + AccessTools.Property(type, propertyName).SetMethod, + new HarmonyMethod(GetPrefix(nameof(OnSetQuaternion)))); + + private void PatchSetterAvatarHeight(Type type, string propertyName) + => HarmonyInstance.Patch( + AccessTools.Property(type, propertyName).SetMethod, + new HarmonyMethod(GetPrefix(nameof(OnSetAvatarHeight)))); + + private void PatchMethod(Type type, string methodName, string prefixName, params Type[] parameterTypes) + => HarmonyInstance.Patch( + AccessTools.Method(type, methodName, parameterTypes), + new HarmonyMethod(GetPrefix(prefixName))); + + private static MethodInfo GetPrefix(string name) + => typeof(BullshitWatcherMod).GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe bool IsBullshit(float value) + => (((*(int*)&value) & int.MaxValue) >= 0x7F800000) + || value <= MaxAllowedValueBottom + || value >= MaxAllowedValueTop; + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsBullshit(Vector3 value) + => IsBullshit(value.x) || IsBullshit(value.y) || IsBullshit(value.z); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsBullshit(Quaternion value) + => IsBullshit(value.x) || IsBullshit(value.y) || IsBullshit(value.z) || IsBullshit(value.w); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsBullshit(Vector3 a, Vector3 b) + => IsBullshit(a.x) || IsBullshit(a.y) || IsBullshit(a.z) + || IsBullshit(b.x) || IsBullshit(b.y) || IsBullshit(b.z); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static bool IsBullshit(Vector3 vector, Quaternion quaternion) + => IsBullshit(vector.x) || IsBullshit(vector.y) || IsBullshit(vector.z) + || IsBullshit(quaternion.x) || IsBullshit(quaternion.y) || IsBullshit(quaternion.z) || IsBullshit(quaternion.w); + + // --- Sanitizers -------------------------------------------------------- + // NaN -> 0 (NaN can't be clamped meaningfully). + // +/-Infinity and out-of-range finite values -> clamped to the allowed bound. + // A bullshit Quaternion -> identity, because zeroing it produces a degenerate + // (0,0,0,0) rotation that just turns back into NaN the moment Unity normalizes it. + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static float Sanitize(float value) + { + if (float.IsNaN(value)) + return 0f; + if (value >= MaxAllowedValueTop) // also catches +Infinity + return MaxAllowedValueTop; + if (value <= MaxAllowedValueBottom) // also catches -Infinity + return MaxAllowedValueBottom; + return value; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Vector3 Sanitize(Vector3 value) + => new Vector3(Sanitize(value.x), Sanitize(value.y), Sanitize(value.z)); + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static Quaternion Sanitize(Quaternion value) + => IsBullshit(value) ? Quaternion.identity : value; + // ----------------------------------------------------------------------- + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void LogBullshitValue(Component instance, MethodBase method, object value) + { + string member = method.Name.Replace("set_", ""); + MelonLogger.Error($"Bullshit {instance.GetType().Name}.{member} = {value} on '{GetPath(instance.transform)}' (sanitized)"); + MelonLogger.Error(Environment.StackTrace); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void LogBullshitArgs1(Component instance, MethodBase method, object arg0) + { + MelonLogger.Error($"Bullshit args in {instance.GetType().Name}.{method.Name}() on '{GetPath(instance.transform)}' (sanitized)"); + MelonLogger.Error($" arg0: {arg0}"); + MelonLogger.Error(Environment.StackTrace); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void LogBullshitArgs2(Component instance, MethodBase method, object arg0, object arg1) + { + MelonLogger.Error($"Bullshit args in {instance.GetType().Name}.{method.Name}() on '{GetPath(instance.transform)}' (sanitized)"); + MelonLogger.Error($" arg0: {arg0}"); + MelonLogger.Error($" arg1: {arg1}"); + MelonLogger.Error(Environment.StackTrace); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void LogBullshitArgs3(Component instance, MethodBase method, object arg0, object arg1, object arg2) + { + MelonLogger.Error($"Bullshit args in {instance.GetType().Name}.{method.Name}() on '{GetPath(instance.transform)}' (sanitized)"); + MelonLogger.Error($" arg0: {arg0}"); + MelonLogger.Error($" arg1: {arg1}"); + MelonLogger.Error($" arg2: {arg2}"); + MelonLogger.Error(Environment.StackTrace); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void LogBullshitInstantiate(MethodBase method, Object original, Vector3 position, Quaternion rotation, Transform parent) + { + string originalName = original != null ? original.name : "null"; + string parentPath = parent != null ? GetPath(parent) : ""; + + MelonLogger.Error($"Bullshit args in Object.{method.Name}() original='{originalName}' parent='{parentPath}' (sanitized)"); + MelonLogger.Error($" position: {position}"); + MelonLogger.Error($" rotation: {rotation}"); + MelonLogger.Error(Environment.StackTrace); + } + + private static void OnSetVector3(ref Vector3 value, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(value)) + return; + + LogBullshitValue(__instance, __originalMethod, value); + value = Sanitize(value); + } + + private static void OnSetQuaternion(ref Quaternion value, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(value)) + return; + + LogBullshitValue(__instance, __originalMethod, value); + value = Sanitize(value); + } + + private static void OnSetAvatarHeight(ref float value, Component __instance, MethodBase __originalMethod) + { + float clamped; + if (float.IsNaN(value) || value < MinAvatarHeight) // also catches 0, negatives, -Infinity + clamped = MinAvatarHeight; + else if (value > MaxAllowedValueTop) // also catches +Infinity + clamped = MaxAllowedValueTop; + else + return; // height is fine, leave it alone + + LogBullshitValue(__instance, __originalMethod, value); + value = clamped; + } + + private static void OnTransformSetPositionAndRotation(ref Vector3 position, ref Quaternion rotation, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(position, rotation)) + return; + + LogBullshitArgs2(__instance, __originalMethod, position, rotation); + position = Sanitize(position); + rotation = Sanitize(rotation); + } + + private static void OnTransformSetLocalPositionAndRotation(ref Vector3 localPosition, ref Quaternion localRotation, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(localPosition, localRotation)) + return; + + LogBullshitArgs2(__instance, __originalMethod, localPosition, localRotation); + localPosition = Sanitize(localPosition); + localRotation = Sanitize(localRotation); + } + + private static void OnTransformTranslateVector3Space(ref Vector3 translation, Space relativeTo, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(translation)) + return; + + LogBullshitArgs2(__instance, __originalMethod, translation, relativeTo); + translation = Sanitize(translation); + } + + private static void OnTransformTranslateVector3(ref Vector3 translation, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(translation)) + return; + + LogBullshitArgs1(__instance, __originalMethod, translation); + translation = Sanitize(translation); + } + + private static void OnTransformTranslateVector3Transform(ref Vector3 translation, Transform relativeTo, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(translation)) + return; + + LogBullshitArgs2(__instance, __originalMethod, translation, relativeTo); + translation = Sanitize(translation); + } + + private static void OnTransformRotateVector3Space(ref Vector3 eulers, Space relativeTo, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(eulers)) + return; + + LogBullshitArgs2(__instance, __originalMethod, eulers, relativeTo); + eulers = Sanitize(eulers); + } + + private static void OnTransformRotateVector3(ref Vector3 eulers, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(eulers)) + return; + + LogBullshitArgs1(__instance, __originalMethod, eulers); + eulers = Sanitize(eulers); + } + + private static void OnTransformRotateAxisAngleSpace(ref Vector3 axis, ref float angle, Space relativeTo, Component __instance, MethodBase __originalMethod) + { + if (!(IsBullshit(axis) || IsBullshit(angle))) + return; + + LogBullshitArgs3(__instance, __originalMethod, axis, angle, relativeTo); + axis = Sanitize(axis); + angle = Sanitize(angle); + } + + private static void OnTransformRotateAround(ref Vector3 point, ref Vector3 axis, ref float angle, Component __instance, MethodBase __originalMethod) + { + if (!(IsBullshit(point, axis) || IsBullshit(angle))) + return; + + LogBullshitArgs3(__instance, __originalMethod, point, axis, angle); + point = Sanitize(point); + axis = Sanitize(axis); + angle = Sanitize(angle); + } + + private static void OnTransformLookAt(ref Vector3 worldPosition, ref Vector3 worldUp, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(worldPosition, worldUp)) + return; + + LogBullshitArgs2(__instance, __originalMethod, worldPosition, worldUp); + worldPosition = Sanitize(worldPosition); + // worldUp must stay a usable direction; a zeroed up vector makes LookAt produce garbage. + worldUp = Sanitize(worldUp); + if (worldUp == Vector3.zero) + worldUp = Vector3.up; + } + + private static void OnRigidbodyMovePosition(ref Vector3 position, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(position)) + return; + + LogBullshitArgs1(__instance, __originalMethod, position); + position = Sanitize(position); + } + + private static void OnRigidbodyMoveRotation(ref Quaternion rot, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(rot)) + return; + + LogBullshitArgs1(__instance, __originalMethod, rot); + rot = Sanitize(rot); + } + + private static void OnRigidbodyAddForce(ref Vector3 force, ForceMode mode, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(force)) + return; + + LogBullshitArgs2(__instance, __originalMethod, force, mode); + force = Sanitize(force); + } + + private static void OnRigidbodyAddRelativeForce(ref Vector3 force, ForceMode mode, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(force)) + return; + + LogBullshitArgs2(__instance, __originalMethod, force, mode); + force = Sanitize(force); + } + + private static void OnRigidbodyAddTorque(ref Vector3 torque, ForceMode mode, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(torque)) + return; + + LogBullshitArgs2(__instance, __originalMethod, torque, mode); + torque = Sanitize(torque); + } + + private static void OnRigidbodyAddRelativeTorque(ref Vector3 torque, ForceMode mode, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(torque)) + return; + + LogBullshitArgs2(__instance, __originalMethod, torque, mode); + torque = Sanitize(torque); + } + + private static void OnRigidbodyAddForceAtPosition(ref Vector3 force, ref Vector3 position, ForceMode mode, Component __instance, MethodBase __originalMethod) + { + if (!IsBullshit(force, position)) + return; + + LogBullshitArgs3(__instance, __originalMethod, force, position, mode); + force = Sanitize(force); + position = Sanitize(position); + } + + private static void OnInstantiatePositionRotation(Object original, ref Vector3 position, ref Quaternion rotation, MethodBase __originalMethod) + { + if (!IsBullshit(position, rotation)) + return; + + LogBullshitInstantiate(__originalMethod, original, position, rotation, null); + position = Sanitize(position); + rotation = Sanitize(rotation); + } + + private static void OnInstantiatePositionRotationParent(Object original, ref Vector3 position, ref Quaternion rotation, Transform parent, MethodBase __originalMethod) + { + if (!IsBullshit(position, rotation)) + return; + + LogBullshitInstantiate(__originalMethod, original, position, rotation, parent); + position = Sanitize(position); + rotation = Sanitize(rotation); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static string GetPath(Transform current) + { + string path = current.name; + for (Transform parent = current.parent; parent != null; parent = parent.parent) + path = parent.name + "/" + path; + return path; + } +} \ No newline at end of file diff --git a/.Experimental/BullshitWatcher/Properties/AssemblyInfo.cs b/.Experimental/BullshitWatcher/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..ee1bd3e --- /dev/null +++ b/.Experimental/BullshitWatcher/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.BullshitWatcher.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.BullshitWatcher))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.BullshitWatcher))] + +[assembly: MelonInfo( + typeof(NAK.BullshitWatcher.BullshitWatcherMod), + nameof(NAK.BullshitWatcher), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/BullshitWatcher" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.BullshitWatcher.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Experimental/BullshitWatcher/README.md b/.Experimental/BullshitWatcher/README.md new file mode 100644 index 0000000..399e70a --- /dev/null +++ b/.Experimental/BullshitWatcher/README.md @@ -0,0 +1,54 @@ +# ASTExtension + +Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool): +- VR Gesture to scale +- Persistent height +- Copy height from others + +Best used with Avatar Scale Tool, but will attempt to work with found scaling setups. +Requires already having Avatar Scaling on the avatar. This is **not** Universal Scaling. + +## Supported Setups + +ASTExtension will attempt to work with the following setups: + +**Parameter Names:** +- AvatarScale +- Scale +- Scaler +- Scale/Scale +- Height +- LoliModifier +- AvatarSize +- Size +- SizeScale +- Scaling + +These parameter names are not case sensitive and have been gathered from polling the community for common parameter names. + +Assuming the parameter is a float, ASTExtension will attempt to use it as the height parameter. Will automatically calibrate to the height range of the found parameter, assuming the scaling animation is in a blend tree / state using motion time & is linear. The scaling animation state **must be active** at time of avatar load. + +The max value ASTExtension will drive the parameter to is 100. As the mod is having to guess the max height, it may not be accurate if the max height is not capped at a multiple of 10. + +Examples: +- `AvatarScale` - 0 to 1 (slider) + - This is the default setup for Avatar Scale Tool and will work perfectly. +- `Scale` - 0 to 100 (input single) + - This will also work perfectly as the max height is a multiple of 10. +- `Height` - 0 to 2 (input single) + - This will not work properly. The max value to drive the parameter to is not a multiple of 10, and as such ASTExtension will believe the parameter range is 0 to 1. +- `BurntToast` - 0 to 10 (input single) + - This will not work properly. The parameter name is not recognized by ASTExtension. + +If your setup is theoretically supported but not working, it is likely the scaling animation is not linear or has loop enabled if using Motion Time, making the first and last frame identical height. In this case, you will need to fix your animation clip curves / blend tree to be linear &|| not loop, or use Avatar Scale Tool to generate a new scaling animation. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Experimental/BullshitWatcher/format.json b/.Experimental/BullshitWatcher/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/.Experimental/BullshitWatcher/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Experimental/FeedbackDotChilloutVRDotNet/FeedbackDotChilloutVRDotNet.csproj b/.Experimental/FeedbackDotChilloutVRDotNet/FeedbackDotChilloutVRDotNet.csproj new file mode 100644 index 0000000..78195e6 --- /dev/null +++ b/.Experimental/FeedbackDotChilloutVRDotNet/FeedbackDotChilloutVRDotNet.csproj @@ -0,0 +1,6 @@ + + + + ASTExtension + + diff --git a/.Experimental/FeedbackDotChilloutVRDotNet/Main.cs b/.Experimental/FeedbackDotChilloutVRDotNet/Main.cs new file mode 100644 index 0000000..50f090a --- /dev/null +++ b/.Experimental/FeedbackDotChilloutVRDotNet/Main.cs @@ -0,0 +1,110 @@ +using ABI_RC.Core.Player; +using ABI_RC.Systems.ChatBox; +using ABI_RC.Systems.UI.UILib; +using ABI_RC.Systems.UI.UILib.UIObjects; +using ABI_RC.Systems.UI.UILib.UIObjects.Components; +using MelonLoader; + +namespace NAK.FeedbackDotChilloutVRDotNet; + +public class FeedbackDotChilloutVRDotNetMod : MelonMod +{ + private static MelonPreferences_Category _prefs; + private static MelonPreferences_Entry _autoReact; + + public override void OnInitializeMelon() + { + // Emails: + // Moderation Reports moderation@chilloutvr.net + // Legal legal@chilloutvr.net + // Team (general feedback, bug reports) team@chilloutvr.net + + // Websites: + // Feedback (Issue Tracker) feedback.chilloutvr.net + // Docs docs.chilloutvr.net + // Hub hub.chilloutvr.net + // Discord discord.gg/chilloutvr + + // Quick Messages: + // I am not moderation. You will need to reach out to moderation@chilloutvr.net. + + // Auto React (goofy, behind toggle): + // issue, bug -> feedback site + // nak fix, @NotAKid fix, @NotAKidoS fix, pls fix, go fix -> no + + _prefs = MelonPreferences.CreateCategory(nameof(FeedbackDotChilloutVRDotNetMod)); + _autoReact = _prefs.CreateEntry("AutoReact", false, "Auto React", + "Automatically reply to messages containing certain keywords (goofy)."); + + SetupMenu(); + SetupAutoReact(); + } + + private static void SetupMenu() + { + Category category = QuickMenuAPI.MiscTabPage.AddCategory("Quick ChatBox Messages", true, true); + category.ChildIndex = 0; + + // Websites + AddMessageButton(category, "Feedback", "feedback.chilloutvr.net"); + AddMessageButton(category, "Docs", "docs.chilloutvr.net"); + AddMessageButton(category, "Hub", "hub.chilloutvr.net"); + AddMessageButton(category, "Discord", "discord.gg/chilloutvr"); + + // Emails + AddMessageButton(category, "Moderation", "moderation@chilloutvr.net"); + AddMessageButton(category, "Legal", "legal@chilloutvr.net"); + AddMessageButton(category, "Team", "team@chilloutvr.net"); + + // Canned responses + AddMessageButton(category, "Not Moderation", + "I am not moderation. You will need to reach out to moderation@chilloutvr.net."); + + // Toggle for the goofy auto-react interceptor + ToggleButton autoReactToggle = category.AddToggle("Auto React", + "Automatically reply to messages with certain keywords (goofy).", + _autoReact.Value); + autoReactToggle.OnValueUpdated += b => _autoReact.Value = b; + } + + private static Button AddMessageButton(Category category, string name, string message) + { + Button button = category.AddButton(name, string.Empty, message, ButtonStyle.TextOnly); + button.OnPress += () => ChatBoxAPI.SendMessage(message, true, true, false); + return button; + } + + private static readonly ChatBoxAPI.InterceptorResult _emptyCauseCantReturnNull = new(false, false); + + private static void SetupAutoReact() + { + ChatBoxAPI.AddReceivingInterceptor(message => + { + if (_autoReact.Value) + { + string text = message.Message; + string username = CVRPlayerManager.Instance.TryGetPlayerName(message.SenderGuid); + + // Order matters: catch the "fix" demands before the generic feedback keywords. + if (ContainsAny(text, "nak fix", "@NotAKid fix", "@NotAKidoS fix", "pls fix", "go fix")) + ChatBoxAPI.SendMessage($"@{username} no", true, true, false); + else if (ContainsAny(text, "issue", "bug", "feedback")) + ChatBoxAPI.SendMessage($"@{username} feedback.chilloutvr.net", true, true, false); + + // game broke -> remove mods, find player.log + + } + return _emptyCauseCantReturnNull; + }); + } + + private static bool ContainsAny(string source, params string[] values) + { + foreach (string value in values) + { + if (source.Contains(value, StringComparison.InvariantCultureIgnoreCase)) + return true; + } + return false; + } +} \ No newline at end of file diff --git a/.Experimental/FeedbackDotChilloutVRDotNet/Properties/AssemblyInfo.cs b/.Experimental/FeedbackDotChilloutVRDotNet/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8cea620 --- /dev/null +++ b/.Experimental/FeedbackDotChilloutVRDotNet/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.FeedbackDotChilloutVRDotNet.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.FeedbackDotChilloutVRDotNet))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.FeedbackDotChilloutVRDotNet))] + +[assembly: MelonInfo( + typeof(NAK.FeedbackDotChilloutVRDotNet.FeedbackDotChilloutVRDotNetMod), + nameof(NAK.FeedbackDotChilloutVRDotNet), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/FeedbackDotChilloutVRDotNet" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.FeedbackDotChilloutVRDotNet.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Experimental/FeedbackDotChilloutVRDotNet/README.md b/.Experimental/FeedbackDotChilloutVRDotNet/README.md new file mode 100644 index 0000000..399e70a --- /dev/null +++ b/.Experimental/FeedbackDotChilloutVRDotNet/README.md @@ -0,0 +1,54 @@ +# ASTExtension + +Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool): +- VR Gesture to scale +- Persistent height +- Copy height from others + +Best used with Avatar Scale Tool, but will attempt to work with found scaling setups. +Requires already having Avatar Scaling on the avatar. This is **not** Universal Scaling. + +## Supported Setups + +ASTExtension will attempt to work with the following setups: + +**Parameter Names:** +- AvatarScale +- Scale +- Scaler +- Scale/Scale +- Height +- LoliModifier +- AvatarSize +- Size +- SizeScale +- Scaling + +These parameter names are not case sensitive and have been gathered from polling the community for common parameter names. + +Assuming the parameter is a float, ASTExtension will attempt to use it as the height parameter. Will automatically calibrate to the height range of the found parameter, assuming the scaling animation is in a blend tree / state using motion time & is linear. The scaling animation state **must be active** at time of avatar load. + +The max value ASTExtension will drive the parameter to is 100. As the mod is having to guess the max height, it may not be accurate if the max height is not capped at a multiple of 10. + +Examples: +- `AvatarScale` - 0 to 1 (slider) + - This is the default setup for Avatar Scale Tool and will work perfectly. +- `Scale` - 0 to 100 (input single) + - This will also work perfectly as the max height is a multiple of 10. +- `Height` - 0 to 2 (input single) + - This will not work properly. The max value to drive the parameter to is not a multiple of 10, and as such ASTExtension will believe the parameter range is 0 to 1. +- `BurntToast` - 0 to 10 (input single) + - This will not work properly. The parameter name is not recognized by ASTExtension. + +If your setup is theoretically supported but not working, it is likely the scaling animation is not linear or has loop enabled if using Motion Time, making the first and last frame identical height. In this case, you will need to fix your animation clip curves / blend tree to be linear &|| not loop, or use Avatar Scale Tool to generate a new scaling animation. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Experimental/FeedbackDotChilloutVRDotNet/format.json b/.Experimental/FeedbackDotChilloutVRDotNet/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/.Experimental/FeedbackDotChilloutVRDotNet/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Experimental/FuckDebugConsole/FuckDebugConsole.csproj b/.Experimental/FuckDebugConsole/FuckDebugConsole.csproj new file mode 100644 index 0000000..78195e6 --- /dev/null +++ b/.Experimental/FuckDebugConsole/FuckDebugConsole.csproj @@ -0,0 +1,6 @@ + + + + ASTExtension + + diff --git a/.Experimental/FuckDebugConsole/Main.cs b/.Experimental/FuckDebugConsole/Main.cs new file mode 100644 index 0000000..b9257de --- /dev/null +++ b/.Experimental/FuckDebugConsole/Main.cs @@ -0,0 +1,23 @@ +using MelonLoader; +using UnityEngine; + +namespace NAK.FuckDebugConsole; + +public class FuckDebugConsoleMod : MelonMod +{ + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(FuckDebugConsole)); + + internal static readonly MelonPreferences_Entry EntryEnableDebugConsole = + Category.CreateEntry("enable_debug_console", false, + "Enable Debug Console", description: "Whether to use the debug console at all."); + + public override void OnInitializeMelon() + { + Debug.developerConsoleEnabled = EntryEnableDebugConsole.Value; + EntryEnableDebugConsole.OnEntryValueChanged.Subscribe((oldValue, newValue) => + { + Debug.developerConsoleEnabled = newValue; + }); + } +} \ No newline at end of file diff --git a/.Experimental/FuckDebugConsole/Properties/AssemblyInfo.cs b/.Experimental/FuckDebugConsole/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..04bbea6 --- /dev/null +++ b/.Experimental/FuckDebugConsole/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.FuckDebugConsole.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.FuckDebugConsole))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.FuckDebugConsole))] + +[assembly: MelonInfo( + typeof(NAK.FuckDebugConsole.FuckDebugConsoleMod), + nameof(NAK.FuckDebugConsole), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/FuckDebugConsole" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.FuckDebugConsole.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/.Experimental/FuckDebugConsole/README.md b/.Experimental/FuckDebugConsole/README.md new file mode 100644 index 0000000..399e70a --- /dev/null +++ b/.Experimental/FuckDebugConsole/README.md @@ -0,0 +1,54 @@ +# ASTExtension + +Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool): +- VR Gesture to scale +- Persistent height +- Copy height from others + +Best used with Avatar Scale Tool, but will attempt to work with found scaling setups. +Requires already having Avatar Scaling on the avatar. This is **not** Universal Scaling. + +## Supported Setups + +ASTExtension will attempt to work with the following setups: + +**Parameter Names:** +- AvatarScale +- Scale +- Scaler +- Scale/Scale +- Height +- LoliModifier +- AvatarSize +- Size +- SizeScale +- Scaling + +These parameter names are not case sensitive and have been gathered from polling the community for common parameter names. + +Assuming the parameter is a float, ASTExtension will attempt to use it as the height parameter. Will automatically calibrate to the height range of the found parameter, assuming the scaling animation is in a blend tree / state using motion time & is linear. The scaling animation state **must be active** at time of avatar load. + +The max value ASTExtension will drive the parameter to is 100. As the mod is having to guess the max height, it may not be accurate if the max height is not capped at a multiple of 10. + +Examples: +- `AvatarScale` - 0 to 1 (slider) + - This is the default setup for Avatar Scale Tool and will work perfectly. +- `Scale` - 0 to 100 (input single) + - This will also work perfectly as the max height is a multiple of 10. +- `Height` - 0 to 2 (input single) + - This will not work properly. The max value to drive the parameter to is not a multiple of 10, and as such ASTExtension will believe the parameter range is 0 to 1. +- `BurntToast` - 0 to 10 (input single) + - This will not work properly. The parameter name is not recognized by ASTExtension. + +If your setup is theoretically supported but not working, it is likely the scaling animation is not linear or has loop enabled if using Motion Time, making the first and last frame identical height. In this case, you will need to fix your animation clip curves / blend tree to be linear &|| not loop, or use Avatar Scale Tool to generate a new scaling animation. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. +https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games + +> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. diff --git a/.Experimental/FuckDebugConsole/format.json b/.Experimental/FuckDebugConsole/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/.Experimental/FuckDebugConsole/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/.Experimental/LuaNetworkVariables/README.md b/.Experimental/LuaNetworkVariables/README.md index 5ad6ee2..4fc40ea 100644 --- a/.Experimental/LuaNetworkVariables/README.md +++ b/.Experimental/LuaNetworkVariables/README.md @@ -75,11 +75,11 @@ end --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/.Experimental/OriginShift/OriginShift.csproj b/.Experimental/OriginShift/OriginShift.csproj index d65c89e..5fc1ec8 100644 --- a/.Experimental/OriginShift/OriginShift.csproj +++ b/.Experimental/OriginShift/OriginShift.csproj @@ -1,16 +1,11 @@ - - ..\.ManagedLibs\BTKUILib.dll - - - - - - - - + + + + + diff --git a/.Experimental/OriginShift/README.md b/.Experimental/OriginShift/README.md index 35bb285..7ac709e 100644 --- a/.Experimental/OriginShift/README.md +++ b/.Experimental/OriginShift/README.md @@ -42,11 +42,11 @@ The provided receiver components are automatically added to Props, Players, and --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/ASTExtension/ASTExtension.csproj b/ASTExtension/ASTExtension.csproj index 6bbefe0..0f491d4 100644 --- a/ASTExtension/ASTExtension.csproj +++ b/ASTExtension/ASTExtension.csproj @@ -1,15 +1,9 @@ - - ASTExtension - - - - ..\.ManagedLibs\BTKUILib.dll - False - - + + + diff --git a/ASTExtension/Integrations/BTKUI/BtkUiAddon.cs b/ASTExtension/Integrations/BTKUI/BtkUiAddon.cs index e075e88..859f703 100644 --- a/ASTExtension/Integrations/BTKUI/BtkUiAddon.cs +++ b/ASTExtension/Integrations/BTKUI/BtkUiAddon.cs @@ -1,8 +1,8 @@ using ABI_RC.Core.Player; using ABI_RC.Core.Util.AnimatorManager; -using BTKUILib; -using BTKUILib.UIObjects; -using BTKUILib.UIObjects.Components; +using ABI_RC.Systems.UI.UILib; +using ABI_RC.Systems.UI.UILib.UIObjects; +using ABI_RC.Systems.UI.UILib.UIObjects.Components; using UnityEngine; namespace NAK.ASTExtension.Integrations; @@ -11,15 +11,15 @@ public static partial class BtkUiAddon { public static void Initialize() { - Prepare_Icons(); - Setup_PlayerSelectPage(); - } + Prepare_Icons(); + Setup_PlayerSelectPage(); + } private static void Prepare_Icons() { - QuickMenuAPI.PrepareIcon(ASTExtensionMod.ModName, "ASM_Icon_AvatarHeightCopy", - GetIconStream("ASM_Icon_AvatarHeightCopy.png")); - } + QuickMenuAPI.PrepareIcon(ASTExtensionMod.ModName, "ASM_Icon_AvatarHeightCopy", GetIconStream("ASM_Icon_AvatarHeightCopy.png")); + QuickMenuAPI.PrepareIcon(ASTExtensionMod.ModName, "CopyAvatarAASAlt", GetIconStream("CopyAvatarAASAlt.png")); + } #region Player Select Page @@ -27,20 +27,20 @@ public static partial class BtkUiAddon private static void Setup_PlayerSelectPage() { - QuickMenuAPI.OnPlayerSelected += OnPlayerSelected; - Category category = QuickMenuAPI.PlayerSelectPage.AddCategory(ASTExtensionMod.ModName, ASTExtensionMod.ModName); - Button button = category.AddButton("Copy Height", "ASM_Icon_AvatarHeightCopy", "Copy selected players Eye Height."); - button.OnPress += OnCopyPlayerHeight; - - Button button2 = category.AddButton("Copy AAS", string.Empty, "Copy selected players AAS."); - button2.OnPress += OnCopyPlayerAAS; - } + QuickMenuAPI.OnPlayerSelected += OnPlayerSelected; + Category category = QuickMenuAPI.PlayerSelectPage.AddCategory(ASTExtensionMod.ModName, ASTExtensionMod.ModName); + Button button = category.AddButton("Copy Height", "ASM_Icon_AvatarHeightCopy", "Copy selected players Eye Height."); + button.OnPress += OnCopyPlayerHeight; + + Button button2 = category.AddButton("Copy AAS", "CopyAvatarAASAlt", "Copy selected players AAS."); + button2.OnPress += OnCopyPlayerAAS; + } private static void OnPlayerSelected(string _, string id) { - _selectedPlayer = id; - } - + _selectedPlayer = id; + } + private static void OnCopyPlayerHeight() { if (string.IsNullOrEmpty(_selectedPlayer)) @@ -90,8 +90,6 @@ public static partial class BtkUiAddon break; } } - - } #endregion Player Select Page diff --git a/ASTExtension/Main.cs b/ASTExtension/Main.cs index 4ddf871..34883e6 100644 --- a/ASTExtension/Main.cs +++ b/ASTExtension/Main.cs @@ -1,14 +1,17 @@ using System.Reflection; +using ABI_RC.Core; using ABI_RC.Core.InteractionSystem; using ABI_RC.Core.Player; using ABI_RC.Core.Savior; using ABI_RC.Core.Util; using ABI_RC.Core.Util.AnimatorManager; +using ABI_RC.Systems.IK; using ABI_RC.Systems.InputManagement; using ABI.CCK.Components; using HarmonyLib; using MelonLoader; using NAK.ASTExtension.Extensions; +using NAK.Contacts; using UnityEngine; namespace NAK.ASTExtension; @@ -74,8 +77,8 @@ public class ASTExtensionMod : MelonMod ); HarmonyInstance.Patch( - typeof(ColliderTools).GetMethod(nameof(ColliderTools.PlaceDefaultPointers), - BindingFlags.Public | BindingFlags.Static), + typeof(IKSystem).GetMethod(nameof(IKSystem.OnAvatarInitialized), + BindingFlags.Public | BindingFlags.Instance), postfix: new HarmonyMethod(typeof(ASTExtensionMod).GetMethod(nameof(OnSetupAvatar), BindingFlags.NonPublic | BindingFlags.Static)) ); @@ -86,17 +89,8 @@ public class ASTExtensionMod : MelonMod prefix: new HarmonyMethod(typeof(ASTExtensionMod).GetMethod(nameof(OnClearAvatar), BindingFlags.NonPublic | BindingFlags.Static)) ); - - InitializeIntegration("BTKUILib", Integrations.BtkUiAddon.Initialize); - } - private static void InitializeIntegration(string modName, Action integrationAction) - { - if (RegisteredMelons.All(it => it.Info.Name != modName)) - return; - - Logger.Msg($"Initializing {modName} integration."); - integrationAction.Invoke(); + Integrations.BtkUiAddon.Initialize(); } #endregion Melon Events @@ -106,9 +100,8 @@ public class ASTExtensionMod : MelonMod private static void OnGestureRecogniserInitialized() => Instance.InitializeScaleGesture(); - private static void OnSetupAvatar(bool isLocalPlayer) + private static void OnSetupAvatar() { - if (!isLocalPlayer) return; Instance.OnLocalAvatarLoad(); } diff --git a/ASTExtension/Properties/AssemblyInfo.cs b/ASTExtension/Properties/AssemblyInfo.cs index 427308d..e392b9e 100644 --- a/ASTExtension/Properties/AssemblyInfo.cs +++ b/ASTExtension/Properties/AssemblyInfo.cs @@ -27,6 +27,6 @@ using System.Reflection; namespace NAK.ASTExtension.Properties; internal static class AssemblyInfoParams { - public const string Version = "1.0.5"; + public const string Version = "1.0.6"; public const string Author = "NotAKidoS"; } \ No newline at end of file diff --git a/ASTExtension/README.md b/ASTExtension/README.md index 399e70a..5ed44c4 100644 --- a/ASTExtension/README.md +++ b/ASTExtension/README.md @@ -44,11 +44,11 @@ If your setup is theoretically supported but not working, it is likely the scali --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/ASTExtension/Resources/CopyAvatarAASAlt.png b/ASTExtension/Resources/CopyAvatarAASAlt.png new file mode 100644 index 0000000..0b0ba02 Binary files /dev/null and b/ASTExtension/Resources/CopyAvatarAASAlt.png differ diff --git a/ASTExtension/format.json b/ASTExtension/format.json index 390aeac..37a2135 100644 --- a/ASTExtension/format.json +++ b/ASTExtension/format.json @@ -1,8 +1,8 @@ { "_id": 223, "name": "ASTExtension", - "modversion": "1.0.5", - "gameversion": "2025r181", + "modversion": "1.0.6", + "gameversion": "2026r181", "loaderversion": "0.7.2", "modtype": "Mod", "author": "NotAKidoS", @@ -17,8 +17,8 @@ "requirements": [ "BTKUILib" ], - "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r49/ASTExtension.dll", "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", - "changelog": "- Rebuilt for CVR 2025r181", + "changelog": "- Rebuilt for CVR 2026r181", "embedcolor": "#f61963" } \ No newline at end of file diff --git a/AutoAccept/AutoAccept.csproj b/AutoAccept/AutoAccept.csproj new file mode 100644 index 0000000..dca6210 --- /dev/null +++ b/AutoAccept/AutoAccept.csproj @@ -0,0 +1,6 @@ + + + + AutoAcceptByCategory + + diff --git a/AutoAccept/Main.cs b/AutoAccept/Main.cs new file mode 100644 index 0000000..3a8e5c4 --- /dev/null +++ b/AutoAccept/Main.cs @@ -0,0 +1,508 @@ +using ABI_RC.Core.InteractionSystem; +using ABI_RC.Core.Networking.API; +using ABI_RC.Core.Networking.API.Responses; +using ABI_RC.Core.Networking.API.UserWebsocket; +using ABI_RC.Core.Networking.IO.Social; +using HarmonyLib; +using MelonLoader; +using System.Reflection; +using ABI_RC.Core.Networking; +using ABI_RC.Core.UI; + +namespace NAK.AutoAccept; + +public class AutoAcceptMod : MelonMod +{ + private static readonly MelonPreferences_Category Category = MelonPreferences.CreateCategory(nameof(AutoAccept)); + + private enum InviteStatus + { + Ask, + AllFriends, + SelectCategories, + DoNotDisturb + } + + private static readonly MelonPreferences_Entry EntryInviteStatus = + Category.CreateEntry( + identifier: "invite_status", + InviteStatus.Ask, + display_name: "Invite Status", + description: "How incoming invite requests are handled."); + + private static readonly MelonPreferences_Entry EntryAutoAcceptCategories = + Category.CreateEntry( + identifier: "auto_accept_categories", + "", + display_name: "Auto Accept Categories", + description: "Categories whose members get auto-accepted in Select mode."); + + public override void OnInitializeMelon() + { + HarmonyInstance.Patch( // auto accept + typeof(ViewManager).GetMethod(nameof(ViewManager.ShowInviteRequest), + BindingFlags.Public | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(AutoAcceptMod).GetMethod(nameof(OnPreShowInviteRequest), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( // add useful notification + typeof(ViewManager).GetMethod(nameof(ViewManager.UpdateInvites), + BindingFlags.Public | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(AutoAcceptMod).GetMethod(nameof(OnPreUpdateInvites), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( // eat useless notifications + typeof(ViewManager).GetMethod(nameof(ViewManager.BufferMenuPopup), + BindingFlags.Public | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(AutoAcceptMod).GetMethod(nameof(OnPreBufferMenuPopup), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( // add useful notification + typeof(ViewManager).GetMethod(nameof(ViewManager.InvitePlayer), + BindingFlags.Public | BindingFlags.Instance), + postfix: new HarmonyMethod(typeof(AutoAcceptMod).GetMethod(nameof(OnPostInvitePlayer), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( // add useful notification + typeof(ViewManager).GetMethod(nameof(ViewManager.RequestInvite), + BindingFlags.Public | BindingFlags.Instance), + postfix: new HarmonyMethod(typeof(AutoAcceptMod).GetMethod(nameof(OnPostRequestInvite), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( // new menu buttons + typeof(ViewManager).GetMethod(nameof(ViewManager.Start), + BindingFlags.NonPublic | BindingFlags.Instance), + postfix: new HarmonyMethod(typeof(AutoAcceptMod).GetMethod(nameof(OnViewManagerStart), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + Friends.OnFriendListUpdated += OnFriendsListUpdated; + + LoadAutoAcceptCategories(); + } + + private static readonly HashSet _autoAcceptCategories = new(); + + private static void LoadAutoAcceptCategories() + { + _autoAcceptCategories.Clear(); + string raw = EntryAutoAcceptCategories.Value; + if (string.IsNullOrEmpty(raw)) return; + foreach (string key in raw.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)) + _autoAcceptCategories.Add(key.Trim()); + } + + private static void SaveAutoAcceptCategories() + { + EntryAutoAcceptCategories.Value = string.Join(",", _autoAcceptCategories); + } + + private static readonly HashSet AutoAcceptUserIds = new(); + + private static void OnFriendsListUpdated() + { + RebuildAutoAcceptUserIds(); + PushAutoAcceptCategoriesToJs(); + } + + private static void RebuildAutoAcceptUserIds() + { + AutoAcceptUserIds.Clear(); + if (_autoAcceptCategories.Count > 0) + { + foreach (var (userId, friendInfo) in Friends.CurrentFriendsInfo) + { + if (friendInfo.Categories.Any(cat => _autoAcceptCategories.Contains(cat))) + { + AutoAcceptUserIds.Add(userId); + } + } + } + AutoAcceptUserIds.TrimExcess(); + } + + private static readonly HashSet UselessMenuPopups = + [ + "You have already 3 outstanding invites to this user.", + "Invite sent.", + "Request invite successfully sent." + ]; + + private static void OnPreBufferMenuPopup(string message, ref bool __runOriginal) + { + // Kill the annoying fuckers + if (UselessMenuPopups.Contains(message)) __runOriginal = false; + } + + private static void OnPreUpdateInvites(List invites) + { + // Display received notification for incoming requests + for (int index = 0; index < invites.Count; index++) + { + Invite invite = invites[index]; + ReceiveInvite(invite); + } + } + + private static void OnPreShowInviteRequest(List requestInvites, ref bool __runOriginal) + { + // Intercept and process incoming invite requests + bool canAutoAcceptInvite = NetworkManager.Instance.IsConnectedToGameNetwork(); + switch (EntryInviteStatus.Value) + { + default: + case InviteStatus.Ask: + break; + case InviteStatus.AllFriends: + for (var index = requestInvites.Count - 1; index >= 0; index--) + { + RequestInvite inviteRequest = requestInvites[index]; + if (!canAutoAcceptInvite) CannotAcceptInviteRequest(inviteRequest); + else if (Friends.FriendsWith(inviteRequest.Sender.Id)) + { + __runOriginal = false; + requestInvites.Remove(inviteRequest); + AcceptInviteRequest(inviteRequest); + } + } + break; + case InviteStatus.SelectCategories: + for (var index = requestInvites.Count - 1; index >= 0; index--) + { + RequestInvite inviteRequest = requestInvites[index]; + if (!canAutoAcceptInvite) CannotAcceptInviteRequest(inviteRequest); + else if (AutoAcceptUserIds.Contains(inviteRequest.Sender.Id)) + { + __runOriginal = false; + requestInvites.Remove(inviteRequest); + AcceptInviteRequest(inviteRequest); + } + } + break; + case InviteStatus.DoNotDisturb: + __runOriginal = false; + requestInvites.Clear(); + break; + } + + // Display received notification for remaining unhandled requests + for (int index = 0; index < requestInvites.Count; index++) + { + RequestInvite inviteRequest = requestInvites[index]; + ReceiveInviteRequest(inviteRequest); + } + } + + private static void AcceptInviteRequest(RequestInvite inviteRequest) + { + ApiConnection.SendWebSocketRequest(RequestType.RequestInviteAccept, new { id = inviteRequest.Id }); + CohtmlHud.Instance.ViewDropTextImmediate( + "(Mod) Auto Accept", + "Accepting invite", + $"Accepted request from {inviteRequest.Sender.Name}", + $"ACCEPTREQ+{inviteRequest.Sender.Id}", + false); + } + + private static void CannotAcceptInviteRequest(RequestInvite inviteRequest) + { + CohtmlHud.Instance.ViewDropTextImmediate( + "(Mod) Auto Accept", + "Cannot accept invite", + $"Received request from {inviteRequest.Sender.Name}", + $"CANNOTACCEPTREQ+{inviteRequest.Sender.Id}", + false); + } + + private static void ReceiveInvite(Invite invite) + { + CohtmlHud.Instance.ViewDropTextImmediate( + "(Mod) Auto Accept", + "Received invite", + $"Received invite from {invite.User.Name}", + $"RECEIVEDINV+{invite.User.Id}", + false); + } + + private static void ReceiveInviteRequest(RequestInvite inviteRequest) + { + CohtmlHud.Instance.ViewDropTextImmediate( + "(Mod) Auto Accept", + "Received invite request", + $"Received request from {inviteRequest.Sender.Name}", + $"RECEIVEDREQ+{inviteRequest.Sender.Id}", + false); + } + + private static void OnPostInvitePlayer() + { + ViewManager.Instance.NotifyUser("(Mod) Auto Accept", "Sent invite", 1f); + } + + private static void OnPostRequestInvite() + { + ViewManager.Instance.NotifyUser("(Mod) Auto Accept", "Requested invite", 1f); + } + + // Menu Patches + + private static void OnViewManagerStart() + { + ViewManager.Instance.cohtmlView.Listener.FinishLoad += _ => + { + ViewManager.Instance.cohtmlView.View._view.ExecuteScript(InjectJs); + }; + ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () => + { + var view = ViewManager.Instance.cohtmlView.View; + view.BindCall("NAKSetInviteStatus", new Action(OnJsSetInviteStatus)); + view.BindCall("NAKSetAutoAcceptCategory", new Action(OnJsSetAutoAcceptCategory)); + view.BindCall("NAKRequestInviteState", new Action(PushInviteStateToJs)); + }; + } + + private static void OnJsSetInviteStatus(string statusName) + { + if (!Enum.TryParse(statusName, out InviteStatus status)) return; + EntryInviteStatus.Value = status; + RebuildAutoAcceptUserIds(); + PushInviteStatusToJs(); // echo back so the menu is authoritative + } + + private static void OnJsSetAutoAcceptCategory(string categoryKey, bool add) + { + if (string.IsNullOrEmpty(categoryKey)) return; + if (add) _autoAcceptCategories.Add(categoryKey); + else _autoAcceptCategories.Remove(categoryKey); + SaveAutoAcceptCategories(); + RebuildAutoAcceptUserIds(); + PushAutoAcceptCategoriesToJs(); + } + + private static void PushInviteStateToJs() + { + PushInviteStatusToJs(); + PushAutoAcceptCategoriesToJs(); + } + + private static void PushInviteStatusToJs() + { + ViewManager.Instance.cohtmlView.View.TriggerEvent("NAKInviteStatusUpdate", EntryInviteStatus.Value.ToString()); + } + + private static void PushAutoAcceptCategoriesToJs() + { + ViewManager.Instance.cohtmlView.View.TriggerEvent("NAKAutoAcceptCategoriesUpdate", ToJsonArray(_autoAcceptCategories)); + } + + private static string ToJsonArray(IEnumerable values) + { + var sb = new System.Text.StringBuilder(); + sb.Append('['); + bool first = true; + foreach (string v in values) + { + if (!first) sb.Append(','); + first = false; + sb.Append('"').Append(v.Replace("\\", "\\\\").Replace("\"", "\\\"")).Append('"'); + } + sb.Append(']'); + return sb.ToString(); + } + + private const string InjectJs = @" +(function () { + if (window.__nakAutoAcceptInjected) return; + window.__nakAutoAcceptInjected = true; + + var nakInviteStatus = 'Ask'; + var nakAutoAcceptCats = new Set(); + + var STATUSES = [ + { key: 'Ask', label: 'Ask', tip: 'Show a prompt for each incoming invite.' }, + { key: 'AllFriends', label: 'All', tip: 'Auto-accept invites from any friend.' }, + { key: 'SelectCategories', label: 'Select', tip: 'Auto-accept friends in your starred categories.' }, + { key: 'DoNotDisturb', label: 'DND', tip: 'Silently ignore all incoming invites.' } + ]; + + function descFor(key) { + for (var i = 0; i < STATUSES.length; i++) + if (STATUSES[i].key === key) return STATUSES[i].tip; + return ''; + } + + function showDesc(key) { + var d = document.querySelector('#friends .nak-aa-desc'); + if (d) d.textContent = descFor(key || nakInviteStatus); + } + + function injectStyle() { + if (document.getElementById('nak-aa-style')) return; + var css = + '#friends .nak-aa-statusbar{display:flex;flex-direction:column;gap:6px;margin:8px 0 10px;padding-bottom:10px;border-bottom:1px solid rgba(255,255,255,.08);}' + + '#friends .nak-aa-statusbar .nak-aa-label{font-size:.74em;letter-spacing:.04em;text-transform:uppercase;opacity:.85;font-weight:600;}' + + '#friends .nak-aa-statusbar .nak-aa-options{display:flex;gap:4px;background:rgba(255,255,255,.05);padding:3px;border-radius:8px;}' + + '#friends .nak-aa-statusbar .nak-aa-opt{flex:1;text-align:center;padding:5px 4px;border-radius:6px;cursor:pointer;font-size:.85em;opacity:.7;}' + + '#friends .nak-aa-statusbar .nak-aa-opt:hover{opacity:1;}' + + '#friends .nak-aa-statusbar .nak-aa-opt.active{opacity:1;background:rgba(255,255,255,.14);font-weight:600;}' + + '#friends .nak-aa-statusbar .nak-aa-desc{font-size:.78em;line-height:1.3;opacity:.6;min-height:1.1em;}' + + '#friends .filter-option{position:relative;}' + + '#friends .filter-option .nak-aa-toggle{position:absolute;right:8px;top:50%;transform:translateY(-50%);cursor:pointer;line-height:1;opacity:0;pointer-events:none;}' + + '#friends.nak-mode-select .filter-option[data-nak-key]{padding-right:22px;}' + + '#friends.nak-mode-select .filter-option .nak-aa-toggle{opacity:.5;pointer-events:auto;}' + + '#friends.nak-mode-select .filter-option .nak-aa-toggle:hover{opacity:.95;}' + + '#friends.nak-mode-select .filter-option.nak-aa-eligible .nak-aa-toggle{opacity:1;}'; + var s = document.createElement('style'); + s.id = 'nak-aa-style'; + s.textContent = css; + document.head.appendChild(s); + } + + function setInviteStatus(key, tellCs) { + nakInviteStatus = key; + refreshStatusBar(); + if (tellCs && window.engine) engine.call('NAKSetInviteStatus', key); + } + + function refreshStatusBar() { + var opts = document.querySelectorAll('#friends .nak-aa-statusbar .nak-aa-opt'); + for (var i = 0; i < opts.length; i++) + opts[i].classList.toggle('active', opts[i].getAttribute('data-nak-status') === nakInviteStatus); + var f = document.getElementById('friends'); + if (f) f.classList.toggle('nak-mode-select', nakInviteStatus === 'SelectCategories'); + showDesc(null); + } + + function buildStatusBar() { + var filter = document.querySelector('#friends .list-filter'); + if (!filter || filter.querySelector('.nak-aa-statusbar')) return; + + var bar = document.createElement('div'); + bar.className = 'nak-aa-statusbar'; + + var label = document.createElement('div'); + label.className = 'nak-aa-label'; + label.textContent = 'Incoming invites'; + bar.appendChild(label); + + var opts = document.createElement('div'); + opts.className = 'nak-aa-options'; + STATUSES.forEach(function (st) { + var b = document.createElement('div'); + b.className = 'nak-aa-opt'; + b.textContent = st.label; + b.setAttribute('data-nak-status', st.key); + b.addEventListener('click', function () { setInviteStatus(st.key, true); }); + b.addEventListener('mouseenter', function () { showDesc(st.key); }); + b.addEventListener('mouseleave', function () { showDesc(null); }); + opts.appendChild(b); + }); + bar.appendChild(opts); + + var desc = document.createElement('div'); + desc.className = 'nak-aa-desc'; + bar.appendChild(desc); + + var h1 = filter.querySelector('h1'); + if (h1) filter.insertBefore(bar, h1.nextSibling); else filter.appendChild(bar); + refreshStatusBar(); + } + + function eligible(key) { return nakAutoAcceptCats.has(String(key)); } + + function paintCategory(el, key) { + var on = eligible(key); + el.classList.toggle('nak-aa-eligible', on); + var t = el.querySelector('.nak-aa-toggle'); + if (t) { + t.textContent = on ? '\u2605' : '\u2606'; + t.setAttribute('data-tooltip', on + ? 'Auto-accepting invites from this category' + : 'Click to auto-accept invites from this category'); + } + } + + function decorateCategory(el, key) { + if (!el) return; + key = String(key); + el.setAttribute('data-nak-key', key); + if (!el.querySelector('.nak-aa-toggle')) { + var t = document.createElement('span'); + t.className = 'nak-aa-toggle'; + t.addEventListener('click', function (e) { + e.stopPropagation(); + e.preventDefault(); + var want = !eligible(key); + if (want) nakAutoAcceptCats.add(key); else nakAutoAcceptCats.delete(key); + paintCategory(el, key); + if (window.engine) engine.call('NAKSetAutoAcceptCategory', key, want); + }); + el.appendChild(t); + } + paintCategory(el, key); + } + + function keyFromClass(cn) { + var parts = (cn || '').split(/\s+/); + for (var i = 0; i < parts.length; i++) + if (parts[i].indexOf('data-filter-') === 0) return parts[i].slice(12); + return null; + } + + // catches categories that were already rendered before we injected + function decorateExisting() { + var list = window.friendCategories || []; + var nonSystem = {}; + list.forEach(function (c) { if (!c.IsSystemCategory) nonSystem[String(c.CategoryKey)] = true; }); + var els = document.querySelectorAll('#friends .filter-option'); + for (var i = 0; i < els.length; i++) { + var key = keyFromClass(els[i].className); + if (key && nonSystem[key]) decorateCategory(els[i], key); + } + } + + function repaintAll() { + var els = document.querySelectorAll('#friends .filter-option[data-nak-key]'); + for (var i = 0; i < els.length; i++) + paintCategory(els[i], els[i].getAttribute('data-nak-key')); + } + + // wrap the game's builder so our toggle is re-added on every re-render + function wrapCreateRenderCategory() { + if (typeof window.CreateRenderCategory !== 'function' || window.CreateRenderCategory.__nakWrapped) return; + var orig = window.CreateRenderCategory; + var wrapped = function (categoryName, categoryInfo) { + var el = orig.apply(this, arguments); + try { + if (categoryName === 'friends' && categoryInfo && !categoryInfo.IsSystemCategory) + decorateCategory(el, categoryInfo.CategoryKey); + } catch (err) { console.error('[NAK] decorate failed', err); } + return el; + }; + wrapped.__nakWrapped = true; + window.CreateRenderCategory = wrapped; + } + + if (window.engine) { + engine.on('NAKInviteStatusUpdate', function (statusKey) { + setInviteStatus(String(statusKey), false); + }); + engine.on('NAKAutoAcceptCategoriesUpdate', function (json) { + nakAutoAcceptCats = new Set(); + try { + var arr = JSON.parse(json || '[]'); + for (var i = 0; i < arr.length; i++) nakAutoAcceptCats.add(String(arr[i])); + } catch (e) { console.error('[NAK] bad categories payload', e); } + repaintAll(); + refreshStatusBar(); + }); + } + + injectStyle(); + wrapCreateRenderCategory(); + buildStatusBar(); + decorateExisting(); + repaintAll(); + if (window.engine) engine.call('NAKRequestInviteState'); +})(); +"; +} \ No newline at end of file diff --git a/AutoAccept/Properties/AssemblyInfo.cs b/AutoAccept/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..20626b9 --- /dev/null +++ b/AutoAccept/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.AutoAccept.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.AutoAccept))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.AutoAccept))] + +[assembly: MelonInfo( + typeof(NAK.AutoAccept.AutoAcceptMod), + nameof(NAK.AutoAccept), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/AutoAccept" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.AutoAccept.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/AutoAccept/README.md b/AutoAccept/README.md new file mode 100644 index 0000000..1413ed1 --- /dev/null +++ b/AutoAccept/README.md @@ -0,0 +1,19 @@ +# Tinyboard + +Makes the keyboard small and smart. + +Few small tweaks to the keyboard: +- Shrinks the keyboard to a size that isn't fit for grandma. +- Adjusts keyboard placement logic to align with the menu that it spawns from. +- Enforces a title on the keyboard input if one is not found. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game + +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/AutoAccept/format.json b/AutoAccept/format.json new file mode 100644 index 0000000..3dda9a3 --- /dev/null +++ b/AutoAccept/format.json @@ -0,0 +1,23 @@ +{ + "_id": 264, + "name": "Tinyboard", + "modversion": "1.0.1", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Few small tweaks to the keyboard:\n- Shrinks the keyboard to a size that isn't fit for grandma.\n- Adjusts keyboard placement logic to align with the menu that it spawns from.\n- Enforces a title on the keyboard input if one is not found.", + "searchtags": [ + "keyboard", + "menu", + "ui", + "input" + ], + "requirements": [ + "None" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/Tinyboard.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/Tinyboard/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/ChatBoxHud/Main.cs b/ChatBoxHud/Main.cs index 107e8e6..05f7c25 100644 --- a/ChatBoxHud/Main.cs +++ b/ChatBoxHud/Main.cs @@ -264,7 +264,7 @@ public class ChatBoxHudMod : MelonMod if (EntryUsePlayerColors.Value) { PlayerColors pc = PlayerColorsManager.GetPlayerColors(playerId); - hex = "#" + ColorUtility.ToHtmlStringRGB(pc.PrimaryColor); + hex = "#" + ColorUtility.ToHtmlStringRGB(pc.EmissionColor); } else hex = Friends.FriendsWith(playerId) ? "#4FC3F7" : "#E0E0E0"; diff --git a/ChatBoxHud/Properties/AssemblyInfo.cs b/ChatBoxHud/Properties/AssemblyInfo.cs index a6cd27b..f7f1dd2 100644 --- a/ChatBoxHud/Properties/AssemblyInfo.cs +++ b/ChatBoxHud/Properties/AssemblyInfo.cs @@ -27,6 +27,6 @@ using System.Reflection; namespace NAK.ChatBoxHud.Properties; internal static class AssemblyInfoParams { - public const string Version = "1.0.0"; + public const string Version = "1.0.1"; public const string Author = "NotAKidoS"; } \ No newline at end of file diff --git a/ChatBoxHud/README.md b/ChatBoxHud/README.md index 126be0a..c4e33f5 100644 --- a/ChatBoxHud/README.md +++ b/ChatBoxHud/README.md @@ -4,11 +4,11 @@ Shows nearby ChatBox messages directly on your HUD so you can read them comforta --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/ChatBoxHud/format.json b/ChatBoxHud/format.json index cd46a8b..7d33490 100644 --- a/ChatBoxHud/format.json +++ b/ChatBoxHud/format.json @@ -1,7 +1,7 @@ { "_id": -1, "name": "ChatBoxHud", - "modversion": "1.0.0", + "modversion": "1.0.1", "gameversion": "2026r181", "loaderversion": "0.7.2", "modtype": "Mod", @@ -18,6 +18,6 @@ ], "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r49/ChatBoxHud.dll", "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ChatBoxHud/", - "changelog": "- Initial release", + "changelog": "- Changed username color to use emission player color", "embedcolor": "#f61963" } \ No newline at end of file diff --git a/CustomSpawnPoint/Main.cs b/CustomSpawnPoint/Main.cs index dbf3f6f..476970c 100644 --- a/CustomSpawnPoint/Main.cs +++ b/CustomSpawnPoint/Main.cs @@ -15,11 +15,24 @@ public class CustomSpawnPointMod : MelonMod SpawnPointManager.Init(); - HarmonyInstance.Patch( // listen for world details page request - typeof(ViewManager).GetMethod(nameof(ViewManager.RequestWorldDetailsPage)), - new HarmonyMethod(typeof(CustomSpawnPointMod).GetMethod(nameof(OnRequestWorldDetailsPage), + HarmonyInstance.Patch( + typeof(ViewManager).GetMethod(nameof(ViewManager.Start), + BindingFlags.NonPublic | BindingFlags.Instance), + postfix: new HarmonyMethod(typeof(CustomSpawnPointMod).GetMethod(nameof(OnViewManagerStart), BindingFlags.NonPublic | BindingFlags.Static)) ); + + HarmonyInstance.Patch( // listen for world details page request + typeof(ViewManager).GetMethod(nameof(ViewManager.RequestWorldDetailsPage), + BindingFlags.Public | BindingFlags.Instance), + postfix: new HarmonyMethod(typeof(CustomSpawnPointMod).GetMethod(nameof(OnRequestWorldDetailsPage), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + } + + private static void OnViewManagerStart() + { + SpawnPointManager.OnViewManagerStart(); } private static void OnRequestWorldDetailsPage(string worldId) diff --git a/CustomSpawnPoint/README.md b/CustomSpawnPoint/README.md index bb8230b..877fbba 100644 --- a/CustomSpawnPoint/README.md +++ b/CustomSpawnPoint/README.md @@ -4,11 +4,11 @@ Replaces the unused Images button in the World Details page with a button to set --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/CustomSpawnPoint/SpawnPointManager.cs b/CustomSpawnPoint/SpawnPointManager.cs index 78c81dd..563a277 100644 --- a/CustomSpawnPoint/SpawnPointManager.cs +++ b/CustomSpawnPoint/SpawnPointManager.cs @@ -31,39 +31,35 @@ internal static class SpawnPointManager internal static void Init() { - LoadSpawnpoints(); - CVRGameEventSystem.World.OnLoad.AddListener(OnWorldLoaded); - CVRGameEventSystem.World.OnUnload.AddListener(OnWorldUnloaded); - MelonLoader.MelonCoroutines.Start(WaitMainMenuUi()); - } + LoadSpawnpoints(); + CVRGameEventSystem.World.OnLoad.AddListener(OnWorldLoaded); + CVRGameEventSystem.World.OnUnload.AddListener(OnWorldUnloaded); + CVRGameEventSystem.Initialization.OnPlayerSetupStart.AddListener(OnPlayerSetupStart); + } - private static System.Collections.IEnumerator WaitMainMenuUi() + private static void OnPlayerSetupStart() { - while (ViewManager.Instance == null) - yield return null; - while (ViewManager.Instance.cohtmlView == null) - yield return null; - while (ViewManager.Instance.cohtmlView.Listener == null) - yield return null; + // create our custom spawn point object + GameObject customSpawnPointObject = new("[CustomSpawnPoint]"); + Object.DontDestroyOnLoad(customSpawnPointObject); - ViewManager.Instance.OnUiConfirm.AddListener(OnClearSpawnpointConfirm); - ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) => - { - ViewManager.Instance.cohtmlView.View._view.ExecuteScript(spawnpointJs); - }; - ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () => - { - // listen for setting the spawn point on our custom button - ViewManager.Instance.cohtmlView.View.BindCall("NAKCallSetSpawnpoint", SetSpawnPoint); - }; - - // create our custom spawn point object - GameObject customSpawnPointObject = new("[CustomSpawnPoint]"); - Object.DontDestroyOnLoad(customSpawnPointObject); - - // add to array so we can easily replace worlds spawn points - customSpawnPointsArray = new[] { customSpawnPointObject }; - } + // add to array so we can easily replace worlds spawn points + customSpawnPointsArray = new[] { customSpawnPointObject }; + } + + internal static void OnViewManagerStart() + { + ViewManager.Instance.OnUiConfirm.AddListener(OnClearSpawnpointConfirm); + ViewManager.Instance.cohtmlView.Listener.FinishLoad += (_) => + { + ViewManager.Instance.cohtmlView.View._view.ExecuteScript(spawnpointJs); + }; + ViewManager.Instance.cohtmlView.Listener.ReadyForBindings += () => + { + // listen for setting the spawn point on our custom button + ViewManager.Instance.cohtmlView.View.BindCall("NAKCallSetSpawnpoint", SetSpawnPoint); + }; + } #endregion Initialization diff --git a/DehumanizePlayers/DehumanizePlayers.csproj b/DehumanizePlayers/DehumanizePlayers.csproj new file mode 100644 index 0000000..78195e6 --- /dev/null +++ b/DehumanizePlayers/DehumanizePlayers.csproj @@ -0,0 +1,6 @@ + + + + ASTExtension + + diff --git a/DehumanizePlayers/HumanoidAvatarRebinder.cs b/DehumanizePlayers/HumanoidAvatarRebinder.cs new file mode 100644 index 0000000..93d4cf4 --- /dev/null +++ b/DehumanizePlayers/HumanoidAvatarRebinder.cs @@ -0,0 +1,109 @@ +using UnityEngine; + +namespace NAK.DehumanizePlayers; + +public static class HumanoidAvatarRebinder +{ + private static readonly HashSet s_BoneTransforms = new(); + private static readonly HashSet s_HumanBoneNames = new(); + private static readonly List<(Transform t, string original)> s_Renames = new(); + private static readonly List s_AllTransforms = new(); + + public static Animator RebindToParentHumanoidAnimator(GameObject avatarGameObject) + { + if (avatarGameObject == null) return null; + + var parent = avatarGameObject.transform.parent; + if (parent == null) return null; + + var innerAnimator = avatarGameObject.GetComponent(); + if (innerAnimator == null || innerAnimator.avatar == null || !innerAnimator.avatar.isHuman) + { + DehumanizePlayersMod.Logger.Error("[HumanoidAvatarRebinder] avatarGameObject must have an Animator with a humanoid Avatar."); + return null; + } + + s_BoneTransforms.Clear(); + s_HumanBoneNames.Clear(); + s_Renames.Clear(); + s_AllTransforms.Clear(); + + var humanDescription = innerAnimator.avatar.humanDescription; + var sourceAvatarName = innerAnimator.avatar.name; + + var outerAnimator = parent.GetComponent(); + if (outerAnimator) UnityEngine.Object.DestroyImmediate(outerAnimator); + + //if (outerAnimator == null) + outerAnimator = parent.gameObject.AddComponent(); + outerAnimator.enabled = false; + outerAnimator.applyRootMotion = false; + outerAnimator.cullingMode = AnimatorCullingMode.AlwaysAnimate; + outerAnimator.runtimeAnimatorController = null; + + for (int i = 0; i < (int)HumanBodyBones.LastBone; i++) + { + var bone = innerAnimator.GetBoneTransform((HumanBodyBones)i); + if (bone != null) s_BoneTransforms.Add(bone); + } + + // As we cannot rebind the inner animator, unassign now ...? + // Cannot undo renames without breaking things, assuming need to wait a frame. + innerAnimator.avatar = null; + // innerAnimator.Rebind(); + + if (humanDescription.skeleton != null && humanDescription.skeleton.Length > 0) + { + var expectedRootName = humanDescription.skeleton[0].name; + if (!string.IsNullOrEmpty(expectedRootName) && avatarGameObject.name != expectedRootName) + { + s_Renames.Add((avatarGameObject.transform, avatarGameObject.name)); + avatarGameObject.name = expectedRootName; + } + } + + foreach (var bone in humanDescription.human) + if (!string.IsNullOrEmpty(bone.boneName)) s_HumanBoneNames.Add(bone.boneName); + + parent.GetComponentsInChildren(true, s_AllTransforms); + + int renamed = 0; + foreach (var t in s_AllTransforms) + { + if (s_HumanBoneNames.Contains(t.name) && !s_BoneTransforms.Contains(t)) + { + s_Renames.Add((t, t.name)); + t.name = t.name + "__nb"; + renamed++; + } + } + + if (renamed > 0) + DehumanizePlayersMod.Logger.Msg($"[HumanoidAvatarRebinder] Renamed {renamed} non-bone transforms."); + + var rebuiltAvatar = AvatarBuilder.BuildHumanAvatar(parent.gameObject, humanDescription); + if (!rebuiltAvatar.isValid) + { + DehumanizePlayersMod.Logger.Error("[HumanoidAvatarRebinder] Rebuilt Avatar is invalid."); + RevertRenames(); + return null; + } + rebuiltAvatar.name = sourceAvatarName + "_Rebound"; + outerAnimator.avatar = rebuiltAvatar; + outerAnimator.Rebind(); + + // RevertRenames(); + + return outerAnimator; + } + + private static void RevertRenames() + { + for (int i = s_Renames.Count - 1; i >= 0; i--) + { + var (t, original) = s_Renames[i]; + if (t != null) t.name = original; + } + s_Renames.Clear(); + } +} \ No newline at end of file diff --git a/DehumanizePlayers/Main.cs b/DehumanizePlayers/Main.cs new file mode 100644 index 0000000..eb03d0b --- /dev/null +++ b/DehumanizePlayers/Main.cs @@ -0,0 +1,37 @@ +using System.Reflection; +using ABI_RC.Core.Player; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace NAK.DehumanizePlayers; + +public class DehumanizePlayersMod : MelonMod +{ + internal static MelonLogger.Instance Logger; + + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(DehumanizePlayers)); + + private static readonly MelonPreferences_Entry EntryEnabled = + Category.CreateEntry("enabled", true, + "Dehumanize Players", description: "When enabled creates a dummy animator above the avatar root which handles muscle application."); + + public override void OnInitializeMelon() + { + Logger = LoggerInstance; + HarmonyInstance.Patch( + typeof(NetIKController).GetMethod(nameof(NetIKController.SetupAvatar), + BindingFlags.Public | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(DehumanizePlayersMod).GetMethod(nameof(OnPreNetIKControllerSetupAvatar), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + } + + // ReSharper disable once RedundantAssignment + private static void OnPreNetIKControllerSetupAvatar(GameObject remoteAvatar, ref Animator remoteAnimator) + { + if (!EntryEnabled.Value) return; + remoteAnimator = HumanoidAvatarRebinder.RebindToParentHumanoidAnimator(remoteAvatar); + } +} \ No newline at end of file diff --git a/DehumanizePlayers/Properties/AssemblyInfo.cs b/DehumanizePlayers/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..f97e7fc --- /dev/null +++ b/DehumanizePlayers/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.DehumanizePlayers.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.DehumanizePlayers))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.DehumanizePlayers))] + +[assembly: MelonInfo( + typeof(NAK.DehumanizePlayers.DehumanizePlayersMod), + nameof(NAK.DehumanizePlayers), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/DehumanizePlayers" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.DehumanizePlayers.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/DehumanizePlayers/README.md b/DehumanizePlayers/README.md new file mode 100644 index 0000000..cde5320 --- /dev/null +++ b/DehumanizePlayers/README.md @@ -0,0 +1,33 @@ +# DehumanizePlayers + +Humanoid animators are needlessly more expensive than generic ones due to scheduling twist resolving for each layer, even when empty or unnecessary. + +You can see some profiler data gathered by a VRChat community member here: +https://docs.google.com/document/d/1SpG7O30O0Cb5tQCEgRro8BixO0lRkrlV2o9Cbq-rzJU/edit?tab=t.0 + +This was my attempt at addressing the issue when it was first linked to me. It works, albeit really jank. Remote avatars do not need to be humanoid as muscle data is streamed in over the network (unless playing an emote). + +VRChat has recently addressed this issue as well, but with an engine modification to skip this when IK Pass is disabled on the evaluated layer, which we are unable to do via mod or native. I have no way to test if the two fixes are comparable, but their fix likely applies to all animators, unlike this fix which only applies to remote player avatars. + +Surprisingly, Unity lets you nest animators. This mod creates a dummy disabled animator on the parent object of the avatar and directs the netikcontroller to apply muscles through that (which is very similar to how Basis drives muscles). The avatars original animator is then **dehumanized** to avoid the humanoid layer cost. + +This setup also would allow CVR to utilize Playable Animation Jobs on existing avatars to drive muscles, which makes netik cost free when the avatar is occlusion culled: +https://bsky.app/profile/nak.koneko.cat/post/3mlgptv7ttu2o + +(playable netik was dropped native due to breaking existing animator setups) + +Alternatively, this problem can also be addressed by driving the transforms of remote avatars directly, like Zettai's FastNetIK mod: +https://github.com/ZettaiVR/CVR-Mods/tree/main/FastNetIK + +The two approaches to addressing this low-hanging perf-issue are likely to be considered and tested after the GS2 update. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game + +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/DehumanizePlayers/format.json b/DehumanizePlayers/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/DehumanizePlayers/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/DesktopInteractions/Main.cs b/DesktopInteractions/Main.cs index a92b976..ac1b7c7 100644 --- a/DesktopInteractions/Main.cs +++ b/DesktopInteractions/Main.cs @@ -4,6 +4,7 @@ using ABI_RC.Core.Savior; using ABI_RC.Systems.ChatBox; using ABI_RC.Systems.GameEventSystem; using ABI_RC.Systems.IK; +using ABI_RC.Systems.Movement; using ABI.CCK.Components; using HarmonyLib; using MelonLoader; @@ -109,7 +110,7 @@ public class DesktopInteractionsMod : MelonMod if (MetaPort.Instance.isUsingVr) return; bool isTyping = EntryTypingGesture.Value && ChatBoxManager.Instance.LocalPlayerBubble.IsTypingIndicatorActive; - bool isZooming = EntryZoomGesture.Value && CVR_DesktopCameraController.GetCurrentZoomModifier() > 0.25f; + bool isZooming = EntryZoomGesture.Value && BetterBetterCharacterController.Instance.CharacterLook.GetCurrentZoomModifier() > 0.25f; _leftArmController.SetInfluence(10, isTyping, _calibratedEarIKTargetTransform); _leftArmController.SetInfluence(5, isZooming, _calibratedLeftEyeIKTargetTransform); diff --git a/DesktopInteractions/README.md b/DesktopInteractions/README.md index 2ba4272..776cbcc 100644 --- a/DesktopInteractions/README.md +++ b/DesktopInteractions/README.md @@ -4,11 +4,12 @@ Adds IK-driven hand gestures to your avatar in Desktop: earpiece grab (GMOD-styl --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. +~~~~ \ No newline at end of file diff --git a/DisableInputDuringFingerTracking/DisableInputDuringFingerTracking.csproj b/DisableInputDuringFingerTracking/DisableInputDuringFingerTracking.csproj new file mode 100644 index 0000000..78195e6 --- /dev/null +++ b/DisableInputDuringFingerTracking/DisableInputDuringFingerTracking.csproj @@ -0,0 +1,6 @@ + + + + ASTExtension + + diff --git a/DisableInputDuringFingerTracking/Main.cs b/DisableInputDuringFingerTracking/Main.cs new file mode 100644 index 0000000..a78610e --- /dev/null +++ b/DisableInputDuringFingerTracking/Main.cs @@ -0,0 +1,203 @@ +using System.Reflection; +using ABI_RC.Core.Extensions; +using ABI_RC.Systems.IK; +using ABI_RC.Systems.IK.SubSystems; +using HarmonyLib; +using MelonLoader; +using UnityEngine; + +namespace NAK.DisableInputDuringFingerTracking; + +public class DisableInputDuringFingerTrackingMod : MelonMod +{ + private static readonly MelonPreferences_Category Category = + MelonPreferences.CreateCategory(nameof(DisableInputDuringFingerTracking)); + + private static readonly MelonPreferences_Entry EntryProbableFixes = + Category.CreateEntry("probable_fixes", Fixes.Fix1, + "Fixes", description: "remove me from ur melonpref one day"); + + private enum Fixes + { + Fix1, + Fix2, + Fix3 + } + + public override void OnInitializeMelon() + { + HarmonyInstance.Patch( + typeof(BodySystem).GetMethod(nameof(BodySystem.CalibrateWithSavedData), + BindingFlags.Public | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(DisableInputDuringFingerTrackingMod).GetMethod(nameof(CalibrateWithSavedData), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + HarmonyInstance.Patch( + typeof(BodySystem).GetMethod(nameof(BodySystem.SaveCalibrationData), + BindingFlags.Public | BindingFlags.Instance), + prefix: new HarmonyMethod(typeof(DisableInputDuringFingerTrackingMod).GetMethod(nameof(SaveCalibrationData), + BindingFlags.NonPublic | BindingFlags.Static)) + ); + } + + private static void CalibrateWithSavedData(BodySystem.CalibrationData data, BodySystem __instance, ref bool __runOriginal) + { + __runOriginal = false; + + Vector3 scale = IKSystem.Instance._vrPlaySpace.localScale; + Vector3 position = data.AvatarPosition; + position.x *= scale.x; + position.y *= scale.y; + position.z *= scale.z; + + // IKSystem.vrik.transform.SetLocalPositionAndRotation(position, data.AvatarRotation); + // need to set relative to IKSystem.Instance._vrPlaySpace + + switch (EntryProbableFixes.Value) + { + case Fixes.Fix1: + IKSystem.vrik.transform.SetPositionAndRotation( + IKSystem.Instance._vrPlaySpace.TransformPointNoScale(position), + IKSystem.Instance._vrPlaySpace.rotation * data.AvatarRotation); + break; + case Fixes.Fix2: + IKSystem.vrik.transform.SetPositionAndRotation( + IKSystem.Instance._vrPlaySpace.TransformPointNoScale(position), + data.AvatarRotation); + break; + // Position relative to playspace position only, ignore playspace rotation. + case Fixes.Fix3: + IKSystem.vrik.transform.SetPositionAndRotation( + IKSystem.Instance._vrPlaySpace.position + position, + data.AvatarRotation); + break; + } + + List validTrackers = IKSystem.Instance.TrackingSystem.AllTrackingPoints.FindAll(m => + m.isActive && + m.isValid && + m.suggestedRole != TrackingPoint.TrackingRole.Invalid + ); + + foreach (BodySystem.CalibrationPoint calibrationPoint in data.CalibrationPoints) + { + foreach (var tracker in validTrackers) + { + if (tracker.identifier == calibrationPoint.TrackerSerial) + { + tracker.assignedRole = calibrationPoint.TrackingRole; + tracker.position = calibrationPoint.LocalPosition; + tracker.rotation = calibrationPoint.LocalRotation; + tracker.referenceTransform.localPosition = calibrationPoint.LocalPosition; + tracker.referenceTransform.localRotation = calibrationPoint.LocalRotation; + } + } + } + + __instance.SetupOffsets(validTrackers); + +// #if UNITY_EDITOR +// UnityEditor.EditorApplication.isPaused = true; +// #endif + + __instance.Calibrate(false); + } + + private static void SaveCalibrationData(string avatarId, BodySystem __instance, ref bool __runOriginal) + { + __runOriginal = false; + + // needs to be relative to vr playspace + Vector3 position = IKSystem.Instance._vrPlaySpace.InverseTransformPoint(IKSystem.vrik.transform.position); + Quaternion rotation = Quaternion.Inverse(IKSystem.Instance._vrPlaySpace.rotation) * IKSystem.vrik.transform.rotation; + + switch (EntryProbableFixes.Value) + { + // Load: + // TransformPointNoScale(position) + // playspace.rotation * avatarRotation + case Fixes.Fix1: + { + position = IKSystem.Instance._vrPlaySpace.InverseTransformPointNoScale(IKSystem.vrik.transform.position); + + Vector3 scale = IKSystem.Instance._vrPlaySpace.localScale; + position.x /= scale.x; + position.y /= scale.y; + position.z /= scale.z; + + rotation = Quaternion.Inverse(IKSystem.Instance._vrPlaySpace.rotation) * + IKSystem.vrik.transform.rotation; + break; + } + + // Load: + // TransformPointNoScale(position) + // avatarRotation + case Fixes.Fix2: + { + position = IKSystem.Instance._vrPlaySpace.InverseTransformPointNoScale(IKSystem.vrik.transform.position); + + Vector3 scale = IKSystem.Instance._vrPlaySpace.localScale; + position.x /= scale.x; + position.y /= scale.y; + position.z /= scale.z; + + rotation = IKSystem.vrik.transform.rotation; + break; + } + + // Load: + // playspace.position + position + // avatarRotation + case Fixes.Fix3: + { + position = IKSystem.vrik.transform.position - + IKSystem.Instance._vrPlaySpace.position; + + Vector3 scale = IKSystem.Instance._vrPlaySpace.localScale; + position.x /= scale.x; + position.y /= scale.y; + position.z /= scale.z; + + rotation = IKSystem.vrik.transform.rotation; + break; + } + } + + BodySystem.UniversalData = new BodySystem.CalibrationData( + position, + rotation, + avatarId + ); + + List validTrackers = IKSystem.Instance.TrackingSystem.AllTrackingPoints.FindAll(m => + m.isActive && + m.isValid && + m.suggestedRole != TrackingPoint.TrackingRole.Invalid && + m.assignedRole != TrackingPoint.TrackingRole.Invalid && + m.assignedRole != TrackingPoint.TrackingRole.Generic + ); + + BodySystem.UniversalData.CalibrationPoints.Clear(); + + foreach (var tracker in validTrackers) + { + BodySystem.CalibrationPoint point = new BodySystem.CalibrationPoint( + tracker.position, + tracker.rotation, + tracker.assignedRole, + tracker.identifier + ); + + BodySystem.UniversalData.CalibrationPoints.Add(point); + } + + // save to universal + if (BodySystem.enableUniversalCalibration) BodySystem.SavedAvatars[BodySystem.UniversalCalibrationKey] = BodySystem.UniversalData; + // save to current avatar + if (BodySystem.enableSaveCalibration) BodySystem.SavedAvatars[avatarId] = BodySystem.UniversalData; + + // save to file + if (BodySystem.enableUniversalCalibration || BodySystem.enableSaveCalibration) __instance.SaveSavedCalibrations(); + } +} \ No newline at end of file diff --git a/DisableInputDuringFingerTracking/Properties/AssemblyInfo.cs b/DisableInputDuringFingerTracking/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..e08b476 --- /dev/null +++ b/DisableInputDuringFingerTracking/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +using MelonLoader; +using NAK.DisableInputDuringFingerTracking.Properties; +using System.Reflection; + +[assembly: AssemblyVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)] +[assembly: AssemblyTitle(nameof(NAK.DisableInputDuringFingerTracking))] +[assembly: AssemblyCompany(AssemblyInfoParams.Author)] +[assembly: AssemblyProduct(nameof(NAK.DisableInputDuringFingerTracking))] + +[assembly: MelonInfo( + typeof(NAK.DisableInputDuringFingerTracking.DisableInputDuringFingerTrackingMod), + nameof(NAK.DisableInputDuringFingerTracking), + AssemblyInfoParams.Version, + AssemblyInfoParams.Author, + downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/DisableInputDuringFingerTracking" +)] + +[assembly: MelonGame("ChilloutVR", "ChilloutVR")] +[assembly: MelonPlatform(MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)] +[assembly: MelonPlatformDomain(MelonPlatformDomainAttribute.CompatibleDomains.MONO)] +[assembly: MelonColor(255, 246, 25, 99)] // red-pink +[assembly: MelonAuthorColor(255, 158, 21, 32)] // red +[assembly: HarmonyDontPatchAll] + +namespace NAK.DisableInputDuringFingerTracking.Properties; +internal static class AssemblyInfoParams +{ + public const string Version = "1.0.0"; + public const string Author = "NotAKidoS"; +} \ No newline at end of file diff --git a/DisableInputDuringFingerTracking/README.md b/DisableInputDuringFingerTracking/README.md new file mode 100644 index 0000000..5ed44c4 --- /dev/null +++ b/DisableInputDuringFingerTracking/README.md @@ -0,0 +1,54 @@ +# ASTExtension + +Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool): +- VR Gesture to scale +- Persistent height +- Copy height from others + +Best used with Avatar Scale Tool, but will attempt to work with found scaling setups. +Requires already having Avatar Scaling on the avatar. This is **not** Universal Scaling. + +## Supported Setups + +ASTExtension will attempt to work with the following setups: + +**Parameter Names:** +- AvatarScale +- Scale +- Scaler +- Scale/Scale +- Height +- LoliModifier +- AvatarSize +- Size +- SizeScale +- Scaling + +These parameter names are not case sensitive and have been gathered from polling the community for common parameter names. + +Assuming the parameter is a float, ASTExtension will attempt to use it as the height parameter. Will automatically calibrate to the height range of the found parameter, assuming the scaling animation is in a blend tree / state using motion time & is linear. The scaling animation state **must be active** at time of avatar load. + +The max value ASTExtension will drive the parameter to is 100. As the mod is having to guess the max height, it may not be accurate if the max height is not capped at a multiple of 10. + +Examples: +- `AvatarScale` - 0 to 1 (slider) + - This is the default setup for Avatar Scale Tool and will work perfectly. +- `Scale` - 0 to 100 (input single) + - This will also work perfectly as the max height is a multiple of 10. +- `Height` - 0 to 2 (input single) + - This will not work properly. The max value to drive the parameter to is not a multiple of 10, and as such ASTExtension will believe the parameter range is 0 to 1. +- `BurntToast` - 0 to 10 (input single) + - This will not work properly. The parameter name is not recognized by ASTExtension. + +If your setup is theoretically supported but not working, it is likely the scaling animation is not linear or has loop enabled if using Motion Time, making the first and last frame identical height. In this case, you will need to fix your animation clip curves / blend tree to be linear &|| not loop, or use Avatar Scale Tool to generate a new scaling animation. + +--- + +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game + +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. + +> Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. + +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/DisableInputDuringFingerTracking/format.json b/DisableInputDuringFingerTracking/format.json new file mode 100644 index 0000000..390aeac --- /dev/null +++ b/DisableInputDuringFingerTracking/format.json @@ -0,0 +1,24 @@ +{ + "_id": 223, + "name": "ASTExtension", + "modversion": "1.0.5", + "gameversion": "2025r181", + "loaderversion": "0.7.2", + "modtype": "Mod", + "author": "NotAKidoS", + "description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Persistent height\n- Copy height from others\n\nBest used with Avatar Scale Tool, but will attempt to work with found scaling setups.\nRequires already having Avatar Scaling on the avatar. This is **not** Universal Scaling.", + "searchtags": [ + "tool", + "scaling", + "height", + "extension", + "avatar" + ], + "requirements": [ + "BTKUILib" + ], + "downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r48/ASTExtension.dll", + "sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/", + "changelog": "- Rebuilt for CVR 2025r181", + "embedcolor": "#f61963" +} \ No newline at end of file diff --git a/DoubleTapJumpToExitSeat/DoubleTapJumpToExitSeat.csproj b/DoubleTapJumpToExitSeat/DoubleTapJumpToExitSeat.csproj index 5a8badc..e94f9dc 100644 --- a/DoubleTapJumpToExitSeat/DoubleTapJumpToExitSeat.csproj +++ b/DoubleTapJumpToExitSeat/DoubleTapJumpToExitSeat.csproj @@ -1,6 +1,2 @@ - - - YouAreMineNow - - + diff --git a/DoubleTapJumpToExitSeat/README.md b/DoubleTapJumpToExitSeat/README.md index c154674..759e5aa 100644 --- a/DoubleTapJumpToExitSeat/README.md +++ b/DoubleTapJumpToExitSeat/README.md @@ -4,11 +4,11 @@ Replaces seat exit controls with a double-tap of the jump button, avoiding accid --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/NAK_CVR_Mods.sln b/NAK_CVR_Mods.sln deleted file mode 100644 index 1e104ac..0000000 --- a/NAK_CVR_Mods.sln +++ /dev/null @@ -1,483 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 17 -VisualStudioVersion = 17.2.32630.192 -MinimumVisualStudioVersion = 10.0.40219.1 -EndProject -EndProject -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PathCamDisabler", "PathCamDisabler\PathCamDisabler.csproj", "{98169FD2-5CEB-46D1-A320-D7E06F82C9E0}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PortableCameraAdditions", "PortableCameraAdditions\PortableCameraAdditions.csproj", "{C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PropUndoButton", "PropUndoButton\PropUndoButton.csproj", "{FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ThirdPerson", "ThirdPerson\ThirdPerson.csproj", "{675CEC0E-3E8A-4970-98EA-9B79277A7252}" -EndProject -EndProject -EndProject -EndProject -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RelativeSyncJitterFix", "RelativeSyncJitterFix\RelativeSyncJitterFix.csproj", "{B48C8F19-9451-4EE2-999F-82C0033CDE2C}" -EndProject -EndProject -EndProject -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScrollFlight", "ScrollFlight\ScrollFlight.csproj", "{1B5D7DCB-01A4-4988-8B25-211948AEED76}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PropLoadingHexagon", "PropLoadingHexagon\PropLoadingHexagon.csproj", "{642A2BC7-C027-4F8F-969C-EF0F867936FD}" -EndProject -EndProject -EndProject -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASTExtension", "ASTExtension\ASTExtension.csproj", "{6580AA87-6A95-438E-A5D3-70E583CCD77B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AvatarQueueSystemTweaks", "AvatarQueueSystemTweaks\AvatarQueueSystemTweaks.csproj", "{D178E422-283B-4FB3-89A6-AA4FB9F87E2F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CustomSpawnPoint", "CustomSpawnPoint\CustomSpawnPoint.csproj", "{51CA34CA-7684-4819-AC9E-89DFAD63E9AB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Stickers", "Stickers\Stickers.csproj", "{E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}" -EndProject -EndProject -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SmootherRay", "SmootherRay\SmootherRay.csproj", "{99F9D60D-9A2D-4DBE-AA52-13D8A0838696}" -EndProject -EndProject -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShareBubbles", "ShareBubbles\ShareBubbles.csproj", "{ADD6205B-67A4-4BA8-8BED-DF7D0E857A6A}" -EndProject -EndProject -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RCCVirtualSteeringWheel", "RCCVirtualSteeringWheel\RCCVirtualSteeringWheel.csproj", "{4A378F81-3805-41E8-9565-A8A89A8C00D6}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YouAreMyPropNowWeAreHavingSoftTacosLater", "YouAreMyPropNowWeAreHavingSoftTacosLater\YouAreMyPropNowWeAreHavingSoftTacosLater.csproj", "{8DA821CC-F911-4FCB-8C29-5EF3D76A5F76}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DoubleTapJumpToExitSeat", "DoubleTapJumpToExitSeat\DoubleTapJumpToExitSeat.csproj", "{36BF2B8B-F444-4886-AA4C-0EDF7540F1CE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuckToes", "FuckToes\FuckToes.csproj", "{751E4140-2F4D-4550-A4A9-65ABA9F7893A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LuaNetworkVariables", ".Experimental\LuaNetworkVariables\LuaNetworkVariables.csproj", "{6E7857D9-07AC-419F-B111-0DB0348D1C92}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TouchySquishy", ".Blackbox\TouchySquishy\TouchySquishy.csproj", "{FF4BF0E7-698D-49A0-96E9-0E2646FEAFFA}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConfigureCalibrationPose", "ConfigureCalibrationPose\ConfigureCalibrationPose.csproj", "{31667A36-D069-4708-9DCA-E3446009941B}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperAwesomeMod", ".Deprecated\SuperAwesomeMod\SuperAwesomeMod.csproj", "{11417BE7-7C4F-40D9-9FCB-467C7B3DCF66}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatBubbles", "ChatBubbles\ChatBubbles.csproj", "{6981A299-1743-4342-9F20-B8FC0263C54D}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InDepthLogging", ".Blackbox\InDepthLogging\InDepthLogging.csproj", "{544C21EF-51EF-4947-BBED-26A6794A71D7}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuckCameras", "FuckCameras\FuckCameras.csproj", "{D2B53F5A-9D6A-4402-B7FD-83BB1503D395}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuckCohtml2", "FuckCohtml2\FuckCohtml2.csproj", "{F1CCF5D2-EA11-4FE8-A5E2-A92655245893}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MisatyanEffector", "MisatyanEffector\MisatyanEffector.csproj", "{0EA59927-C46A-43DE-9E16-ED64EC1F4FB5}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DummyMenu", "DummyMenu\DummyMenu.csproj", "{DDCEE1C8-80EE-4DFF-84F2-6CE67D02AC22}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tinyboard", "Tinyboard\Tinyboard.csproj", "{3678F633-47DD-443B-8A6B-0CF33F45097F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FuckOffUICamera", "FuckOffUICamera\FuckOffUICamera.csproj", "{FAF20A58-1CA6-4543-A8FB-70085F31EFDF}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IFUCKINGHATECAMERAS", "IFUCKINGHATECAMERAS\IFUCKINGHATECAMERAS.csproj", "{2878A29C-E40F-4A1D-A0A3-678742D3814F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ApiSwitcher", ".Blackbox\ApiSwitcher\ApiSwitcher.csproj", "{BBDFF009-CD61-4345-AE16-01B18B5F8073}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Blackbox", "Blackbox", "{FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BufferParticleFixer", "BufferParticleFixer\BufferParticleFixer.csproj", "{46E47494-A96A-4138-BA3E-3A9A012C518A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ShowPlayerInSelfMirror", "ShowPlayerInSelfMirror\ShowPlayerInSelfMirror.csproj", "{33435863-4366-438B-9524-354D61E06806}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatBoxTweaks", "ChatBoxTweaks\ChatBoxTweaks.csproj", "{661119FB-B83B-4C48-8810-48293C6D7661}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlToUnlockEyes", "ControlToUnlockEyes\ControlToUnlockEyes.csproj", "{42C051F5-8DF6-4335-83F9-43A732595C05}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AccountSwitcher", ".Blackbox\AccountSwitcher\AccountSwitcher.csproj", "{CB20A400-51AC-456E-B261-3F6804EA6314}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RConHelper", ".Blackbox\RConHelper\RConHelper.csproj", "{E3950FB3-C4BD-4320-89F9-331C93781FBB}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ByeByePerformanceThankYouAMD", "ByeByePerformanceThankYouAMD\ByeByePerformanceThankYouAMD.csproj", "{B9B67099-777A-4686-AE01-455B101B3B36}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CVRGizmos", ".Deprecated\CVRGizmos\CVRGizmos.csproj", "{77FF7FA8-EBC2-4400-B7FF-3A5F7DBFAEAE}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CVRPersonalMirror", ".Blackbox\CVRPersonalMirror\CVRPersonalMirror.csproj", "{A19BF0EC-70C3-49D0-B278-02807669F240}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlayableNetIk", ".Blackbox\PlayableNetIk\PlayableNetIk.csproj", "{7CE6B276-A25C-4B7B-B99D-AD52C6B48E5B}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Experimental", "Experimental", "{B8FAD767-CB47-4112-8AFC-8620A51B946A}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlapPlapForAll", ".Experimental\PlapPlapForAll\PlapPlapForAll.csproj", "{1DE6CF9F-996E-459B-9129-D76245001F5F}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PlapPlapForAll", "PlapPlapForAll\PlapPlapForAll.csproj", "{B467F55B-55C4-44E7-83EF-E6ABC9225A90}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OriginShift", ".Experimental\OriginShift\OriginShift.csproj", "{CE2F1DF8-347D-4AAF-870C-8F2A97FDC308}" -EndProject -EndProject -EndProject -EndProject -EndProject -EndProject -EndProject -EndProject -EndProject -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CF9BC79E-4FB6-429A-8C19-DF31F040BD4A}.Release|Any CPU.Build.0 = Release|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Release|Any CPU.ActiveCfg = Release|Any CPU - {79B2A7C4-348D-4A8E-94D1-BA22FDD5FEED}.Release|Any CPU.Build.0 = Release|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Debug|Any CPU.Build.0 = Debug|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Release|Any CPU.ActiveCfg = Release|Any CPU - {45A65AEB-4BFC-4E47-B181-BBB43BD81283}.Release|Any CPU.Build.0 = Release|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {98169FD2-5CEB-46D1-A320-D7E06F82C9E0}.Release|Any CPU.Build.0 = Release|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4DAFE9D-C79B-4417-9B7D-B7327999DA4C}.Release|Any CPU.Build.0 = Release|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FBFDB717-F81E-4C06-ACF9-A0F3FFDCDE00}.Release|Any CPU.Build.0 = Release|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Debug|Any CPU.Build.0 = Debug|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Release|Any CPU.ActiveCfg = Release|Any CPU - {675CEC0E-3E8A-4970-98EA-9B79277A7252}.Release|Any CPU.Build.0 = Release|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EE552804-30B1-49CF-BBDE-3B312895AFF7}.Release|Any CPU.Build.0 = Release|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E1DD746-33A1-4179-AE70-8FB83AC40ABC}.Release|Any CPU.Build.0 = Release|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F94DDB73-9041-4F5C-AD43-6960701E8417}.Release|Any CPU.Build.0 = Release|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AC4857DD-F6D9-436D-A3EE-D148A518E642}.Release|Any CPU.Build.0 = Release|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {69AF3C10-1BB1-4746-B697-B5A81D78C8D9}.Release|Any CPU.Build.0 = Release|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9FA83514-13F8-412C-9790-C2B750E0E7E7}.Release|Any CPU.Build.0 = Release|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B48C8F19-9451-4EE2-999F-82C0033CDE2C}.Release|Any CPU.Build.0 = Release|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6B4396C7-B451-4FFD-87B6-3ED8377AC308}.Release|Any CPU.Build.0 = Release|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {24A069F4-4D69-4ABD-AA16-77765469245B}.Release|Any CPU.Build.0 = Release|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {05C427DD-1261-4AAD-B316-A551FC126F2C}.Release|Any CPU.Build.0 = Release|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C6794B18-E785-4F91-A517-3A2A8006E008}.Release|Any CPU.Build.0 = Release|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F381F604-9C16-4870-AD49-4BD7CA3F36DC}.Release|Any CPU.Build.0 = Release|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1B5D7DCB-01A4-4988-8B25-211948AEED76}.Release|Any CPU.Build.0 = Release|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BE9629C2-8461-481C-B267-1B8A1805DCD7}.Release|Any CPU.Build.0 = Release|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {642A2BC7-C027-4F8F-969C-EF0F867936FD}.Release|Any CPU.Build.0 = Release|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D11214B0-94FE-4008-8D1B-3DC8614466B3}.Release|Any CPU.Build.0 = Release|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2CC1F7C6-A953-4008-8C10-C7592EB401E8}.Release|Any CPU.Build.0 = Release|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {39915C4C-B555-4CB9-890F-26DE1388BC2E}.Release|Any CPU.Build.0 = Release|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7C675E64-0A2D-4B34-B6D1-5D6AA369A520}.Release|Any CPU.Build.0 = Release|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6580AA87-6A95-438E-A5D3-70E583CCD77B}.Release|Any CPU.Build.0 = Release|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D178E422-283B-4FB3-89A6-AA4FB9F87E2F}.Release|Any CPU.Build.0 = Release|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {51CA34CA-7684-4819-AC9E-89DFAD63E9AB}.Release|Any CPU.Build.0 = Release|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FE6BA6EC-2C11-49E1-A2FB-13F2A1C9E7F9}.Release|Any CPU.Build.0 = Release|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5F54B3E-A676-4DD5-A6DB-73AFA54BEC5E}.Release|Any CPU.Build.0 = Release|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3C992D0C-9729-438E-800C-496B7EFFFB25}.Release|Any CPU.Build.0 = Release|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E285BCC9-D953-4066-8FA2-97EA28EB348E}.Release|Any CPU.Build.0 = Release|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A38E687F-8B6B-499E-ABC9-BD95C53DD391}.Release|Any CPU.Build.0 = Release|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Debug|Any CPU.Build.0 = Debug|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Release|Any CPU.ActiveCfg = Release|Any CPU - {99F9D60D-9A2D-4DBE-AA52-13D8A0838696}.Release|Any CPU.Build.0 = Release|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A3D97D1A-3099-49C5-85AD-D8C79CC5FDE3}.Release|Any CPU.Build.0 = Release|Any CPU - {0640B2BF-1EF5-4FFE-A144-0368748FC48B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0640B2BF-1EF5-4FFE-A144-0368748FC48B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0640B2BF-1EF5-4FFE-A144-0368748FC48B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0640B2BF-1EF5-4FFE-A144-0368748FC48B}.Release|Any CPU.Build.0 = Release|Any CPU - {FC91FFFE-1E0A-4F59-8802-BFF99152AD07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FC91FFFE-1E0A-4F59-8802-BFF99152AD07}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FC91FFFE-1E0A-4F59-8802-BFF99152AD07}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FC91FFFE-1E0A-4F59-8802-BFF99152AD07}.Release|Any CPU.Build.0 = Release|Any CPU - {ADD6205B-67A4-4BA8-8BED-DF7D0E857A6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ADD6205B-67A4-4BA8-8BED-DF7D0E857A6A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ADD6205B-67A4-4BA8-8BED-DF7D0E857A6A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ADD6205B-67A4-4BA8-8BED-DF7D0E857A6A}.Release|Any CPU.Build.0 = Release|Any CPU - {6E315182-CC9F-4F62-8385-5E26EFA3B98A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E315182-CC9F-4F62-8385-5E26EFA3B98A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E315182-CC9F-4F62-8385-5E26EFA3B98A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E315182-CC9F-4F62-8385-5E26EFA3B98A}.Release|Any CPU.Build.0 = Release|Any CPU - {09238300-4583-45C6-A997-025CBDC44C24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {09238300-4583-45C6-A997-025CBDC44C24}.Debug|Any CPU.Build.0 = Debug|Any CPU - {09238300-4583-45C6-A997-025CBDC44C24}.Release|Any CPU.ActiveCfg = Release|Any CPU - {09238300-4583-45C6-A997-025CBDC44C24}.Release|Any CPU.Build.0 = Release|Any CPU - {21FDAB94-5014-488D-86C7-A366F1902B24}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21FDAB94-5014-488D-86C7-A366F1902B24}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21FDAB94-5014-488D-86C7-A366F1902B24}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21FDAB94-5014-488D-86C7-A366F1902B24}.Release|Any CPU.Build.0 = Release|Any CPU - {4A378F81-3805-41E8-9565-A8A89A8C00D6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A378F81-3805-41E8-9565-A8A89A8C00D6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A378F81-3805-41E8-9565-A8A89A8C00D6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A378F81-3805-41E8-9565-A8A89A8C00D6}.Release|Any CPU.Build.0 = Release|Any CPU - {FFCF6FA8-4F38-415E-AC2D-B576FFD5FED5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FFCF6FA8-4F38-415E-AC2D-B576FFD5FED5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FFCF6FA8-4F38-415E-AC2D-B576FFD5FED5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FFCF6FA8-4F38-415E-AC2D-B576FFD5FED5}.Release|Any CPU.Build.0 = Release|Any CPU - {71CBD7CC-C787-4796-B05E-4F3BC3C28B48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {71CBD7CC-C787-4796-B05E-4F3BC3C28B48}.Debug|Any CPU.Build.0 = Debug|Any CPU - {71CBD7CC-C787-4796-B05E-4F3BC3C28B48}.Release|Any CPU.ActiveCfg = Release|Any CPU - {71CBD7CC-C787-4796-B05E-4F3BC3C28B48}.Release|Any CPU.Build.0 = Release|Any CPU - {42E626F7-9A7E-4F55-B02C-16EB56E2B540}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42E626F7-9A7E-4F55-B02C-16EB56E2B540}.Debug|Any CPU.Build.0 = Debug|Any CPU - {42E626F7-9A7E-4F55-B02C-16EB56E2B540}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42E626F7-9A7E-4F55-B02C-16EB56E2B540}.Release|Any CPU.Build.0 = Release|Any CPU - {8BF2CBBF-6DAB-4D7A-87E0-AE643D6019AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8BF2CBBF-6DAB-4D7A-87E0-AE643D6019AB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8BF2CBBF-6DAB-4D7A-87E0-AE643D6019AB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8BF2CBBF-6DAB-4D7A-87E0-AE643D6019AB}.Release|Any CPU.Build.0 = Release|Any CPU - {262A8AE0-E610-405F-B4EC-DB714FB54C00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {262A8AE0-E610-405F-B4EC-DB714FB54C00}.Debug|Any CPU.Build.0 = Debug|Any CPU - {262A8AE0-E610-405F-B4EC-DB714FB54C00}.Release|Any CPU.ActiveCfg = Release|Any CPU - {262A8AE0-E610-405F-B4EC-DB714FB54C00}.Release|Any CPU.Build.0 = Release|Any CPU - {E5F07862-5715-470D-B324-19BDEBB2AA4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E5F07862-5715-470D-B324-19BDEBB2AA4D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E5F07862-5715-470D-B324-19BDEBB2AA4D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E5F07862-5715-470D-B324-19BDEBB2AA4D}.Release|Any CPU.Build.0 = Release|Any CPU - {21B591A0-F6E5-4645-BF2D-4E71F47394A7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {21B591A0-F6E5-4645-BF2D-4E71F47394A7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {21B591A0-F6E5-4645-BF2D-4E71F47394A7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {21B591A0-F6E5-4645-BF2D-4E71F47394A7}.Release|Any CPU.Build.0 = Release|Any CPU - {F093BDE5-1824-459E-B86E-B9F79B548E58}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F093BDE5-1824-459E-B86E-B9F79B548E58}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F093BDE5-1824-459E-B86E-B9F79B548E58}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F093BDE5-1824-459E-B86E-B9F79B548E58}.Release|Any CPU.Build.0 = Release|Any CPU - {EDA96974-0BEA-404B-8EED-F19CCA2C95A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EDA96974-0BEA-404B-8EED-F19CCA2C95A8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {EDA96974-0BEA-404B-8EED-F19CCA2C95A8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EDA96974-0BEA-404B-8EED-F19CCA2C95A8}.Release|Any CPU.Build.0 = Release|Any CPU - {ED2CAA2D-4E49-4636-86C4-367D0CDC3572}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {ED2CAA2D-4E49-4636-86C4-367D0CDC3572}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ED2CAA2D-4E49-4636-86C4-367D0CDC3572}.Release|Any CPU.ActiveCfg = Release|Any CPU - {ED2CAA2D-4E49-4636-86C4-367D0CDC3572}.Release|Any CPU.Build.0 = Release|Any CPU - {8DA821CC-F911-4FCB-8C29-5EF3D76A5F76}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8DA821CC-F911-4FCB-8C29-5EF3D76A5F76}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8DA821CC-F911-4FCB-8C29-5EF3D76A5F76}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8DA821CC-F911-4FCB-8C29-5EF3D76A5F76}.Release|Any CPU.Build.0 = Release|Any CPU - {36BF2B8B-F444-4886-AA4C-0EDF7540F1CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {36BF2B8B-F444-4886-AA4C-0EDF7540F1CE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {36BF2B8B-F444-4886-AA4C-0EDF7540F1CE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {36BF2B8B-F444-4886-AA4C-0EDF7540F1CE}.Release|Any CPU.Build.0 = Release|Any CPU - {751E4140-2F4D-4550-A4A9-65ABA9F7893A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {751E4140-2F4D-4550-A4A9-65ABA9F7893A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {751E4140-2F4D-4550-A4A9-65ABA9F7893A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {751E4140-2F4D-4550-A4A9-65ABA9F7893A}.Release|Any CPU.Build.0 = Release|Any CPU - {6E7857D9-07AC-419F-B111-0DB0348D1C92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6E7857D9-07AC-419F-B111-0DB0348D1C92}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6E7857D9-07AC-419F-B111-0DB0348D1C92}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6E7857D9-07AC-419F-B111-0DB0348D1C92}.Release|Any CPU.Build.0 = Release|Any CPU - {FF4BF0E7-698D-49A0-96E9-0E2646FEAFFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FF4BF0E7-698D-49A0-96E9-0E2646FEAFFA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF4BF0E7-698D-49A0-96E9-0E2646FEAFFA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FF4BF0E7-698D-49A0-96E9-0E2646FEAFFA}.Release|Any CPU.Build.0 = Release|Any CPU - {31667A36-D069-4708-9DCA-E3446009941B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {31667A36-D069-4708-9DCA-E3446009941B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {31667A36-D069-4708-9DCA-E3446009941B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {31667A36-D069-4708-9DCA-E3446009941B}.Release|Any CPU.Build.0 = Release|Any CPU - {11417BE7-7C4F-40D9-9FCB-467C7B3DCF66}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {11417BE7-7C4F-40D9-9FCB-467C7B3DCF66}.Debug|Any CPU.Build.0 = Debug|Any CPU - {11417BE7-7C4F-40D9-9FCB-467C7B3DCF66}.Release|Any CPU.ActiveCfg = Release|Any CPU - {11417BE7-7C4F-40D9-9FCB-467C7B3DCF66}.Release|Any CPU.Build.0 = Release|Any CPU - {6981A299-1743-4342-9F20-B8FC0263C54D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6981A299-1743-4342-9F20-B8FC0263C54D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6981A299-1743-4342-9F20-B8FC0263C54D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6981A299-1743-4342-9F20-B8FC0263C54D}.Release|Any CPU.Build.0 = Release|Any CPU - {544C21EF-51EF-4947-BBED-26A6794A71D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {544C21EF-51EF-4947-BBED-26A6794A71D7}.Debug|Any CPU.Build.0 = Debug|Any CPU - {544C21EF-51EF-4947-BBED-26A6794A71D7}.Release|Any CPU.ActiveCfg = Release|Any CPU - {544C21EF-51EF-4947-BBED-26A6794A71D7}.Release|Any CPU.Build.0 = Release|Any CPU - {D2B53F5A-9D6A-4402-B7FD-83BB1503D395}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D2B53F5A-9D6A-4402-B7FD-83BB1503D395}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D2B53F5A-9D6A-4402-B7FD-83BB1503D395}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D2B53F5A-9D6A-4402-B7FD-83BB1503D395}.Release|Any CPU.Build.0 = Release|Any CPU - {F1CCF5D2-EA11-4FE8-A5E2-A92655245893}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F1CCF5D2-EA11-4FE8-A5E2-A92655245893}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F1CCF5D2-EA11-4FE8-A5E2-A92655245893}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F1CCF5D2-EA11-4FE8-A5E2-A92655245893}.Release|Any CPU.Build.0 = Release|Any CPU - {0EA59927-C46A-43DE-9E16-ED64EC1F4FB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0EA59927-C46A-43DE-9E16-ED64EC1F4FB5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0EA59927-C46A-43DE-9E16-ED64EC1F4FB5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0EA59927-C46A-43DE-9E16-ED64EC1F4FB5}.Release|Any CPU.Build.0 = Release|Any CPU - {DDCEE1C8-80EE-4DFF-84F2-6CE67D02AC22}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DDCEE1C8-80EE-4DFF-84F2-6CE67D02AC22}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DDCEE1C8-80EE-4DFF-84F2-6CE67D02AC22}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DDCEE1C8-80EE-4DFF-84F2-6CE67D02AC22}.Release|Any CPU.Build.0 = Release|Any CPU - {3678F633-47DD-443B-8A6B-0CF33F45097F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {3678F633-47DD-443B-8A6B-0CF33F45097F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3678F633-47DD-443B-8A6B-0CF33F45097F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {3678F633-47DD-443B-8A6B-0CF33F45097F}.Release|Any CPU.Build.0 = Release|Any CPU - {FAF20A58-1CA6-4543-A8FB-70085F31EFDF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FAF20A58-1CA6-4543-A8FB-70085F31EFDF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FAF20A58-1CA6-4543-A8FB-70085F31EFDF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FAF20A58-1CA6-4543-A8FB-70085F31EFDF}.Release|Any CPU.Build.0 = Release|Any CPU - {2878A29C-E40F-4A1D-A0A3-678742D3814F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2878A29C-E40F-4A1D-A0A3-678742D3814F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2878A29C-E40F-4A1D-A0A3-678742D3814F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2878A29C-E40F-4A1D-A0A3-678742D3814F}.Release|Any CPU.Build.0 = Release|Any CPU - {BBDFF009-CD61-4345-AE16-01B18B5F8073}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BBDFF009-CD61-4345-AE16-01B18B5F8073}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BBDFF009-CD61-4345-AE16-01B18B5F8073}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BBDFF009-CD61-4345-AE16-01B18B5F8073}.Release|Any CPU.Build.0 = Release|Any CPU - {46E47494-A96A-4138-BA3E-3A9A012C518A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {46E47494-A96A-4138-BA3E-3A9A012C518A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {46E47494-A96A-4138-BA3E-3A9A012C518A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {46E47494-A96A-4138-BA3E-3A9A012C518A}.Release|Any CPU.Build.0 = Release|Any CPU - {33435863-4366-438B-9524-354D61E06806}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {33435863-4366-438B-9524-354D61E06806}.Debug|Any CPU.Build.0 = Debug|Any CPU - {33435863-4366-438B-9524-354D61E06806}.Release|Any CPU.ActiveCfg = Release|Any CPU - {33435863-4366-438B-9524-354D61E06806}.Release|Any CPU.Build.0 = Release|Any CPU - {661119FB-B83B-4C48-8810-48293C6D7661}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {661119FB-B83B-4C48-8810-48293C6D7661}.Debug|Any CPU.Build.0 = Debug|Any CPU - {661119FB-B83B-4C48-8810-48293C6D7661}.Release|Any CPU.ActiveCfg = Release|Any CPU - {661119FB-B83B-4C48-8810-48293C6D7661}.Release|Any CPU.Build.0 = Release|Any CPU - {42C051F5-8DF6-4335-83F9-43A732595C05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {42C051F5-8DF6-4335-83F9-43A732595C05}.Debug|Any CPU.Build.0 = Debug|Any CPU - {42C051F5-8DF6-4335-83F9-43A732595C05}.Release|Any CPU.ActiveCfg = Release|Any CPU - {42C051F5-8DF6-4335-83F9-43A732595C05}.Release|Any CPU.Build.0 = Release|Any CPU - {CB20A400-51AC-456E-B261-3F6804EA6314}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CB20A400-51AC-456E-B261-3F6804EA6314}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CB20A400-51AC-456E-B261-3F6804EA6314}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CB20A400-51AC-456E-B261-3F6804EA6314}.Release|Any CPU.Build.0 = Release|Any CPU - {E3950FB3-C4BD-4320-89F9-331C93781FBB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E3950FB3-C4BD-4320-89F9-331C93781FBB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E3950FB3-C4BD-4320-89F9-331C93781FBB}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E3950FB3-C4BD-4320-89F9-331C93781FBB}.Release|Any CPU.Build.0 = Release|Any CPU - {B9B67099-777A-4686-AE01-455B101B3B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B9B67099-777A-4686-AE01-455B101B3B36}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B9B67099-777A-4686-AE01-455B101B3B36}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B9B67099-777A-4686-AE01-455B101B3B36}.Release|Any CPU.Build.0 = Release|Any CPU - {77FF7FA8-EBC2-4400-B7FF-3A5F7DBFAEAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {77FF7FA8-EBC2-4400-B7FF-3A5F7DBFAEAE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {77FF7FA8-EBC2-4400-B7FF-3A5F7DBFAEAE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {77FF7FA8-EBC2-4400-B7FF-3A5F7DBFAEAE}.Release|Any CPU.Build.0 = Release|Any CPU - {A19BF0EC-70C3-49D0-B278-02807669F240}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A19BF0EC-70C3-49D0-B278-02807669F240}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A19BF0EC-70C3-49D0-B278-02807669F240}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A19BF0EC-70C3-49D0-B278-02807669F240}.Release|Any CPU.Build.0 = Release|Any CPU - {7CE6B276-A25C-4B7B-B99D-AD52C6B48E5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7CE6B276-A25C-4B7B-B99D-AD52C6B48E5B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7CE6B276-A25C-4B7B-B99D-AD52C6B48E5B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7CE6B276-A25C-4B7B-B99D-AD52C6B48E5B}.Release|Any CPU.Build.0 = Release|Any CPU - {1DE6CF9F-996E-459B-9129-D76245001F5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1DE6CF9F-996E-459B-9129-D76245001F5F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1DE6CF9F-996E-459B-9129-D76245001F5F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1DE6CF9F-996E-459B-9129-D76245001F5F}.Release|Any CPU.Build.0 = Release|Any CPU - {B467F55B-55C4-44E7-83EF-E6ABC9225A90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B467F55B-55C4-44E7-83EF-E6ABC9225A90}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B467F55B-55C4-44E7-83EF-E6ABC9225A90}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B467F55B-55C4-44E7-83EF-E6ABC9225A90}.Release|Any CPU.Build.0 = Release|Any CPU - {CE2F1DF8-347D-4AAF-870C-8F2A97FDC308}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {CE2F1DF8-347D-4AAF-870C-8F2A97FDC308}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CE2F1DF8-347D-4AAF-870C-8F2A97FDC308}.Release|Any CPU.ActiveCfg = Release|Any CPU - {CE2F1DF8-347D-4AAF-870C-8F2A97FDC308}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {CD7DECEC-F4A0-4EEF-978B-72748414D52A} - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {BBDFF009-CD61-4345-AE16-01B18B5F8073} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {FF4BF0E7-698D-49A0-96E9-0E2646FEAFFA} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {544C21EF-51EF-4947-BBED-26A6794A71D7} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {0EA59927-C46A-43DE-9E16-ED64EC1F4FB5} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {CB20A400-51AC-456E-B261-3F6804EA6314} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {E3950FB3-C4BD-4320-89F9-331C93781FBB} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {A19BF0EC-70C3-49D0-B278-02807669F240} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {7CE6B276-A25C-4B7B-B99D-AD52C6B48E5B} = {FF8CA700-BB6F-45FD-AEB6-CCAEACE50B0F} - {1DE6CF9F-996E-459B-9129-D76245001F5F} = {B8FAD767-CB47-4112-8AFC-8620A51B946A} - {CE2F1DF8-347D-4AAF-870C-8F2A97FDC308} = {B8FAD767-CB47-4112-8AFC-8620A51B946A} - EndGlobalSection -EndGlobal diff --git a/NAK_CVR_Mods.slnx b/NAK_CVR_Mods.slnx new file mode 100644 index 0000000..09c4813 --- /dev/null +++ b/NAK_CVR_Mods.slnx @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/PlapPlapForAll/Main.cs b/PlapPlapForAll/Main.cs index 7b05d3f..46f9bc0 100644 --- a/PlapPlapForAll/Main.cs +++ b/PlapPlapForAll/Main.cs @@ -58,15 +58,19 @@ public class PlapPlapForAllMod : MelonMod if (!Friends.FriendsWith(player.PlayerId)) return; + // AdvTags check mask + CVRAvatarAdvancedTaggingEntry.Tags findTags = 0; + findTags |= CVRAvatarAdvancedTaggingEntry.Tags.Explicit; + findTags |= CVRAvatarAdvancedTaggingEntry.Tags.Suggestive; + // Ensure the avatar is NSFW UgcContentTags tags = player.AvatarMetadata.TagsData; if (tags is { Suggestive: false, Explicit: false } // Main tags - && !avatar.TagHandledByAdvancedTagging(CVRAvatarAdvancedTaggingEntry.Tags.Suggestive) // Advanced tags - && !avatar.TagHandledByAdvancedTagging(CVRAvatarAdvancedTaggingEntry.Tags.Explicit)) + && !HasAdvTags(avatar.advancedTaggingList, findTags)) // Advanced tags return; // Ensure mature content is allowed by user settings - if (!MetaPort.Instance.matureContentAllowed) + if (!MetaPort.Instance.MatureContentPermitted) return; GameObject avatarObject = avatar.gameObject; @@ -102,6 +106,19 @@ public class PlapPlapForAllMod : MelonMod } } + private static bool HasAdvTags( + List list, + CVRAvatarAdvancedTaggingEntry.Tags findTags) + { + foreach (CVRAvatarAdvancedTaggingEntry entry in list) + { + // If entry is dead or no tags are blocked, go to next entry + if (entry == null || (entry.tags & findTags) == 0) continue; + return true; + } + return false; + } + /* Asset Bundle Loading */ private const string PlapPlapAssetsName = "PlapPlapForAll.Resources.plap plap.assets"; diff --git a/PlapPlapForAll/README.md b/PlapPlapForAll/README.md index 65ad59f..e0e3ad3 100644 --- a/PlapPlapForAll/README.md +++ b/PlapPlapForAll/README.md @@ -1,10 +1,10 @@ # PlapPlapForAll -Penetrator SFX mod which adds Noach's PlapPlap prefab to any detected DPS setup on avatars that do not already have it. +Penetrator SFX mod which adds Noachi's PlapPlap prefab to any detected DPS setup on avatars that do not already have it. **Requirements:** - The avatar must have DPS lights -- The avatar must not already have Noach's PlapPlap prefab +- The avatar must not already have Noachi's PlapPlap prefab - The avatar must be tagged Suggestive or Explicit - Mature content must be enabled in the user's settings - The avatar must be worn by a friend or the local user diff --git a/PlapPlapForAll/format.json b/PlapPlapForAll/format.json index 88c9774..b27d5b0 100644 --- a/PlapPlapForAll/format.json +++ b/PlapPlapForAll/format.json @@ -6,7 +6,7 @@ "loaderversion": "0.7.2", "modtype": "Mod", "author": "NotAKidoS, Noachi", - "description": "Penetrator SFX mod which adds Noach's PlapPlap prefab to any detected DPS setup on avatars that do not already have it.\n\n**Requirements:**\n- The avatar must have DPS lights\n- The avatar must not already have Noach's PlapPlap prefab\n- The avatar must be tagged Suggestive or Explicit\n- Mature content must be enabled in the user's settings\n- The avatar must be worn by a friend or the local user\n\nSFX are driven by the Avatar Audio slider. \n\nIf you have a setup which does not function correctly with this mod, I can *try* to look into it, but no guarantees.", + "description": "Penetrator SFX mod which adds Noachi's PlapPlap prefab to any detected DPS setup on avatars that do not already have it.\n\n**Requirements:**\n- The avatar must have DPS lights\n- The avatar must not already have Noachi's PlapPlap prefab\n- The avatar must be tagged Suggestive or Explicit\n- Mature content must be enabled in the user's settings\n- The avatar must be worn by a friend or the local user\n\nSFX are driven by the Avatar Audio slider. \n\nIf you have a setup which does not function correctly with this mod, I can *try* to look into it, but no guarantees.", "searchtags": [ "dps", "plapplap", diff --git a/PropUndoButton/Main.cs b/PropUndoButton/Main.cs index 2e7b4a9..8e1c4fe 100644 --- a/PropUndoButton/Main.cs +++ b/PropUndoButton/Main.cs @@ -1,362 +1,35 @@ -using System.Reflection; -using ABI_RC.Core.AudioEffects; -using ABI_RC.Core.Networking; -using ABI_RC.Core.Networking.GameServer; -using ABI_RC.Core.Savior; -using ABI_RC.Core.Util; -using ABI_RC.Systems.InputManagement.InputModules; -using ABI.CCK.Components; -using DarkRift; +using ABI_RC.Systems.InputManagement.InputModules; +using System.Reflection; +using ABI_RC.Core.PropManagement; using HarmonyLib; using MelonLoader; using UnityEngine; namespace NAK.PropUndoButton; -// https://pixabay.com/sound-effects/selection-sounds-73225/ - public class PropUndoButton : MelonMod { - private static readonly MelonPreferences_Category Category = - MelonPreferences.CreateCategory(nameof(PropUndoButton)); - - private static readonly MelonPreferences_Entry EntryEnabled = - Category.CreateEntry("Enabled", true, description: "Toggle Undo Prop Button."); - - private static readonly MelonPreferences_Entry EntryUseSFX = - Category.CreateEntry("Use SFX", true, - description: "Toggle audio queues for prop spawn, undo, redo, and warning."); - - private static readonly List deletedProps = []; - - // audio clip names, InterfaceAudio adds "PropUndo_" prefix - private const string sfx_spawn = "PropUndo_sfx_spawn"; - private const string sfx_undo = "PropUndo_sfx_undo"; - private const string sfx_redo = "PropUndo_sfx_redo"; - private const string sfx_warn = "PropUndo_sfx_warn"; - private const string sfx_deny = "PropUndo_sfx_deny"; - - private static int maxPropsPerUser = 20; - - // Amount that can be in history at once. - private static readonly int redoHistoryLimit = Mathf.Max(maxPropsPerUser, CVRSyncHelper.MyPropCount); - private const int redoTimeoutLimit = 120; // seconds - public override void OnInitializeMelon() { - GSInfoHandler.OnGSInfoUpdate += OnGSInfoUpdate; - - HarmonyInstance.Patch( // delete my props in reverse order for redo - typeof(CVRSyncHelper).GetMethod(nameof(CVRSyncHelper.DeleteMyProps)), - new HarmonyMethod(typeof(PropUndoButton).GetMethod(nameof(OnDeleteMyProps), - BindingFlags.NonPublic | BindingFlags.Static)) - ); - HarmonyInstance.Patch( // delete all props in reverse order for redo - typeof(CVRSyncHelper).GetMethod(nameof(CVRSyncHelper.DeleteAllProps)), - new HarmonyMethod(typeof(PropUndoButton).GetMethod(nameof(OnDeleteAllProps), - BindingFlags.NonPublic | BindingFlags.Static)) - ); - HarmonyInstance.Patch( // prop spawn sfx - typeof(CVRSyncHelper).GetMethod(nameof(CVRSyncHelper.SpawnProp)), - postfix: new HarmonyMethod(typeof(PropUndoButton).GetMethod(nameof(OnSpawnProp), - BindingFlags.NonPublic | BindingFlags.Static)) - ); - HarmonyInstance.Patch( // prop delete sfx, log for possible redo - typeof(CVRSyncHelper).GetMethod(nameof(CVRSyncHelper.DeleteMyPropByInstanceIdOverNetwork)), - postfix: new HarmonyMethod(typeof(PropUndoButton).GetMethod(nameof(OnDeletePropByInstanceId), - BindingFlags.NonPublic | BindingFlags.Static)) - ); HarmonyInstance.Patch( // desktop input patch so we don't run in menus/gui typeof(CVRInputModule_Keyboard).GetMethod(nameof(CVRInputModule_Keyboard.Update_Binds)), postfix: new HarmonyMethod(typeof(PropUndoButton).GetMethod(nameof(OnUpdateInput), BindingFlags.NonPublic | BindingFlags.Static)) ); - HarmonyInstance.Patch( // clear redo list on world change - typeof(CVRWorld).GetMethod(nameof(CVRWorld.ConfigureWorld)), - postfix: new HarmonyMethod(typeof(PropUndoButton).GetMethod(nameof(OnWorldLoad), - BindingFlags.NonPublic | BindingFlags.Static)) - ); - - SetupDefaultAudioClips(); - } - - private void SetupDefaultAudioClips() - { - // PropUndo and audio folders do not exist, create them if dont exist yet - var path = Application.streamingAssetsPath + "/Cohtml/UIResources/GameUI/mods/PropUndo/audio/"; - if (!Directory.Exists(path)) - { - Directory.CreateDirectory(path); - LoggerInstance.Msg("Created PropUndo/audio directory!"); - } - - // copy embedded resources to this folder if they do not exist - string[] clipNames = { "sfx_spawn.wav", "sfx_undo.wav", "sfx_redo.wav", "sfx_warn.wav", "sfx_deny.wav" }; - foreach (var clipName in clipNames) - { - var clipPath = Path.Combine(path, clipName); - if (!File.Exists(clipPath)) - { - // read the clip data from embedded resources - byte[] clipData; - var resourceName = "PropUndoButton.SFX." + clipName; - using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) - { - clipData = new byte[stream!.Length]; - stream.Read(clipData, 0, clipData.Length); - } - - // write the clip data to the file - using (FileStream fileStream = new(clipPath, FileMode.CreateNew)) - { - fileStream.Write(clipData, 0, clipData.Length); - } - - LoggerInstance.Msg("Placed missing sfx in audio folder: " + clipName); - } - } - } - - private void OnGSInfoUpdate(GSInfoUpdate update, GSInfoChanged changed) - { - if (changed == GSInfoChanged.MaxPropsPerUser) - maxPropsPerUser = update.MaxPropsPerUser; - } - - private static void OnWorldLoad() - { - deletedProps.Clear(); } private static void OnUpdateInput() { - if (!EntryEnabled.Value) return; - if (Input.GetKey(KeyCode.LeftControl)) { if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Z)) - RedoProp(); - else if (Input.GetKeyDown(KeyCode.Z)) UndoProp(); - } - } - - private static void OnSpawnProp() - { - if (!EntryEnabled.Value) return; - - if (!IsPropSpawnAllowed() || IsAtPropLimit()) - { - PlayAudioModule(sfx_deny); - return; - } - - PlayAudioModule(sfx_spawn); - } - - private static void OnDeletePropByInstanceId(string instanceId) - { - if (!EntryEnabled.Value || string.IsNullOrEmpty(instanceId)) return; - - CVRSyncHelper.PropData propData = GetPropByInstanceIdAndOwnerId(instanceId); - if (propData == null) return; - - AddDeletedProp(propData); - PlayAudioModule(sfx_undo); - } - - private static void AddDeletedProp(CVRSyncHelper.PropData propData) - { - if (deletedProps.Count >= redoHistoryLimit) - deletedProps.RemoveAt(0); - - DeletedProp deletedProp = new(propData); - deletedProps.Add(deletedProp); - } - - // delete in reverse order for undo to work as expected - private static bool OnDeleteMyProps() - { - if (!EntryEnabled.Value) return true; - - var propsList = GetAllPropsByOwnerId(); - - if (propsList.Count == 0) - { - PlayAudioModule(sfx_warn); - return false; - } - - for (var i = propsList.Count - 1; i >= 0; i--) - { - CVRSyncHelper.PropData propData = propsList[i]; - SafeDeleteProp(propData); - } - - return false; - } - - // delete in reverse order for undo to work as expected - private static bool OnDeleteAllProps() - { - if (!EntryEnabled.Value) return true; - - var propsList = CVRSyncHelper.Props.ToArray(); - if (propsList.Length == 0) - { - PlayAudioModule(sfx_warn); - return false; - } - - for (var i = propsList.Length - 1; i >= 0; i--) - { - CVRSyncHelper.PropData propData = propsList[i]; - SafeDeleteProp(propData); - } - - return false; - } - - private static void UndoProp() - { - CVRSyncHelper.PropData propData = GetLatestPropByOwnerId(); - if (propData == null) - { - PlayAudioModule(sfx_warn); - return; - } - - SafeDeleteProp(propData); - } - - public static void RedoProp() - { - var index = deletedProps.Count - 1; - if (index < 0) - { - PlayAudioModule(sfx_warn); - return; - } - - if (!IsPropSpawnAllowed() || IsAtPropLimit()) - { - PlayAudioModule(sfx_deny); - return; - } - - // only allow redo of prop spawned in last minute - DeletedProp deletedProp = deletedProps[index]; - if (Time.time - deletedProp.timeDeleted <= redoTimeoutLimit) - { - SendRedoProp(deletedProp.propGuid, deletedProp.position, deletedProp.rotation); - deletedProps.RemoveAt(index); - PlayAudioModule(sfx_redo); - } - else - { - // if latest prop is too old, same with rest - deletedProps.Clear(); - PlayAudioModule(sfx_warn); - } - } - - // original spawn prop method does not let you specify rotation - public static void SendRedoProp(string propGuid, Vector3 position, Vector3 rotation) - { - using (DarkRiftWriter darkRiftWriter = DarkRiftWriter.Create()) - { - darkRiftWriter.Write(propGuid); - darkRiftWriter.Write(position.x); - darkRiftWriter.Write(position.y); - darkRiftWriter.Write(position.z); - darkRiftWriter.Write(rotation.x); - darkRiftWriter.Write(rotation.y); - darkRiftWriter.Write(rotation.z); - darkRiftWriter.Write(1f); - darkRiftWriter.Write(1f); - darkRiftWriter.Write(1f); - darkRiftWriter.Write(0f); - using (Message message = Message.Create(10050, darkRiftWriter)) { - NetworkManager.Instance.GameNetwork.SendMessage(message, SendMode.Reliable); + PropUserActions.Redo(); } - } - } - - public static void PlayAudioModule(string module) - { - if (EntryUseSFX.Value) InterfaceAudio.PlayModule(module); - } - - private static void SafeDeleteProp(CVRSyncHelper.PropData propData) - { - if (propData.Spawnable == null) - { - // network delete prop manually, then delete prop data - CVRSyncHelper.DeleteMyPropByInstanceIdOverNetwork(propData.InstanceId); - propData.Recycle(); - return; - } - - // delete prop, prop data, and network delete prop - propData.Spawnable.Delete(); - } - - private static bool IsPropSpawnAllowed() - { - return MetaPort.Instance.worldAllowProps - && MetaPort.Instance.settings.GetSettingsBool("ContentFilterPropsEnabled") - && NetworkManager.Instance.GameNetwork.ConnectionState == ConnectionState.Connected; - } - - public static bool IsAtPropLimit() - { - return GetAllPropsByOwnerId().Count >= maxPropsPerUser; - } - - private static CVRSyncHelper.PropData GetPropByInstanceIdAndOwnerId(string instanceId) - { - return CVRSyncHelper.Props.Find(propData => - propData.InstanceId == instanceId && propData.SpawnedBy == MetaPort.Instance.ownerId); - } - - private static CVRSyncHelper.PropData GetLatestPropByOwnerId() - { - // return last prop spawned by owner in CVRSyncHelper.MySpawnedPropInstanceIds - return CVRSyncHelper.Props.LastOrDefault(propData => propData.SpawnedBy == MetaPort.Instance.ownerId); - } - - private static List GetAllPropsByOwnerId() - { - return CVRSyncHelper.Props.FindAll(propData => propData.SpawnedBy == MetaPort.Instance.ownerId); - } - - public class DeletedProp - { - public string propGuid; - public Vector3 position; - public Vector3 rotation; - public float timeDeleted; - - public DeletedProp(CVRSyncHelper.PropData propData) - { - if (propData.Spawnable == null) + else if (Input.GetKeyDown(KeyCode.Z)) { - // use original spawn position and rotation / last known position and rotation - position = new Vector3(propData.PositionX, propData.PositionY, propData.PositionZ); - rotation = new Vector3(propData.RotationX, propData.RotationY, propData.RotationZ); + PropUserActions.Undo(); } - else - { - Transform spawnableTransform = propData.Spawnable.transform; - position = spawnableTransform.position; - rotation = spawnableTransform.rotation.eulerAngles; - - // Offset spawn height so game can account for it later - position.y -= propData.Spawnable.spawnHeight; - } - - propGuid = propData.ObjectId; - timeDeleted = Time.time; } } } \ No newline at end of file diff --git a/PropUndoButton/PropUndoButton.csproj b/PropUndoButton/PropUndoButton.csproj index 9e48033..e94f9dc 100644 --- a/PropUndoButton/PropUndoButton.csproj +++ b/PropUndoButton/PropUndoButton.csproj @@ -1,12 +1,2 @@ - - - - - - - - - - - + diff --git a/PropUndoButton/Properties/AssemblyInfo.cs b/PropUndoButton/Properties/AssemblyInfo.cs index ec7d524..7196902 100644 --- a/PropUndoButton/Properties/AssemblyInfo.cs +++ b/PropUndoButton/Properties/AssemblyInfo.cs @@ -27,6 +27,6 @@ using System.Reflection; namespace NAK.PropUndoButton.Properties; internal static class AssemblyInfoParams { - public const string Version = "1.0.5"; + public const string Version = "1.0.6"; public const string Author = "NotAKidoS"; } \ No newline at end of file diff --git a/PropsButBetter/PropsButBetter/Extensions/PropDataExtensions.cs b/PropsButBetter/PropsButBetter/Extensions/PropDataExtensions.cs deleted file mode 100644 index db302f4..0000000 --- a/PropsButBetter/PropsButBetter/Extensions/PropDataExtensions.cs +++ /dev/null @@ -1,42 +0,0 @@ -using ABI_RC.Core.Networking; -using ABI_RC.Core.Util; - -namespace NAK.PropsButBetter; - -public static class PropDataExtensions -{ - extension(CVRSyncHelper.PropData prop) - { - public bool IsSpawnedByMe() - => prop.SpawnedBy == AuthManager.UserId; - - public void CopyFrom(CVRSyncHelper.PropData sourceData) - { - prop.ObjectId = sourceData.ObjectId; - prop.InstanceId = sourceData.InstanceId; - prop.PositionX = sourceData.PositionX; - prop.PositionY = sourceData.PositionY; - prop.PositionZ = sourceData.PositionZ; - prop.RotationX = sourceData.RotationX; - prop.RotationY = sourceData.RotationY; - prop.RotationZ = sourceData.RotationZ; - prop.ScaleX = sourceData.ScaleX; - prop.ScaleY = sourceData.ScaleY; - prop.ScaleZ = sourceData.ScaleZ; - prop.CustomFloatsAmount = sourceData.CustomFloatsAmount; - prop.CustomFloats = sourceData.CustomFloats; - prop.SpawnedBy = sourceData.SpawnedBy; - prop.syncedBy = sourceData.syncedBy; - prop.syncType = sourceData.syncType; - prop.ContentMetadata = sourceData.ContentMetadata; - prop.CanFireDecommissionEvents = sourceData.CanFireDecommissionEvents; - } - - public void RecycleSafe() - { - if (prop.IsSpawnedByMe()) - CVRSyncHelper.DeleteMyPropByInstanceIdOverNetwork(prop.InstanceId); - prop.Recycle(); - } - } -} \ No newline at end of file diff --git a/PropsButBetter/Resources/SFX/sfx_deny.wav b/PropsButBetter/Resources/SFX/sfx_deny.wav deleted file mode 100644 index 0a8b4ba..0000000 Binary files a/PropsButBetter/Resources/SFX/sfx_deny.wav and /dev/null differ diff --git a/PropsButBetter/Resources/SFX/sfx_redo.wav b/PropsButBetter/Resources/SFX/sfx_redo.wav deleted file mode 100644 index 41bb0cf..0000000 Binary files a/PropsButBetter/Resources/SFX/sfx_redo.wav and /dev/null differ diff --git a/PropsButBetter/Resources/SFX/sfx_spawn.wav b/PropsButBetter/Resources/SFX/sfx_spawn.wav deleted file mode 100644 index ab2aef3..0000000 Binary files a/PropsButBetter/Resources/SFX/sfx_spawn.wav and /dev/null differ diff --git a/PropsButBetter/Resources/SFX/sfx_undo.wav b/PropsButBetter/Resources/SFX/sfx_undo.wav deleted file mode 100644 index 84f0cf7..0000000 Binary files a/PropsButBetter/Resources/SFX/sfx_undo.wav and /dev/null differ diff --git a/PropsButBetter/Resources/SFX/sfx_warn.wav b/PropsButBetter/Resources/SFX/sfx_warn.wav deleted file mode 100644 index 8e96b57..0000000 Binary files a/PropsButBetter/Resources/SFX/sfx_warn.wav and /dev/null differ diff --git a/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel.csproj b/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel.csproj index 8920c39..e94f9dc 100644 --- a/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel.csproj +++ b/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel.csproj @@ -1,15 +1,2 @@ - - - net48 - GrabbableSteeringWheel - - - - ..\.ManagedLibs\BTKUILib.dll - - - ..\.ManagedLibs\TheClapper.dll - - - + diff --git a/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel/Components/SteeringWheelRoot.cs b/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel/Components/SteeringWheelRoot.cs index 088752d..8f87d6e 100644 --- a/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel/Components/SteeringWheelRoot.cs +++ b/RCCVirtualSteeringWheel/RCCVirtualSteeringWheel/Components/SteeringWheelRoot.cs @@ -95,7 +95,7 @@ public class SteeringWheelRoot : MonoBehaviour private void Start() { - ActiveWheels.TryAdd(_carController, this); + ActiveWheels.Add(_carController, this); InitializeWheel(); } diff --git a/RCCVirtualSteeringWheel/README.md b/RCCVirtualSteeringWheel/README.md index 8d9f529..8fe3516 100644 --- a/RCCVirtualSteeringWheel/README.md +++ b/RCCVirtualSteeringWheel/README.md @@ -4,11 +4,11 @@ Allows you to physically grab rigged RCC steering wheels in VR to provide steeri --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive.~~~~ \ No newline at end of file +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR.~~~~ \ No newline at end of file diff --git a/References.Items.props b/References.Items.props index 8c9a594..e59fad1 100644 --- a/References.Items.props +++ b/References.Items.props @@ -180,6 +180,10 @@ $(MsBuildThisFileDirectory)\.ManagedLibs\MeshBakerCore.dll False + + $(MsBuildThisFileDirectory)\.ManagedLibs\Meta.XR.BuildingBlocks.AIBlocks.dll + False + $(MsBuildThisFileDirectory)\.ManagedLibs\Meta.XR.BuildingBlocks.dll False @@ -200,10 +204,6 @@ $(MsBuildThisFileDirectory)\.ManagedLibs\Meta.XR.MultiplayerBlocks.Shared.dll False - - $(MsBuildThisFileDirectory)\.ManagedLibs\Microsoft.Win32.Registry.dll - False - $(MsBuildThisFileDirectory)\.ManagedLibs\Mono.Security.dll False @@ -360,10 +360,6 @@ $(MsBuildThisFileDirectory)\.ManagedLibs\System.Numerics.dll False - - $(MsBuildThisFileDirectory)\.ManagedLibs\System.Runtime.CompilerServices.Unsafe.dll - False - $(MsBuildThisFileDirectory)\.ManagedLibs\System.Runtime.dll False @@ -616,10 +612,6 @@ $(MsBuildThisFileDirectory)\.ManagedLibs\Unity.XR.MockHMD.dll False - - $(MsBuildThisFileDirectory)\.ManagedLibs\Unity.XR.Oculus.dll - False - $(MsBuildThisFileDirectory)\.ManagedLibs\Unity.XR.OpenVR.dll False diff --git a/RelativeSyncJitterFix/RelativeSyncJitterFix.csproj b/RelativeSyncJitterFix/RelativeSyncJitterFix.csproj index 2bdd4b3..e94f9dc 100644 --- a/RelativeSyncJitterFix/RelativeSyncJitterFix.csproj +++ b/RelativeSyncJitterFix/RelativeSyncJitterFix.csproj @@ -1,6 +1,2 @@ - - - Sprays - - + diff --git a/ShareBubbles/README.md b/ShareBubbles/README.md index 650f790..b71c256 100644 --- a/ShareBubbles/README.md +++ b/ShareBubbles/README.md @@ -40,11 +40,12 @@ If the game is closed unexpectedly, the claimant will keep the content until you --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. + diff --git a/ShareBubbles/ShareBubbles.csproj b/ShareBubbles/ShareBubbles.csproj index 734c1ec..73e0505 100644 --- a/ShareBubbles/ShareBubbles.csproj +++ b/ShareBubbles/ShareBubbles.csproj @@ -1,31 +1,5 @@ - - net48 - - - TRACE;TRACE;UNITY_2017_1_OR_NEWER;UNITY_2018_1_OR_NEWER;UNITY_2019_3_OR_NEWER;USE_BURST;USE_NEWMATHS;USE_BURST_REALLY;USE_TERRAINS - - - - - - - - - - - - - - - - - - ..\.ManagedLibs\BTKUILib.dll - - - diff --git a/ShowPlayerInSelfMirror/README.md b/ShowPlayerInSelfMirror/README.md index 3c85033..7c66d56 100644 --- a/ShowPlayerInSelfMirror/README.md +++ b/ShowPlayerInSelfMirror/README.md @@ -6,11 +6,11 @@ Probably useful for only showing specific people in your mirror while in a puddl --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/ShowPlayerInSelfMirror/ShowPlayerInSelfMirror.csproj b/ShowPlayerInSelfMirror/ShowPlayerInSelfMirror.csproj index 14fc5af..53544a4 100644 --- a/ShowPlayerInSelfMirror/ShowPlayerInSelfMirror.csproj +++ b/ShowPlayerInSelfMirror/ShowPlayerInSelfMirror.csproj @@ -1,8 +1,5 @@  - - PlayerCloneAttachment - diff --git a/SmootherRay/SmootherRay.csproj b/SmootherRay/SmootherRay.csproj index d2a45fb..e94f9dc 100644 --- a/SmootherRay/SmootherRay.csproj +++ b/SmootherRay/SmootherRay.csproj @@ -1,6 +1,2 @@ - - - SmoothRay - - + diff --git a/Tinyboard/README.md b/Tinyboard/README.md index 7ff0922..1413ed1 100644 --- a/Tinyboard/README.md +++ b/Tinyboard/README.md @@ -9,11 +9,11 @@ Few small tweaks to the keyboard: --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/Tinyboard/Tinyboard.csproj b/Tinyboard/Tinyboard.csproj index 5a8badc..e94f9dc 100644 --- a/Tinyboard/Tinyboard.csproj +++ b/Tinyboard/Tinyboard.csproj @@ -1,6 +1,2 @@ - - - YouAreMineNow - - + diff --git a/YouAreMyPropNowWeAreHavingSoftTacosLater/README.md b/YouAreMyPropNowWeAreHavingSoftTacosLater/README.md index b092e40..ada9003 100644 --- a/YouAreMyPropNowWeAreHavingSoftTacosLater/README.md +++ b/YouAreMyPropNowWeAreHavingSoftTacosLater/README.md @@ -12,11 +12,11 @@ https://fixupx.com/NotAKidoS/status/1910545346922422675 --- -Here is the block of text where I tell you this mod is not affiliated with or endorsed by ABI. -https://documentation.abinteractive.net/official/legal/tos/#7-modding-our-games +Here is the block of text where I tell you this mod is not affiliated with or endorsed by ChilloutVR. +https://docs.chilloutvr.net/official/legal/tos/#6-modding-our-game -> This mod is an independent creation not affiliated with, supported by, or approved by Alpha Blend Interactive. +> This mod is an independent creation not affiliated with, supported by, or approved by ChilloutVR. > Use of this mod is done so at the user's own risk and the creator cannot be held responsible for any issues arising from its use. -> To the best of my knowledge, I have adhered to the Modding Guidelines established by Alpha Blend Interactive. +> To the best of my knowledge, I have adhered to the Modding Guidelines established by ChilloutVR. diff --git a/YouAreMyPropNowWeAreHavingSoftTacosLater/YouAreMyPropNowWeAreHavingSoftTacosLater.csproj b/YouAreMyPropNowWeAreHavingSoftTacosLater/YouAreMyPropNowWeAreHavingSoftTacosLater.csproj index 5a8badc..e94f9dc 100644 --- a/YouAreMyPropNowWeAreHavingSoftTacosLater/YouAreMyPropNowWeAreHavingSoftTacosLater.csproj +++ b/YouAreMyPropNowWeAreHavingSoftTacosLater/YouAreMyPropNowWeAreHavingSoftTacosLater.csproj @@ -1,6 +1,2 @@ - - - YouAreMineNow - - + diff --git a/copy_and_nstrip_dll.ps1 b/copy_and_nstrip_dll.ps1 index 68fcc99..0cee733 100644 --- a/copy_and_nstrip_dll.ps1 +++ b/copy_and_nstrip_dll.ps1 @@ -13,7 +13,7 @@ $cvrDefaultPath = "C:\Program Files (x86)\Steam\steamapps\common\ChilloutVR" $dllsToStrip = @('Assembly-CSharp.dll','Assembly-CSharp-firstpass.dll','AVProVideo.Runtime.dll', 'Unity.TextMeshPro.dll', 'MagicaCloth.dll', 'MagicaClothV2.dll', 'ECM2.dll', 'DarkRift.dll', 'DarkRift.Client.dll', 'MTJobSystem.dll') # Array with the mods to grab -$modNames = @("BTKUILib") +# $modNames = @("") # Array with dlls to ignore from ManagedLibs $cvrManagedLibNamesToIgnore = @("netstandard", "Mono.Cecil", "Unity.Burst.Cecil")