Skip to content

Commit

Permalink
A whole slew of track logic fixes (YARC-Official#399)
Browse files Browse the repository at this point in the history
* Fix duplicate drums track events from .mid charts

* Rework how chart events are processed
Fixes various events getting overwritten when the next comes into the time window

* Add named properties for common track time calculations
Also renamed RelativeTime to be more clear about what it actually is
One behavioral change was made:
- Solos now get started at the start of the hit window instead of the center

* Simplify Brutal Mode vanish distance calculation

* Fix solo box fadeout not getting cancelled properly when a new solo starts

* Don't lerp vocals needle if no voice was detected previously

* Handle beatlines in AbstractTrack

* Don't set regular note sustain material properties on open notes

* Fix SP note coloring not always being correct
Sustains at the end of SP phrases would not be colored correctly
  • Loading branch information
TheNathannator authored May 31, 2023
1 parent b425834 commit 82dce2f
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 282 deletions.
5 changes: 4 additions & 1 deletion Assets/Script/Input/MicInputStrategy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public sealed class MicInputStrategy : InputStrategy {

private float updateTimer;

private float previousDbCache;
private float dbCache;

private float pitchCache;
Expand All @@ -44,6 +45,7 @@ public sealed class MicInputStrategy : InputStrategy {
private (float, int) noteCache;

public bool VoiceDetected => dbCache >= 0f;
public bool VoiceDetectedThisFrame => dbCache >= 0f && previousDbCache < 0f;

public float TimeSinceNoVoice { get; private set; }
public float TimeSinceVoiceDetected { get; private set; }
Expand Down Expand Up @@ -99,6 +101,7 @@ protected override void OnUpdate() {
}

// Decibels //
previousDbCache = dbCache;

// Get the root mean square
float sum = 0f;
Expand All @@ -119,7 +122,6 @@ protected override void OnUpdate() {
// Only update pitch if a voice is detected
if (dbCache < 0f) {
TimeSinceVoiceDetected = 0f;

TimeSinceNoVoice += Time.deltaTime;
return;
} else {
Expand Down Expand Up @@ -264,6 +266,7 @@ protected override void UpdateBotMode() {
}

// Set info based on lyric
previousDbCache = dbCache;
if (botLyricInfo == null) {
dbCache = -1f;
TimeSinceNoVoice += Time.deltaTime;
Expand Down
128 changes: 99 additions & 29 deletions Assets/Script/PlayMode/AbstractTrack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
using System.Collections.Generic;
using Unity.Mathematics;
using UnityEngine;
using YARG.Chart;
using YARG.Data;
using YARG.Input;
using YARG.Pools;
using YARG.Settings;
using YARG.UI;

Expand All @@ -12,37 +14,54 @@ public abstract class AbstractTrack : MonoBehaviour {
public const float TRACK_SPAWN_OFFSET = 3f;
public const float TRACK_END_OFFSET = 1.95f;

public delegate void StarpowerMissAction();
public delegate void StarpowerMissAction(EventInfo missedPhrase);
public event StarpowerMissAction StarpowerMissEvent;

[SerializeField]
protected Pool genericPool;

public PlayerManager.Player player;
public float RelativeTime => Play.Instance.SongTime +

// Time values

// Convenience name for current song time
public float CurrentTime => Play.Instance.SongTime;
// Time relative to the start of the hit window
public float HitMarginStartTime => Play.Instance.SongTime + Constants.HIT_MARGIN;
// Time relative to the end of the hit window
public float HitMarginEndTime => Play.Instance.SongTime - Constants.HIT_MARGIN;
// Time relative to the beginning of the track, used for spawning notes and other visuals
public float TrackStartTime => Play.Instance.SongTime +
((TRACK_SPAWN_OFFSET + TRACK_END_OFFSET) / (player.trackSpeed / Play.speed));

protected List<NoteInfo> Chart => Play.Instance.chart
.GetChartByName(player.chosenInstrument)[(int) player.chosenDifficulty];

// Track notes
protected int visualChartIndex = 0;
protected int inputChartIndex = 0;
protected int hitChartIndex = 0;
protected int eventChartIndex = 0;
protected int beatChartIndex = 0;
protected int currentBeatIndex = 0;

protected CommonTrack commonTrack;
protected TrackAnimations trackAnims;

public EventInfo StarpowerSection {
get;
protected set;
} = null;
public EventInfo SoloSection {
get;
protected set;
} = null;
public EventInfo FillSection {
get;
protected set;
} = null;
// Track events
protected List<EventInfo> starpowerSections = new();
protected int starpowerIndex = 0;
protected int starpowerVisualIndex = 0;
public EventInfo CurrentStarpower =>
starpowerIndex < starpowerSections.Count ? starpowerSections[starpowerIndex] : null;
public EventInfo CurrentVisualStarpower =>
starpowerVisualIndex < starpowerSections.Count ? starpowerSections[starpowerVisualIndex] : null;

protected List<EventInfo> soloSections = new();
protected int soloIndex = 0;
protected int soloVisualIndex = 0;
public EventInfo CurrentSolo =>
soloIndex < soloSections.Count ? soloSections[soloIndex] : null;
public EventInfo CurrentVisualSolo =>
soloVisualIndex < soloSections.Count ? soloSections[soloVisualIndex] : null;

protected int notesHit = 0;
// private int notesMissed = 0;
Expand Down Expand Up @@ -94,9 +113,13 @@ protected int Combo {
}

// End starpower if combo ends
if (StarpowerSection?.time <= Play.Instance.SongTime && value == 0) {
StarpowerSection = null;
StarpowerMissEvent?.Invoke();
if (CurrentStarpower?.time <= CurrentTime && value == 0) {
StarpowerMissEvent?.Invoke(CurrentStarpower);
// Only move to the next visual phrase if it is also the current logical phrase
if (starpowerVisualIndex == starpowerIndex) {
starpowerVisualIndex++;
}
starpowerIndex++;
}
}
}
Expand Down Expand Up @@ -190,6 +213,18 @@ private void Start() {
intervalSize = commonTrack.noteStreakInterval;
halfIntervalSize = intervalSize / 2;

// Queue up events
string spName = $"starpower_{player.chosenInstrument}";
string soloName = $"solo_{player.chosenInstrument}";
string fillName = $"fill_{player.chosenInstrument}";
foreach (var eventInfo in Play.Instance.chart.events) {
if (eventInfo.name == spName) {
starpowerSections.Add(eventInfo);
} else if (eventInfo.name == soloName) {
soloSections.Add(eventInfo);
}
}

StartTrack();
}

Expand Down Expand Up @@ -232,8 +267,16 @@ private void Update() {
return;
}

// Progress visual SP phrases
// This is placed here instead of UpdateStarpower() since it causes visual issues otherwise
// TODO: Tracks need to be refactored to address that
while (CurrentVisualStarpower?.EndTime < TrackStartTime) {
starpowerVisualIndex++;
}

UpdateMaterial();

UpdateBeats();
UpdateTrack();

if (hitChartIndex > lastHit) {
Expand Down Expand Up @@ -281,6 +324,22 @@ private void UpdateFullComboState() {
}
}

private void UpdateBeats()
{
var beats = Play.Instance.chart.beats;
while (beats.Count > currentBeatIndex && beats[currentBeatIndex].Time <= TrackStartTime) {
var beatInfo = beats[currentBeatIndex];

float compensation = TRACK_SPAWN_OFFSET - CalcLagCompensation(TrackStartTime, beatInfo.Time);
if (beatInfo.Style is BeatStyle.STRONG or BeatStyle.WEAK) {
genericPool.Add("beatLine_minor", new(0f, 0.01f, compensation));
} else if (beatInfo.Style == BeatStyle.MEASURE) {
genericPool.Add("beatLine_major", new(0f, 0.01f, compensation));
}
currentBeatIndex++;
}
}

protected abstract void UpdateTrack();

private void UpdateMaterial() {
Expand All @@ -307,7 +366,7 @@ private void UpdateMaterial() {
}

float currentSolo = trackMaterial.GetFloat("SoloState");
if (Play.Instance.SongTime >= SoloSection?.time - 2 && Play.Instance.SongTime <= SoloSection?.EndTime - 1) {
if (CurrentTime >= CurrentSolo?.time - 2 && CurrentTime <= CurrentSolo?.EndTime - 1) {
trackMaterial.SetFloat("SoloState", Mathf.Lerp(currentSolo, 1f, Time.deltaTime * 2f));
} else {
trackMaterial.SetFloat("SoloState", Mathf.Lerp(currentSolo, 0f, Time.deltaTime * 2f));
Expand All @@ -334,7 +393,7 @@ private void UpdateMaterial() {
private void UpdateStarpower() {
// Update starpower region
if (IsStarpowerHit()) {
StarpowerSection = null;
starpowerIndex++;
starpowerCharge += 0.25f;
if (starpowerCharge > 1f) {
starpowerCharge = 1f;
Expand Down Expand Up @@ -387,6 +446,11 @@ private void UpdateStarpower() {
commonTrack.comboBase.material = commonTrack.baseNormal;
}
}

// Clear out passed SP phrases
while (CurrentStarpower?.EndTime < HitMarginEndTime) {
starpowerIndex++;
}
}

private void PauseAction() {
Expand All @@ -404,7 +468,7 @@ private void UpdateInfo() {
}

// Set solo box and text
if (Play.Instance.SongTime >= SoloSection?.time && Play.Instance.SongTime <= SoloSection?.EndTime + Constants.HIT_MARGIN) {
if (CurrentSolo?.time <= HitMarginStartTime && CurrentSolo?.EndTime >= HitMarginEndTime) {
if (!soloInProgress) {
soloInProgress = true;
soloNotesHit = 0;
Expand All @@ -416,7 +480,7 @@ private void UpdateInfo() {
continue;
}

if (Chart[i].time > SoloSection?.EndTime) {
if (Chart[i].time > CurrentSolo?.EndTime) {
break;
}

Expand Down Expand Up @@ -451,7 +515,7 @@ private void UpdateInfo() {

soloInProgress = false;
}
// } else if (Play.Instance.SongTime >= SoloSection?.EndTime && Play.Instance.SongTime <= SoloSection?.EndTime + 3) {
// } else if (HitMarginEndTime >= SoloSection?.EndTime && HitWindowEndTime <= SoloSection?.EndTime + 3) {
// // run ONCE
// if (soloInProgress) {
// soloPtsEarned = scoreKeeper.AddSolo(soloNotesHit, soloNoteCount);
Expand Down Expand Up @@ -562,7 +626,7 @@ private void UpdateInfo() {
// Deteremine behavior based on whether or not FC trumps SF
if (commonTrack.fullComboTrumpsStrongFinish) {
if (!strongFinishChecked) {
if (Play.Instance.SongTime > endTime) {
if (CurrentTime > endTime) {
strongFinishChecked = true;

if (FullCombo) {
Expand All @@ -574,7 +638,7 @@ private void UpdateInfo() {
}
} else {
if (!fullComboChecked) {
if (Play.Instance.SongTime > endTime) {
if (CurrentTime > endTime) {
fullComboChecked = true;

if (FullCombo) {
Expand All @@ -587,7 +651,7 @@ private void UpdateInfo() {
if (!strongFinishChecked) {
float checkTime = FullCombo ? offsetEndTime : endTime;

if (Play.Instance.SongTime > checkTime) {
if (CurrentTime > checkTime) {
strongFinishChecked = true;

if (_combo >= commonTrack.strongFinishCutoff) {
Expand All @@ -604,6 +668,13 @@ private void UpdateInfo() {
recentlyBelowMaxMultiplier = Multiplier < MaxMultiplier;
recentStarpowerCharge = starpowerCharge;

// Clear out passed solo sections
while (CurrentSolo?.EndTime < HitMarginEndTime) {
soloIndex++;
}
while (CurrentVisualSolo?.EndTime < TrackStartTime) {
soloVisualIndex++;
}
}

IEnumerator SoloBoxShowScore() {
Expand All @@ -629,8 +700,7 @@ protected float CalcLagCompensation(float currentTime, float noteTime) {

private bool IsStarpowerHit() {
if (Chart.Count > hitChartIndex) {

return Chart[hitChartIndex].time >= StarpowerSection?.EndTime;
return Chart[hitChartIndex].time >= CurrentStarpower?.EndTime;
}

return false;
Expand Down
Loading

0 comments on commit 82dce2f

Please sign in to comment.