Skip to content

Commit

Permalink
add easy tap recovery, allow ghosting if no notes (#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphaelgoulart authored Apr 29, 2023
1 parent 248116d commit 53dcdce
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 16 deletions.
7 changes: 7 additions & 0 deletions Assets/Script/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ namespace YARG {
public static class Constants {
public static readonly YargVersion VERSION_TAG = YargVersion.Parse("v0.10.0b");

// General
public const float HIT_MARGIN = 0.095f;
// Guitar
public const float STRUM_LENIENCY = 0.065f;
public const bool ANCHORING = true;
public const bool INFINITE_FRONTEND = false;
public const bool ANCHOR_CHORD_HOPO = true;
public const bool EASY_TAP_RECOVERY = true;
// Guitar - Anti-ghosting
public const int EXTRA_ALLOWED_GHOSTS = 0;
public const bool ALLOW_DESC_GHOSTS = true;
public const bool ALLOW_GHOST_IF_NO_NOTES = true; // seems to allow more ghosting than it should...
public const float ALLOW_GHOST_IF_NO_NOTES_THRESHOLD = 1.5f;
}
}
78 changes: 62 additions & 16 deletions Assets/Script/PlayMode/FiveFretTrack.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ public class FiveFretTrack : AbstractTrack {
private int allowedGhosts = Constants.EXTRA_ALLOWED_GHOSTS + 1;
private int[] allowedChordGhosts = new int[] { -1, -1, -1, -1, -1 }; // -1 = not a chord; 0 = ghosted; 1 = ghost allowed
private bool antiGhosting = false;
private bool pressedThisFrame = false;

// https://www.reddit.com/r/Rockband/comments/51t3c0/exactly_how_many_points_are_sustains_worth/
private const double SUSTAIN_PTS_PER_BEAT = 12.0;
Expand Down Expand Up @@ -157,6 +158,7 @@ protected override void UpdateTrack() {

// Un-strum
strummed = false;
pressedThisFrame = false;
}

public override void SetReverb(bool on) {
Expand Down Expand Up @@ -200,7 +202,6 @@ private void UpdateInput() {
// Handle misses (multiple a frame in case of lag)
while (Play.Instance.SongTime - expectedHits.PeekOrNull()?[0].time > Constants.HIT_MARGIN) {
var missedChord = expectedHits.Dequeue();
allowedGhosts = allowedGhostsDefault;
ResetAllowedChordGhosts();
// Call miss for each component
Combo = 0;
Expand All @@ -226,11 +227,13 @@ private void UpdateInput() {
return;
}


bool returnLater = false;
// If the note is a HOPO, the player has not strummed, and the HOPO can't be hit, nothing happens.
if ((chord[0].hopo || chord[0].tap) && !strummed && strumLeniency == 0f) {
if ((Combo <= 0 && chord[0].hopo) || allowedGhosts <= 0) {
if (Combo <= 0 && chord[0].hopo) {
return;
} else if (allowedGhosts <= 0) {
returnLater = true;
}

// If infinite front-end window is disabled and the latest input is outside of the timing window, nothing happened.
Expand Down Expand Up @@ -276,9 +279,41 @@ private void UpdateInput() {
}
}
}
// If tapping to recover combo during tap note section, skip to first valid note within the timing window.
// This will make it easier to recover.
if (Constants.EASY_TAP_RECOVERY && Combo <= 0 && pressedThisFrame && chord[0].tap && !ChordPressed(chord)) {
var found = false;
foreach (var newChord in expectedHits) {
if (!newChord[0].tap) {
break;
}
// Stop looking if a valid note to tap was found
if (ChordPressed(newChord) && newChord[0].fret != 5) {
found = true;
returnLater = false;
chord = newChord;
break;
}
}

// If found...
if (found) {
// Miss all notes previous to the tapped note
while (expectedHits.Peek() != chord) {
var missedChord = expectedHits.Dequeue();
foreach (var hit in missedChord) {
hitChartIndex++;
notePool.MissNote(hit);
}
}

// Reset the combo (it will be added to later on)
Combo = 0;
}
}

// Check if correct chord is pressed
if (!ChordPressed(chord)) {
if (returnLater || !ChordPressed(chord)) {
// Overstrums are dealt with at the top of the method
return;
}
Expand All @@ -302,7 +337,6 @@ private void UpdateInput() {
// If correct chord is pressed, and is not a multi-hit, hit it!
expectedHits.Dequeue();

allowedGhosts = allowedGhostsDefault;
ResetAllowedChordGhosts();
Combo++;
strummedCurrentNote = strummedCurrentNote || strummed || strumLeniency > 0f;
Expand Down Expand Up @@ -506,24 +540,33 @@ protected override void PauseToggled(bool pause) {
private void FretChangedAction(bool pressed, int fret) {
latestInput = Play.Instance.SongTime;
latestInputIsStrum = false;
if (pressed) {
pressedThisFrame = true;
}

// Should it check ghosting?
if (antiGhosting && allowedGhosts > 0 && pressed && hitChartIndex > 0) {
bool checkGhosting = true;
for (var i = 0; i < 5; i++) {
if (i == fret) {
continue;
}
if (frets[i].IsPressed) {
if (fret < i) { // Don't check ghosting if pressed fret is below currently held fret
checkGhosting = false;
break;
if (Constants.ALLOW_DESC_GHOSTS) {
for (var i = 0; i < 5; i++) {
if (i == fret) {
continue;
}
if (frets[i].IsPressed) {
if (fret < i) { // Don't check ghosting if pressed fret is below currently held fret
checkGhosting = false;
break;
}
}
}
}
if (checkGhosting) {
var nextNote = GetNextNote(Chart[hitChartIndex - 1].time);
if (nextNote != null && (nextNote[0].hopo || nextNote[0].tap)) {
if ((nextNote == null || (!nextNote[0].hopo && !nextNote[0].tap)) ||
(Constants.ALLOW_GHOST_IF_NO_NOTES && nextNote[0].time - Play.Instance.SongTime > Constants.HIT_MARGIN * Constants.ALLOW_GHOST_IF_NO_NOTES_THRESHOLD)) {
checkGhosting = false;
}
if (checkGhosting) {
if (nextNote.Count == 1 && fret != nextNote[0].fret) { // Hitting wrong button = ghosted = bad
allowedGhosts--;
}
Expand Down Expand Up @@ -704,13 +747,16 @@ private List<NoteInfo> GetNextNote(float currentChordTime) {
}
}
} else {
ResetAllowedChordGhosts();
ResetAllowedChordGhosts(false);
}
return chord;
}
}

private void ResetAllowedChordGhosts() {
private void ResetAllowedChordGhosts(bool resetGhosts = true) {
if (resetGhosts) {
allowedGhosts = allowedGhostsDefault;
}
for (var i = 0; i < 5; i++) {
allowedChordGhosts[i] = -1;
}
Expand Down

0 comments on commit 53dcdce

Please sign in to comment.