mirror of
https://github.com/NotAKidoS/NAK_CVR_Mods.git
synced 2025-09-02 14:29:25 +00:00
ASTExtension: Initial release
This commit is contained in:
parent
4ae78984af
commit
3b830d31c4
7 changed files with 470 additions and 0 deletions
6
ASTExtension/ASTExtension.csproj
Normal file
6
ASTExtension/ASTExtension.csproj
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<RootNamespace>ASTExtension</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
17
ASTExtension/Extensions/PlayerSetupExtensions.cs
Normal file
17
ASTExtension/Extensions/PlayerSetupExtensions.cs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
using ABI_RC.Core.Player;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NAK.ASTExtension.Extensions;
|
||||||
|
|
||||||
|
public static class PlayerSetupExtensions
|
||||||
|
{
|
||||||
|
// immediate measurement of the player's avatar height
|
||||||
|
public static float GetCurrentAvatarHeight(this PlayerSetup playerSetup)
|
||||||
|
{
|
||||||
|
Vector3 localScale = playerSetup._avatar.transform.localScale;
|
||||||
|
Vector3 initialScale = playerSetup.initialScale;
|
||||||
|
float initialHeight = playerSetup._initialAvatarHeight;
|
||||||
|
Vector3 scaleDifference = PlayerSetup.DivideVectors(localScale - initialScale, initialScale);
|
||||||
|
return initialHeight + initialHeight * scaleDifference.y;
|
||||||
|
}
|
||||||
|
}
|
365
ASTExtension/Main.cs
Normal file
365
ASTExtension/Main.cs
Normal file
|
@ -0,0 +1,365 @@
|
||||||
|
using ABI_RC.Core.InteractionSystem;
|
||||||
|
using ABI_RC.Core.Player;
|
||||||
|
using ABI_RC.Core.Savior;
|
||||||
|
using ABI_RC.Core.Util.AnimatorManager;
|
||||||
|
using ABI_RC.Systems.GameEventSystem;
|
||||||
|
using ABI_RC.Systems.InputManagement;
|
||||||
|
using ABI.CCK.Components;
|
||||||
|
using MelonLoader;
|
||||||
|
using NAK.ASTExtension.Extensions;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NAK.ASTExtension;
|
||||||
|
|
||||||
|
public class ASTExtensionMod : MelonMod
|
||||||
|
{
|
||||||
|
private static MelonLogger.Instance Logger;
|
||||||
|
|
||||||
|
#region Melon Preferences
|
||||||
|
|
||||||
|
private static readonly MelonPreferences_Category Category =
|
||||||
|
MelonPreferences.CreateCategory(nameof(ASTExtension));
|
||||||
|
|
||||||
|
private static readonly MelonPreferences_Entry<bool> EntryUseScaleGesture =
|
||||||
|
Category.CreateEntry("use_scale_gesture", true,
|
||||||
|
"Use Scale Gesture", "Use the scale gesture to adjust your avatar's height.");
|
||||||
|
|
||||||
|
private static readonly MelonPreferences_Entry<bool> EntryUseCustomParameter =
|
||||||
|
Category.CreateEntry("use_custom_parameter", false,
|
||||||
|
"Use Custom Parameter", "Use a custom parameter to adjust your avatar's height.");
|
||||||
|
|
||||||
|
private static readonly MelonPreferences_Entry<string> EntryCustomParameterName =
|
||||||
|
Category.CreateEntry("custom_parameter_name", "AvatarScale",
|
||||||
|
"Custom Parameter Name", "The name of the custom parameter to use for height adjustment.");
|
||||||
|
|
||||||
|
private static readonly MelonPreferences_Entry<bool> EntryPersistentHeight =
|
||||||
|
Category.CreateEntry("persistent_height", false,
|
||||||
|
"Persistent Height", "Should the avatar height persist between avatar switches?");
|
||||||
|
|
||||||
|
private static readonly MelonPreferences_Entry<bool> EntryPersistThroughRestart =
|
||||||
|
Category.CreateEntry("persistent_height_through_restart", false,
|
||||||
|
"Persist Through Restart", "Should the avatar height persist between game restarts?");
|
||||||
|
|
||||||
|
private static readonly MelonPreferences_Entry<bool> EntryPersistFromUnsupported
|
||||||
|
= Category.CreateEntry("persist_from_unsupported", false,
|
||||||
|
"Persist From Unsupported", "Should the avatar height persist when the avatar is unsupported?");
|
||||||
|
|
||||||
|
// stores the last avatar height as a melon pref
|
||||||
|
private static readonly MelonPreferences_Entry<float> EntryHiddenAvatarHeight =
|
||||||
|
Category.CreateEntry("hidden_avatar_height", -2f, is_hidden: true);
|
||||||
|
|
||||||
|
private void InitializeSettings()
|
||||||
|
{
|
||||||
|
EntryUseCustomParameter.OnEntryValueChangedUntyped.Subscribe(OnUseCustomParameterChanged);
|
||||||
|
EntryCustomParameterName.OnEntryValueChangedUntyped.Subscribe(OnCustomParameterNameChanged);
|
||||||
|
OnUseCustomParameterChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUseCustomParameterChanged(object oldValue = null, object newValue = null)
|
||||||
|
{
|
||||||
|
SetupCustomParameter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCustomParameterNameChanged(object oldValue = null, object newValue = null)
|
||||||
|
{
|
||||||
|
SetupCustomParameter();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupCustomParameter()
|
||||||
|
{
|
||||||
|
// use custom parameter
|
||||||
|
if (EntryUseCustomParameter.Value)
|
||||||
|
{
|
||||||
|
_parameterName = EntryCustomParameterName.Value;
|
||||||
|
CalibrateCustomParameter();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset to default
|
||||||
|
_parameterName = "AvatarScale";
|
||||||
|
_minHeight = GlobalMinHeight;
|
||||||
|
_maxHeight = GlobalMaxHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Melon Preferences
|
||||||
|
|
||||||
|
#region Melon Events
|
||||||
|
|
||||||
|
public override void OnInitializeMelon()
|
||||||
|
{
|
||||||
|
Logger = LoggerInstance;
|
||||||
|
|
||||||
|
InitializeSettings();
|
||||||
|
InitializeScaleGesture();
|
||||||
|
|
||||||
|
CVRGameEventSystem.Avatar.OnLocalAvatarLoad.AddListener(OnLocalAvatarLoad);
|
||||||
|
CVRGameEventSystem.Avatar.OnLocalAvatarClear.AddListener(OnLocalAvatarClear);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Melon Events
|
||||||
|
|
||||||
|
#region Game Events
|
||||||
|
|
||||||
|
private void OnLocalAvatarLoad(CVRAvatar _)
|
||||||
|
{
|
||||||
|
_currentAvatarSupported = IsAvatarSupported();
|
||||||
|
if (!_currentAvatarSupported)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (EntryUseCustomParameter.Value
|
||||||
|
&& !string.IsNullOrEmpty(_parameterName))
|
||||||
|
CalibrateCustomParameter();
|
||||||
|
|
||||||
|
if (EntryPersistThroughRestart.Value
|
||||||
|
&& _lastHeight < 0) // has not been set
|
||||||
|
{
|
||||||
|
var lastHeight = EntryHiddenAvatarHeight.Value;
|
||||||
|
if (lastHeight > 0) SetAvatarHeight(lastHeight, true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (EntryPersistentHeight.Value
|
||||||
|
&& _lastHeight > 0) // has been set
|
||||||
|
SetAvatarHeight(_lastHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLocalAvatarClear(CVRAvatar _)
|
||||||
|
{
|
||||||
|
_currentAvatarSupported = false;
|
||||||
|
|
||||||
|
if (!EntryPersistentHeight.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!IsAvatarSupported()
|
||||||
|
&& !EntryPersistFromUnsupported.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// update the last height
|
||||||
|
var height = PlayerSetup.Instance.GetCurrentAvatarHeight();
|
||||||
|
_lastHeight = height;
|
||||||
|
EntryHiddenAvatarHeight.Value = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Game Events
|
||||||
|
|
||||||
|
#region Avatar Scale Tool
|
||||||
|
|
||||||
|
// todo: tool needs a dedicated parameter name
|
||||||
|
//private const string ASTParameterName = "ASTHeight";
|
||||||
|
//private const string ASTMotionParameterName = "#MotionScale";
|
||||||
|
|
||||||
|
//https://github.com/NotAKidoS/AvatarScaleTool/blob/eaa6d343f916b9bb834bb30989fc6987680492a2/AvatarScaleTool/Editor/Scripts/AvatarScaleTool.cs#L13-L14
|
||||||
|
private const float GlobalMinHeight = 0.25f;
|
||||||
|
private const float GlobalMaxHeight = 2.5f;
|
||||||
|
|
||||||
|
private string _parameterName = "AvatarScale";
|
||||||
|
|
||||||
|
private float _lastHeight = -1f;
|
||||||
|
private float _minHeight = GlobalMinHeight;
|
||||||
|
private float _maxHeight = GlobalMaxHeight;
|
||||||
|
private bool _currentAvatarSupported;
|
||||||
|
|
||||||
|
private float GetValueFromHeight(float height)
|
||||||
|
{
|
||||||
|
return Mathf.Clamp01((height - _minHeight) / (_maxHeight - _minHeight));
|
||||||
|
}
|
||||||
|
|
||||||
|
private float GetHeightFromValue(float value)
|
||||||
|
{
|
||||||
|
return Mathf.Lerp(_minHeight, _maxHeight, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetAvatarHeight(float height, bool immediate = false)
|
||||||
|
{
|
||||||
|
if (!IsAvatarSupported())
|
||||||
|
return;
|
||||||
|
|
||||||
|
AvatarAnimatorManager animatorManager = PlayerSetup.Instance.animatorManager;
|
||||||
|
if (!animatorManager.IsInitialized)
|
||||||
|
{
|
||||||
|
Logger.Error("AnimatorManager is not initialized!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!animatorManager.HasParameter(_parameterName))
|
||||||
|
{
|
||||||
|
Logger.Error($"Parameter '{_parameterName}' does not exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Animator animator = animatorManager.Animator;
|
||||||
|
var value = GetValueFromHeight(height);
|
||||||
|
animator.SetFloat(_parameterName, value);
|
||||||
|
if (immediate) animator.Update(0f); // apply
|
||||||
|
|
||||||
|
_lastHeight = height; // session
|
||||||
|
EntryHiddenAvatarHeight.Value = height; // persistent
|
||||||
|
|
||||||
|
// update in menus
|
||||||
|
CVR_MenuManager.Instance.SendAdvancedAvatarUpdate(_parameterName, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsAvatarSupported()
|
||||||
|
{
|
||||||
|
// check if avatar has the parameter
|
||||||
|
AvatarAnimatorManager animatorManager = PlayerSetup.Instance.animatorManager;
|
||||||
|
if (!animatorManager.IsInitialized)
|
||||||
|
{
|
||||||
|
Logger.Error("AnimatorManager is not initialized!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!animatorManager.HasParameter(_parameterName))
|
||||||
|
{
|
||||||
|
Logger.Error($"Parameter '{_parameterName}' does not exist!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Avatar Scale Tool
|
||||||
|
|
||||||
|
#region Custom Parameter Calibration
|
||||||
|
|
||||||
|
private void CalibrateCustomParameter()
|
||||||
|
{
|
||||||
|
AvatarAnimatorManager animatorManager = PlayerSetup.Instance.animatorManager;
|
||||||
|
if (!animatorManager.IsInitialized)
|
||||||
|
{
|
||||||
|
Logger.Error("AnimatorManager is not initialized!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!animatorManager.HasParameter(_parameterName))
|
||||||
|
{
|
||||||
|
Logger.Error($"Parameter '{_parameterName}' does not exist!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Animator animator = animatorManager.Animator; // we get from animator manager to ensure we have *profile* param
|
||||||
|
animatorManager.GetParameter(_parameterName, out float initialValue);
|
||||||
|
|
||||||
|
// set min height to 0
|
||||||
|
animator.SetFloat(_parameterName, 0f);
|
||||||
|
animator.Update(0f); // apply
|
||||||
|
var minHeight = PlayerSetup.Instance.GetCurrentAvatarHeight();
|
||||||
|
|
||||||
|
// set max height to 1
|
||||||
|
animator.SetFloat(_parameterName, 1f);
|
||||||
|
animator.Update(0f); // apply
|
||||||
|
var maxHeight = PlayerSetup.Instance.GetCurrentAvatarHeight();
|
||||||
|
|
||||||
|
// reset the parameter to its initial value
|
||||||
|
animator.SetFloat(_parameterName, initialValue);
|
||||||
|
animator.Update(0f); // apply
|
||||||
|
|
||||||
|
Logger.Msg(
|
||||||
|
$"Calibrated custom parameter '{_parameterName}' with min height {minHeight} and max height {maxHeight}");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Custom Parameter Calibration
|
||||||
|
|
||||||
|
#region Scale Reconizer
|
||||||
|
|
||||||
|
// Require triggers to be down while doing fist - Exteratta
|
||||||
|
private readonly bool RequireTriggers = true;
|
||||||
|
|
||||||
|
// Initial values when scale gesture is started
|
||||||
|
private float _initialModifier;
|
||||||
|
private float _initialTargetHeight;
|
||||||
|
|
||||||
|
private void InitializeScaleGesture()
|
||||||
|
{
|
||||||
|
// This requires arms far outward- pull inward with fist and triggers.
|
||||||
|
// Release triggers while still holding fist to readjust.
|
||||||
|
|
||||||
|
CVRGesture gesture = new()
|
||||||
|
{
|
||||||
|
name = "astExtensionIn",
|
||||||
|
type = CVRGesture.GestureType.Hold
|
||||||
|
};
|
||||||
|
gesture.steps.Add(new CVRGestureStep
|
||||||
|
{
|
||||||
|
firstGesture = CVRGestureStep.Gesture.Fist,
|
||||||
|
secondGesture = CVRGestureStep.Gesture.Fist,
|
||||||
|
startDistance = 1f,
|
||||||
|
endDistance = 0.25f,
|
||||||
|
direction = CVRGestureStep.GestureDirection.MovingIn,
|
||||||
|
needsToBeInView = true
|
||||||
|
});
|
||||||
|
gesture.onStart.AddListener(OnScaleStart);
|
||||||
|
gesture.onStay.AddListener(OnScaleStay);
|
||||||
|
CVRGestureRecognizer.Instance.gestures.Add(gesture);
|
||||||
|
|
||||||
|
gesture = new CVRGesture
|
||||||
|
{
|
||||||
|
name = "astExtensionOut",
|
||||||
|
type = CVRGesture.GestureType.Hold
|
||||||
|
};
|
||||||
|
gesture.steps.Add(new CVRGestureStep
|
||||||
|
{
|
||||||
|
firstGesture = CVRGestureStep.Gesture.Fist,
|
||||||
|
secondGesture = CVRGestureStep.Gesture.Fist,
|
||||||
|
startDistance = 0.25f,
|
||||||
|
endDistance = 1f,
|
||||||
|
direction = CVRGestureStep.GestureDirection.MovingOut,
|
||||||
|
needsToBeInView = true
|
||||||
|
});
|
||||||
|
gesture.onStart.AddListener(OnScaleStart);
|
||||||
|
gesture.onStay.AddListener(OnScaleStay);
|
||||||
|
CVRGestureRecognizer.Instance.gestures.Add(gesture);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnScaleStart(float modifier, Transform transform1, Transform transform2)
|
||||||
|
{
|
||||||
|
if (!_currentAvatarSupported)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!EntryUseScaleGesture.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Store initial modifier so we can get difference later
|
||||||
|
_initialModifier = Mathf.Max(modifier, 0.01f); // no zero
|
||||||
|
_initialTargetHeight = PlayerSetup.Instance.GetCurrentAvatarHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnScaleStay(float modifier, Transform transform1, Transform transform2)
|
||||||
|
{
|
||||||
|
if (!_currentAvatarSupported)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!EntryUseScaleGesture.Value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
modifier = Mathf.Max(modifier, 0.01f); // no zero
|
||||||
|
|
||||||
|
// Allow user to release triggers to reset "world grip"
|
||||||
|
if (RequireTriggers && !AreBothTriggersDown())
|
||||||
|
{
|
||||||
|
_initialModifier = modifier;
|
||||||
|
_initialTargetHeight = PlayerSetup.Instance.GetCurrentAvatarHeight();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert so the gesture is more of a world squish instead of happy hug
|
||||||
|
var modifierRatio = 1f / (modifier / _initialModifier);
|
||||||
|
|
||||||
|
// Determine the adjustment factor for the height, this will be >1 if scaling up, <1 if scaling down.
|
||||||
|
var heightAdjustmentFactor = modifierRatio > 1 ? 1 + (modifierRatio - 1) : 1 - (1 - modifierRatio);
|
||||||
|
|
||||||
|
// Apply the adjustment to the target height
|
||||||
|
var targetHeight = _initialTargetHeight * heightAdjustmentFactor;
|
||||||
|
targetHeight = Mathf.Clamp(targetHeight, _minHeight, _maxHeight);
|
||||||
|
SetAvatarHeight(targetHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool AreBothTriggersDown()
|
||||||
|
{
|
||||||
|
// Maybe it should be one trigger? Imagine XSOverlay scaling but for player.
|
||||||
|
return CVRInputManager.Instance.interactLeftValue > 0.75f &&
|
||||||
|
CVRInputManager.Instance.interactRightValue > 0.75f;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Scale Reconizer
|
||||||
|
}
|
32
ASTExtension/Properties/AssemblyInfo.cs
Normal file
32
ASTExtension/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
using MelonLoader;
|
||||||
|
using NAK.ASTExtension.Properties;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
[assembly: AssemblyVersion(AssemblyInfoParams.Version)]
|
||||||
|
[assembly: AssemblyFileVersion(AssemblyInfoParams.Version)]
|
||||||
|
[assembly: AssemblyInformationalVersion(AssemblyInfoParams.Version)]
|
||||||
|
[assembly: AssemblyTitle(nameof(NAK.ASTExtension))]
|
||||||
|
[assembly: AssemblyCompany(AssemblyInfoParams.Author)]
|
||||||
|
[assembly: AssemblyProduct(nameof(NAK.ASTExtension))]
|
||||||
|
|
||||||
|
[assembly: MelonInfo(
|
||||||
|
typeof(NAK.ASTExtension.ASTExtensionMod),
|
||||||
|
nameof(NAK.ASTExtension),
|
||||||
|
AssemblyInfoParams.Version,
|
||||||
|
AssemblyInfoParams.Author,
|
||||||
|
downloadLink: "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension"
|
||||||
|
)]
|
||||||
|
|
||||||
|
[assembly: MelonGame("Alpha Blend Interactive", "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.ASTExtension.Properties;
|
||||||
|
internal static class AssemblyInfoParams
|
||||||
|
{
|
||||||
|
public const string Version = "1.0.0";
|
||||||
|
public const string Author = "NotAKidoS";
|
||||||
|
}
|
20
ASTExtension/README.md
Normal file
20
ASTExtension/README.md
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# ASTExtension
|
||||||
|
|
||||||
|
Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):
|
||||||
|
- VR Gesture to scale
|
||||||
|
- Match IRL height
|
||||||
|
- Persistent height
|
||||||
|
- Copy height from others
|
||||||
|
|
||||||
|
Requires setup in Unity. This is **not** Universal Scaling.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
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.
|
24
ASTExtension/format.json
Normal file
24
ASTExtension/format.json
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"_id": -1,
|
||||||
|
"name": "ASTExtension",
|
||||||
|
"modversion": "1.0.0",
|
||||||
|
"gameversion": "2024r175",
|
||||||
|
"loaderversion": "0.6.1",
|
||||||
|
"modtype": "Mod",
|
||||||
|
"author": "NotAKidoS",
|
||||||
|
"description": "Extension mod for [Avatar Scale Tool](https://github.com/NotAKidoS/AvatarScaleTool):\n- VR Gesture to scale\n- Match IRL height\n- Persistent height\n- Copy height from others\n\nRequires setup in Unity. This is **not** Universal Scaling.",
|
||||||
|
"searchtags": [
|
||||||
|
"tool",
|
||||||
|
"scaling",
|
||||||
|
"height",
|
||||||
|
"extension",
|
||||||
|
"avatar"
|
||||||
|
],
|
||||||
|
"requirements": [
|
||||||
|
"None"
|
||||||
|
],
|
||||||
|
"downloadlink": "https://github.com/NotAKidoS/NAK_CVR_Mods/releases/download/r33/ASTExtension.dll",
|
||||||
|
"sourcelink": "https://github.com/NotAKidoS/NAK_CVR_Mods/tree/main/ASTExtension/",
|
||||||
|
"changelog": "- Initial release",
|
||||||
|
"embedcolor": "#f61963"
|
||||||
|
}
|
|
@ -77,6 +77,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "InteractionTest", "Interact
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeepVelocityOnExitFlight", "KeepVelocityOnExitFlight\KeepVelocityOnExitFlight.csproj", "{0BB3D187-BBBA-4C58-B246-102342BE5E8C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeepVelocityOnExitFlight", "KeepVelocityOnExitFlight\KeepVelocityOnExitFlight.csproj", "{0BB3D187-BBBA-4C58-B246-102342BE5E8C}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASTExtension", "ASTExtension\ASTExtension.csproj", "{6580AA87-6A95-438E-A5D3-70E583CCD77B}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
@ -231,6 +233,10 @@ Global
|
||||||
{0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{0BB3D187-BBBA-4C58-B246-102342BE5E8C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{0BB3D187-BBBA-4C58-B246-102342BE5E8C}.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
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue