Skip to content

Commit

Permalink
fix replay playback being wrong for dupe cks with different offsets
Browse files Browse the repository at this point in the history
this isnt really a fix but it puts a giant bandaid on the issue. we could probably use the replay songoffset but i didnt feel like it
  • Loading branch information
poco0317 committed Jan 9, 2023
1 parent 9addca6 commit 7572298
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 7 deletions.
83 changes: 82 additions & 1 deletion src/Etterna/Actor/Gameplay/PlayerReplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,61 @@ PlayerReplay::Update(float fDeltaTime)
UpdateTapNotesMissedOlderThan(GetMaxStepDistanceSeconds());
}

void
PlayerReplay::SetPlaybackEvents(
const std::map<int, std::vector<PlaybackEvent>>& v)
{
playbackEvents.clear();

std::vector<PlaybackEvent> ghostTaps{};
auto gapError = 0.F;

auto musicRate = REPLAYS->GetActiveReplay()->GetMusicRate();

for (auto& p : v) {
auto noterow = p.first;
auto& evts = p.second;

auto rowpos = m_Timing->GetElapsedTimeFromBeat(NoteRowToBeat(noterow));
for (auto& evt : evts) {
auto supposedTime = evt.songPositionSeconds;

if (evt.noterowJudged == -1) {
ghostTaps.push_back(evt);
continue;
}

// discrepancy in notedata/timing from actual replay
// must update row and time to match current chart
if (fabsf(rowpos - supposedTime) > 0.01F) {
// haha oh my god
noterow = BeatToNoteRow(m_Timing->GetBeatFromElapsedTime(
m_Timing->GetElapsedTimeFromBeat(
NoteRowToBeat(evt.noterowJudged)) +
(evt.offset * musicRate)));
gapError = rowpos - supposedTime;
}

if (playbackEvents.count(noterow) == 0u) {
playbackEvents.emplace(noterow, std::vector<PlaybackEvent>());
}
playbackEvents.at(noterow).push_back(evt);
}
}

// handle ghost taps last because we didnt have enough data to fix gaps
for (auto& evt : ghostTaps) {
auto time =
m_Timing->GetElapsedTimeFromBeat(NoteRowToBeat(evt.noterow));
auto newrow =
BeatToNoteRow(m_Timing->GetBeatFromElapsedTime(time - gapError));
if (playbackEvents.count(newrow) == 0u) {
playbackEvents.emplace(newrow, std::vector<PlaybackEvent>());
}
playbackEvents.at(newrow).push_back(evt);
}
}

void
PlayerReplay::CheckForSteps(const std::chrono::steady_clock::time_point& tm)
{
Expand Down Expand Up @@ -332,10 +387,36 @@ PlayerReplay::CheckForSteps(const std::chrono::steady_clock::time_point& tm)
}

// execute all the events
for (PlaybackEvent evt : evts) {
for (const auto& evt : evts) {
if (evt.isPress) {
if (holdingColumns.contains(evt.track)) {
// it wont break the game, but we should track dupe presses
Locator::getLogger()->warn(
"Please report an issue with this replay: {} - press {}, row "
"{}, judgerow {}, time {}, col {}",
REPLAYS->GetActiveReplay()->GetScoreKey(),
evt.isPress,
evt.noterow,
evt.noterowJudged,
evt.songPositionSeconds,
evt.track);
}

holdingColumns.insert(evt.track);
} else {
if (!holdingColumns.contains(evt.track)) {
// it wont break the game, but we should track dupe releases
Locator::getLogger()->warn(
"Please report an issue with this replay: {} - press {}, row "
"{}, judgerow {}, time {}, col {}",
REPLAYS->GetActiveReplay()->GetScoreKey(),
evt.isPress,
evt.noterow,
evt.noterowJudged,
evt.songPositionSeconds,
evt.track);
}

holdingColumns.erase(evt.track);
}
Step(evt.track,
Expand Down
5 changes: 2 additions & 3 deletions src/Etterna/Actor/Gameplay/PlayerReplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ class PlayerReplay : public Player
std::map<int, std::vector<PlaybackEvent>>& GetPlaybackEvents() {
return playbackEvents;
}
void SetPlaybackEvents(const std::map<int, std::vector<PlaybackEvent>>& v) {
playbackEvents = v;
}
void SetPlaybackEvents(const std::map<int, std::vector<PlaybackEvent>>& v);

std::map<int, std::set<int>>& GetDroppedHolds() {
return droppedHolds;
}
Expand Down
6 changes: 3 additions & 3 deletions src/Etterna/Models/HighScore/Replay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2876,10 +2876,9 @@ Replay::GeneratePlaybackEvents(int startRow) -> std::map<int, std::vector<Playba
const auto& evtPositionSeconds = evt.songPositionSeconds;
const auto& column = evt.column;
const auto& isPress = evt.is_press;
const auto positionSeconds = evt.songPositionSeconds;

const auto noterow =
BeatToNoteRow(td->GetBeatFromElapsedTime(positionSeconds));
BeatToNoteRow(td->GetBeatFromElapsedTime(evtPositionSeconds));
if (evt.nearestTapNoterow < startRow) {
if (evt.nearestTapNoterow == -1) {
// for ghost taps, only remove them if they are truly too early
Expand All @@ -2892,8 +2891,9 @@ Replay::GeneratePlaybackEvents(int startRow) -> std::map<int, std::vector<Playba
}
}

PlaybackEvent playback(noterow, positionSeconds, column, isPress);
PlaybackEvent playback(noterow, evtPositionSeconds, column, isPress);
playback.noterowJudged = evt.nearestTapNoterow;
playback.offset = evt.offsetFromNearest;
if (!out.count(noterow)) {
out.emplace(noterow, std::vector<PlaybackEvent>());
}
Expand Down
1 change: 1 addition & 0 deletions src/Etterna/Models/HighScore/ReplayConstantsAndTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ struct PlaybackEvent
// only applies if the event judges a note
// to prevent events triggering wrong judgments
int noterowJudged = -1;
float offset = 0.F;

PlaybackEvent()
{
Expand Down

0 comments on commit 7572298

Please sign in to comment.