Skip to content
This repository has been archived by the owner on Sep 30, 2019. It is now read-only.

Commit

Permalink
Updated for Beat Saber version 0.11.0. Speed can be changed from 100%…
Browse files Browse the repository at this point in the history
… + if playing without no fail, with no fail you can go below 100%.
  • Loading branch information
xyonico committed Jul 26, 2018
1 parent c397e02 commit dd72a62
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 79 deletions.
45 changes: 45 additions & 0 deletions PracticePlugin/CustomNoteCutSoundEffect.cs
@@ -0,0 +1,45 @@
using System;
using UnityEngine;

namespace PracticePlugin
{
public class CustomNoteCutSoundEffect : NoteCutSoundEffect
{
public static CustomNoteCutSoundEffect CopyOriginal(NoteCutSoundEffect original)
{
var gameObj = Instantiate(original.gameObject);
gameObj.name = "This is a copy!";
//gameObj.SetActive(false);
original = gameObj.GetComponent<NoteCutSoundEffect>();
var noteCutSoundEffect = (CustomNoteCutSoundEffect) ReflectionUtil.CopyComponent(original, typeof(NoteCutSoundEffect),
typeof(CustomNoteCutSoundEffect), gameObj);
DestroyImmediate(original);
noteCutSoundEffect.Awake();
return noteCutSoundEffect;
}

public override void Awake()
{
if (_badCutSoundEffectAudioClips == null) return;
base.Awake();
}

public override void LateUpdate()
{
if (_audioSource.clip == null) return;
base.LateUpdate();
}

public override void Init(AudioClip audioClip, float volumeScale, double noteDSPTime, float aheadTime, float missedTimeOffset,
Saber saber, NoteData noteData, bool handleWrongSaberTypeAsGood)
{
base.Init(audioClip, volumeScale, noteDSPTime, aheadTime, missedTimeOffset, saber, noteData, handleWrongSaberTypeAsGood);
_audioSource.Stop();
var dspTime = AudioSettings.dspTime;
var timeDiff = noteDSPTime - dspTime;
timeDiff /= Plugin.TimeScale;
var newTime = dspTime + (timeDiff - aheadTime);
_audioSource.PlayScheduled(newTime);
}
}
}
30 changes: 30 additions & 0 deletions PracticePlugin/NoteHitPitchChanger.cs
@@ -0,0 +1,30 @@
using System;
using System.Linq;
using UnityEngine;
using Object = UnityEngine.Object;

namespace PracticePlugin
{
public static class NoteHitPitchChanger
{
private static CustomNoteCutSoundEffect _noteCutSoundEffect;

public static void ReplacePrefab()
{
var noteCutSoundEffectManager = Resources.FindObjectsOfTypeAll<NoteCutSoundEffectManager>().FirstOrDefault();
if (noteCutSoundEffectManager == null) return;
var noteCutSoundEffect =
noteCutSoundEffectManager.GetPrivateField<NoteCutSoundEffect>("_noteCutSoundEffectPrefab");
var oldNotes = noteCutSoundEffect.GetSpawned();
foreach (var oldNote in oldNotes)
{
Object.Destroy(oldNote);
}
noteCutSoundEffect.RecycleAll();
_noteCutSoundEffect = CustomNoteCutSoundEffect.CopyOriginal(noteCutSoundEffect);
_noteCutSoundEffect.CreatePool(20,
new Action<NoteCutSoundEffect>(noteCutSoundEffectManager.SetCutSoundEffectEventCallbacks));
noteCutSoundEffectManager.SetPrivateField("_noteCutSoundEffectPrefab", _noteCutSoundEffect);
}
}
}
51 changes: 23 additions & 28 deletions PracticePlugin/Plugin.cs
@@ -1,18 +1,19 @@
using System;
using System.IO;
using System.Linq;
using IllusionPlugin;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.XR;
using Object = UnityEngine.Object;

