Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions NoSwingLossCounter/BSML/Settings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ public bool excludeDottedLink
set => PluginConfig.Instance.excludeDottedLink = value;
}

[UIValue("normaliseArrowedLink")]
public bool normaliseArrowedLink
[UIValue("excludeMultiplier")]
public bool excludeMultiplier
{
get => PluginConfig.Instance.normaliseArrowedLink;
set => PluginConfig.Instance.normaliseArrowedLink = value;
get => PluginConfig.Instance.excludeMultiplier;
set => PluginConfig.Instance.excludeMultiplier = value;
}
}
}
8 changes: 4 additions & 4 deletions NoSwingLossCounter/BSML/View.bsml
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
hover-hint="Exclude dotted link (tail) on chain notes from accuracy percentage calculation"
apply-on-change="true"
/>
<checkbox-setting
text="Assume normal note on arrowed chain notes"
value="normaliseArrowedLink"
hover-hint="Treats arrowed link (head) on chain notes as normal note, hence calculates accuracy on base 115 instead of 85"
<checkbox-setting
text="Exclude multiplier"
value="excludeMultiplier"
hover-hint="Exclude multiplier on swing percentage calculation"
apply-on-change="true"
/>
</vertical>
6 changes: 3 additions & 3 deletions NoSwingLossCounter/Configuration/PluginConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ namespace NoSwingLossCounter.Configuration
class PluginConfig
{
public static PluginConfig Instance { get; set; }
public virtual bool separateSaber { get; set; } = false;
public virtual bool excludeDottedLink { get; set; } = false;
public virtual bool normaliseArrowedLink { get; set; } = false;
public virtual bool separateSaber { get; set; } = true;
public virtual bool excludeDottedLink { get; set; } = false;
public virtual bool excludeMultiplier { get; set; } = false;
}
}
77 changes: 29 additions & 48 deletions NoSwingLossCounter/NoSwingLossCounter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,21 @@ class NoSwingLossCounter : BasicCustomCounter
private TMP_Text _rightText;
private TMP_Text _bottomText;

private readonly ScoreController scoreController;
private readonly NoSwingLossCalculator calculator;

public NoSwingLossCounter(
[Inject] ScoreController scoreController
)
{
this.scoreController = scoreController;
this.calculator = new NoSwingLossCalculator();
}
[Inject] private readonly ScoreController _scoreController;
private NoSwingLossCalculator _calculator;

public override void CounterInit()
{
// Instantiate new calculator when initialising counter
_calculator = new NoSwingLossCalculator();
LabelInit();

scoreController.scoringForNoteFinishedEvent += ScoringForNoteFinishedEvent;
_scoreController.scoringForNoteFinishedEvent += ScoringForNoteFinishedEvent;
}

public override void CounterDestroy()
{
scoreController.scoringForNoteFinishedEvent -= ScoringForNoteFinishedEvent;
_scoreController.scoringForNoteFinishedEvent -= ScoringForNoteFinishedEvent;
}

private void LabelInit()
Expand Down Expand Up @@ -82,19 +76,19 @@ private void RefreshText()
{
if (PluginConfig.Instance.separateSaber)
{
_leftText.text = FormatToPercentage(calculator.PercentageA);
_rightText.text = FormatToPercentage(calculator.PercentageB);
_bottomText.text = FormatToPercentageBottomText(calculator.Percentage);
_leftText.text = FormatToPercentage(_calculator.PercentageA);
_rightText.text = FormatToPercentage(_calculator.PercentageB);
_bottomText.text = FormatToPercentageBottomText(_calculator.Percentage);
}
else
{
_bottomText.text = FormatToPercentage(calculator.Percentage);
_bottomText.text = FormatToPercentage(_calculator.Percentage);
}
}