namespace PracticePlugin
{
public class Plugin : IPlugin
{
public const float MaxSize = 5f;
public const float StepSize = 0.05f;

public static GameObject SettingsObject;

public static float TimeScale
Expand All @@ -34,20 +35,7 @@ public static float TimeScale
}
private static float _timeScale = 1;

public static bool Enabled
{
get { return _enabled; }
set
{
_enabled = value;
if (!_enabled)
{
TimeScale = 1;
}
}
}

private static bool _enabled;
public static bool NoFail { get; private set; }

private bool _init;
private MainGameSceneSetupData _mainGameSceneSetupData;
Expand All @@ -63,7 +51,7 @@ public string Name

public string Version
{
get { return "v1.1"; }
get { return "v2.0"; }
}

public void OnApplicationStart()
Expand All @@ -90,7 +78,7 @@ private void SceneManagerOnActiveSceneChanged(Scene arg0, Scene scene)
SettingsObject.SetActive(false);
volumeSettings.gameObject.SetActive(true);
var volume = SettingsObject.GetComponent<VolumeSettingsController>();
ReflectionUtil.CopyComponent(volume, typeof(SimpleSettingsController), typeof(SpeedSettingsController), SettingsObject);
ReflectionUtil.CopyComponent(volume, typeof(IncDecSettingsController), typeof(SpeedSettingsController), SettingsObject);
Object.DestroyImmediate(volume);
SettingsObject.GetComponentInChildren<TMP_Text>().text = "SPEED";
Object.DontDestroyOnLoad(SettingsObject);
Expand All @@ -103,28 +91,30 @@ private void SceneManagerOnActiveSceneChanged(Scene arg0, Scene scene)
_mainGameSceneSetupData = Resources.FindObjectsOfTypeAll<MainGameSceneSetupData>().FirstOrDefault();
}

if (_mainGameSceneSetupData == null || scene.buildIndex != 4)
if (_mainGameSceneSetupData == null || scene.buildIndex != 5)
{
return;
}

if (_lastLevelId != _mainGameSceneSetupData.levelId && !string.IsNullOrEmpty(_lastLevelId))
if (_lastLevelId != _mainGameSceneSetupData.difficultyLevel.level.levelID && !string.IsNullOrEmpty(_lastLevelId))
{
TimeScale = 1;
_lastLevelId = _mainGameSceneSetupData.levelId;
_lastLevelId = _mainGameSceneSetupData.difficultyLevel.level.levelID;
}

_lastLevelId = _mainGameSceneSetupData.levelId;
_lastLevelId = _mainGameSceneSetupData.difficultyLevel.level.levelID;

_audioTimeSync = Resources.FindObjectsOfTypeAll<AudioTimeSyncController>().FirstOrDefault();
_audioTimeSync.forcedAudioSync = true;
_songAudio = ReflectionUtil.GetPrivateField<AudioSource>(_audioTimeSync, "_audioSource");
Enabled = _mainGameSceneSetupData.gameplayOptions.noEnergy;
var noteCutSoundEffectManager = Resources.FindObjectsOfTypeAll<NoteCutSoundEffectManager>().FirstOrDefault();
var noteCutSoundEffect =
ReflectionUtil.GetPrivateField<NoteCutSoundEffect>(noteCutSoundEffectManager, "_noteCutSoundEffectPrefab");
_noteCutAudioSource =
ReflectionUtil.GetPrivateField<AudioSource>(noteCutSoundEffect, "_audioSource");
NoFail = !_mainGameSceneSetupData.gameplayOptions.validForScoreUse;

if (!NoFail)
{
TimeScale = Mathf.Clamp(TimeScale, 1, MaxSize);
}

NoteHitPitchChanger.ReplacePrefab();

var canvas = Resources.FindObjectsOfTypeAll<HorizontalLayoutGroup>().FirstOrDefault(x => x.name == "Buttons")
.transform.parent;
Expand All @@ -133,6 +123,11 @@ private void SceneManagerOnActiveSceneChanged(Scene arg0, Scene scene)
}
}

private void ScoreControllerOnNoteWasCutEvent(NoteData arg1, NoteCutInfo arg2, int arg3)
{
throw new NotImplementedException();
}

public void OnLevelWasLoaded(int level)
{

Expand Down
43 changes: 14 additions & 29 deletions PracticePlugin/PracticePlugin.csproj
Expand Up @@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>PracticePlugin</RootNamespace>
<AssemblyName>PracticePlugin</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Expand All @@ -33,59 +33,44 @@
</PropertyGroup>
<ItemGroup>
<Reference Include="Assembly-CSharp, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Assembly-CSharp.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\Assembly-CSharp.dll</HintPath>
</Reference>
<Reference Include="IllusionPlugin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\IllusionPlugin.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\IllusionPlugin.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="TextMeshPro-1.0.55.2017.1.0b12, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\TextMeshPro-1.0.55.2017.1.0b12.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\TextMeshPro-1.0.55.2017.1.0b12.dll</HintPath>
</Reference>
<Reference Include="UnityEngine, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AnimationModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.AudioModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.CoreModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.TextRenderingModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.TextRenderingModule.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UI, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UI.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UI.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIElementsModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.UIModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UIModule.dll</HintPath>
</Reference>
<Reference Include="UnityEngine.VRModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null">
<HintPath>D:\SteamLibrary\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.VRModule.dll</HintPath>
<HintPath>..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Beat Saber\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CustomNoteCutSoundEffect.cs" />
<Compile Include="NoteHitPitchChanger.cs" />
<Compile Include="Plugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReflectionUtil.cs" />
<Compile Include="SpeedSettingsController.cs" />
<Compile Include="SpeedSettingsCreator.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
<Target Name="AfterBuild">
<Copy SourceFiles="$(OutputPath)PracticePlugin.dll" DestinationFolder="C:\Program Files (x86)\Steam\steamapps\common\Beat Saber\Plugins\" ContinueOnError="true" />
</Target>
</Project>
6 changes: 3 additions & 3 deletions PracticePlugin/Properties/AssemblyInfo.cs
Expand Up @@ -9,7 +9,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("PracticePlugin")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyCopyright("Copyright © xyonico 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Expand All @@ -31,5 +31,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("2.0")]
[assembly: AssemblyFileVersion("2.0")]
11 changes: 6 additions & 5 deletions PracticePlugin/ReflectionUtil.cs
Expand Up @@ -6,27 +6,27 @@ namespace PracticePlugin
{
public static class ReflectionUtil
{
public static void SetPrivateField(object obj, string fieldName, object value)
public static void SetPrivateField(this object obj, string fieldName, object value)
{
var prop = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
prop.SetValue(obj, value);
}

public static T GetPrivateField<T>(object obj, string fieldName)
public static T GetPrivateField<T>(this object obj, string fieldName)
{
var prop = obj.GetType().GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
var value = prop.GetValue(obj);
return (T) value;
}

public static void SetPrivateProperty(object obj, string propertyName, object value)
public static void SetPrivateProperty(this object obj, string propertyName, object value)
{
var prop = obj.GetType()
.GetProperty(propertyName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
prop.SetValue(obj, value, null);
}

public static void InvokePrivateMethod(object obj, string methodName, object[] methodParams)
public static void InvokePrivateMethod(this object obj, string methodName, object[] methodParams)
{
MethodInfo dynMethod = obj.GetType().GetMethod(methodName, BindingFlags.NonPublic | BindingFlags.Instance);
dynMethod.Invoke(obj, methodParams);
Expand All @@ -40,7 +40,8 @@ public static void InvokePrivateMethod(object obj, string methodName, object[] m
BindingFlags.GetField);
foreach (var field in fields)
{
field.SetValue(copy, field.GetValue(original));
var value = field.GetValue(original);
field.SetValue(copy, value);
}

return copy;
Expand Down
19 changes: 8 additions & 11 deletions PracticePlugin/SpeedSettingsController.cs
@@ -1,20 +1,17 @@
using System;
using System.Reflection;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
using UnityEngine;

namespace PracticePlugin
{
public class SpeedSettingsController : ListSettingsController
{
private const float MaxSize = 5f;
private const float StepSize = 0.05f;

private int _indexOffset;

protected override void GetInitValues(out int idx, out int numberOfElements)
{
numberOfElements = Mathf.RoundToInt(MaxSize / StepSize);
idx = Mathf.RoundToInt(Plugin.TimeScale / StepSize) - 1;
_indexOffset = Plugin.NoFail ? 1 : 20;
numberOfElements = Mathf.RoundToInt(Plugin.MaxSize / Plugin.StepSize) - _indexOffset;
idx = Mathf.RoundToInt(Plugin.TimeScale / Plugin.StepSize) - _indexOffset;
}

protected override void ApplyValue(int idx)
Expand All @@ -23,8 +20,8 @@ protected override void ApplyValue(int idx)

protected override string TextForValue(int idx)
{
Plugin.TimeScale = StepSize * (idx + 1);
return StepSize * 100f * (idx + 1) + "%";
Plugin.TimeScale = Plugin.StepSize * (idx + _indexOffset);
return Plugin.StepSize * 100f * (idx + _indexOffset) + "%";
}
}
}
4 changes: 1 addition & 3 deletions PracticePlugin/SpeedSettingsCreator.cs
@@ -1,5 +1,4 @@
using System;
using UnityEngine;
using UnityEngine;

namespace PracticePlugin
{
Expand All @@ -9,7 +8,6 @@ public class SpeedSettingsCreator : MonoBehaviour

private void OnEnable()
{
if (!Plugin.Enabled) return;
_speedSettings = Instantiate(Plugin.SettingsObject, transform);
_speedSettings.SetActive(true);
_speedSettings.GetComponent<SpeedSettingsController>().Init();
Expand Down

0 comments on commit dd72a62

Please sign in to comment.