private void ScoringForNoteFinishedEvent (ScoringElement scoringElement)
{
calculator.AddScore(scoringElement);
_calculator.AddScore(scoringElement);
RefreshText();
}
}
Expand All @@ -119,7 +113,9 @@ public void AddScore(ScoringElement scoringElement)
{
NoteData.ScoringType scoringType = scoringElement.noteData.scoringType;
ColorType colorType = scoringElement.noteData.colorType;
int multiplier = scoringElement.multiplier;

// Ignore multiplier if excludeMultiplier is true
int multiplier = PluginConfig.Instance.excludeMultiplier ? 1 : scoringElement.multiplier;

if (scoringType == NoteData.ScoringType.BurstSliderElement && PluginConfig.Instance.excludeDottedLink)
{
Expand All @@ -132,6 +128,8 @@ public void AddScore(ScoringElement scoringElement)
{
int fullSwingCutScore = 0;

ScoreModel.NoteScoreDefinition scoring = ScoreModel.GetNoteScoreDefinition(scoringType);

// BurstSliderHead only cares about preswing and accuracy (total points = 85)
// BurstSliderElement has 20 points each
// SliderHead does not care about postswing (total points = 115)
Expand All @@ -141,24 +139,12 @@ public void AddScore(ScoringElement scoringElement)
case NoteData.ScoringType.Normal:
case NoteData.ScoringType.SliderHead:
case NoteData.ScoringType.SliderTail:
fullSwingCutScore =
(100 + goodCutScoringElement.cutScoreBuffer.centerDistanceCutScore) * multiplier;
break;
case NoteData.ScoringType.BurstSliderHead:
if (!PluginConfig.Instance.normaliseArrowedLink)
{
fullSwingCutScore =
(70 + goodCutScoringElement.cutScoreBuffer.centerDistanceCutScore) * multiplier;
}
else
{
// Assume postswing exists on chain head since it is treated as normal note
fullSwingCutScore =
(100 + goodCutScoringElement.cutScoreBuffer.centerDistanceCutScore) * multiplier;
}
fullSwingCutScore =
(scoring.maxBeforeCutScore + scoring.maxAfterCutScore + goodCutScoringElement.cutScoreBuffer.centerDistanceCutScore) * multiplier;
break;
case NoteData.ScoringType.BurstSliderElement:
fullSwingCutScore = 20 * multiplier;
fullSwingCutScore = scoring.fixedCutScore * multiplier;
break;
}

Expand Down Expand Up @@ -191,26 +177,21 @@ private void AddMaxScore(NoteData.ScoringType scoringType, ColorType colorType)

int multiplier = 8;

// Only check if NoteCount is less than notecount on FC maximum multiplier
if (NoteCount < 14)
if (PluginConfig.Instance.excludeMultiplier)
{
multiplier = 1;

} else {
// TODO: check if there is any other way to obtain multiplier
// Only check if NoteCount is less than notecount on FC maximum multiplier
if (NoteCount == 1) multiplier = 1;
else if (NoteCount < 6) multiplier = 2;
else multiplier = 4;
else if (NoteCount < 14) multiplier = 4;
else multiplier = 8;
}

int maxScoreOnScoreType = 115;

switch (scoringType)
{
case NoteData.ScoringType.BurstSliderHead:
// Max score is 85 if arrowed link is not treated as normal note
if (!PluginConfig.Instance.normaliseArrowedLink) maxScoreOnScoreType = 85;
break;
case NoteData.ScoringType.BurstSliderElement:
maxScoreOnScoreType = 20;
break;
}
ScoreModel.NoteScoreDefinition scoring = ScoreModel.GetNoteScoreDefinition(scoringType);
int maxScoreOnScoreType = scoring.maxCutScore;

int maxScore = maxScoreOnScoreType * multiplier;

Expand Down
31 changes: 22 additions & 9 deletions NoSwingLossCounter/NoSwingLossCounter.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -41,19 +41,28 @@
<DisableZipRelease>True</DisableZipRelease>
</PropertyGroup>
<ItemGroup>
<Reference Include="BeatmapCore, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL" />
<Reference Include="BeatmapCore">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\BeatmapCore.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="GameplayCore, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
<Reference Include="IPA.Loader">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll</HintPath>
<Private>False</Private>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="BSML" >
<Reference Include="BSML">
<HintPath>$(BeatSaberDir)\Plugins\BSML.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Counters+" >
<Reference Include="Counters+">
<HintPath>$(BeatSaberDir)\Plugins\Counters+.dll</HintPath>
<Private>False</Private>
</Reference>
Expand All @@ -69,10 +78,6 @@
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\HMUI.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="IPA.Loader">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Unity.TextMeshPro">
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll</HintPath>
<Private>False</Private>
Expand Down Expand Up @@ -101,8 +106,16 @@
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.VRModule.dll</HintPath>
<Private>False</Private>
</Reference>
<Reference Include="Zenject, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL" />
<Reference Include="Zenject-usage, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL" />
<Reference Include="Zenject, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<Private>False</Private>
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\Zenject.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
<Reference Include="Zenject-usage, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<Private>False</Private>
<HintPath>$(BeatSaberDir)\Beat Saber_Data\Managed\Zenject-usage.dll</HintPath>
<SpecificVersion>False</SpecificVersion>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="BSML\Settings.cs" />
Expand Down
1 change: 0 additions & 1 deletion NoSwingLossCounter/Plugin.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using IPA;
using IPALogger = IPA.Logging.Logger;
using IPA.Config.Stores;
using Zenject;
using NoSwingLossCounter.Configuration;

namespace NoSwingLossCounter
Expand Down
6 changes: 3 additions & 3 deletions NoSwingLossCounter/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("NoSwingLossCounter")]
[assembly: AssemblyCopyright("Copyright © 2022 DaftMaple")]
[assembly: AssemblyCopyright("Copyright © 2025 DaftMaple")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

Expand All @@ -32,5 +32,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.1")]
[assembly: AssemblyFileVersion("1.0.1")]
[assembly: AssemblyVersion("1.0.2")]
[assembly: AssemblyFileVersion("1.0.2")]
2 changes: 1 addition & 1 deletion NoSwingLossCounter/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "NoSwingLossCounter",
"name": "NoSwingLossCounter",
"author": "DaftMaple",
"version": "1.0.1",
"version": "1.0.2",
"description": "CountersPlus custom counter for No Swing Loss Percentage",
"gameVersion": "1.20.0",
"dependsOn": {
Expand Down
33 changes: 28 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,35 @@ This mod also supports split value for each hands which can be configured on Cou

## Counters options

| Option | Description |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| Separate Saber | Shows no swing loss accuracy percentage for each saber (shown as separate value) |
| Exclude dotted chain notes | Excludes dotted chain notes (tail) from accuracy percentage calculation |
| Assume normal note on arrowed chain notes | Treats arrowed chain notes (head) as normal note, hence it has assumed postswing (treated as a note with maximum accuracy of 115 instead of 85). |
| Option | Description |
| -------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| Separate Saber | Shows no swing loss accuracy percentage for each saber (shown as separate value) |
| Exclude dotted chain notes | Excludes dotted chain notes (tail) from accuracy percentage calculation |
| Exclude multiplier on swing percentage calculation | Exclude multiplier on notes on higher multiplier (x2, x4, x8 are weighted equally as x1 if this is true) |

## Development

- Install Visual Studio 2022
- Add modding tools: https://github.com/Zingabopp/BeatSaberModdingTools/wiki/How-to-Download-and-Install
- You may use latest version of BeatSaberModdingTools here: https://github.com/denpadokei/BeatSaberModdingTools/releases

## Bug or feature request

[Go here](https://github.com/daftmaple/NoSwingLoss/issues/new/choose)

## Changelog

v1.0.2

- Removed arrowed chain notes normalisation
- Added support for different scoring model
- Added toggle for multiplier exclusion on calculating max score
- Set separate saber setting to default to true

v1.0.1

- Support for link & chain notes

v1.0.0

- Initial project