@@ -126,6 +126,7 @@ PlayerAI::SetScoreData(HighScore* pHighScore, int firstRow, NoteData* pNoteData)
126
126
127
127
// Generate vectors made of pregenerated HoldReplayResults referenced by the
128
128
// song row in a map
129
+ // Only present in replays with column data.
129
130
for (size_t i = 0 ; i < replayHoldVector.size (); i++) {
130
131
if (replayHoldVector[i].row < firstRow)
131
132
continue ;
@@ -151,7 +152,9 @@ PlayerAI::SetScoreData(HighScore* pHighScore, int firstRow, NoteData* pNoteData)
151
152
// We leave out misses in this section because they aren't in the Replay
152
153
// Data
153
154
int tempJudgments[NUM_TapNoteScore] = { 0 };
154
- int holdsDropped = 0 ;
155
+ int tempHNS[NUM_HoldNoteScore] = { 0 };
156
+
157
+ // Iterate over all the noterows we know are in the Replay Data
155
158
for (auto r = validNoterows.begin (); r != validNoterows.end (); r++) {
156
159
// Check for taps and mines
157
160
if (m_ReplayTapMap.count (*r) != 0 ) {
@@ -173,21 +176,24 @@ PlayerAI::SetScoreData(HighScore* pHighScore, int firstRow, NoteData* pNoteData)
173
176
for (auto instance = m_ReplayHoldMap[*r].begin ();
174
177
instance != m_ReplayHoldMap[*r].end ();
175
178
instance++) {
176
- holdsDropped ++;
179
+ tempHNS[HNS_LetGo] ++;
177
180
}
178
181
}
179
182
180
183
// Make the struct and cram it in there
181
184
ReplaySnapshot rs;
182
185
FOREACH_ENUM (TapNoteScore, tns)
183
- {
184
- rs.judgments [tns] = tempJudgments[tns];
185
- }
186
- rs.holdsDropped = holdsDropped;
186
+ rs.judgments [tns] = tempJudgments[tns];
187
+ FOREACH_ENUM (HoldNoteScore, hns)
188
+ rs.hns [hns] = tempHNS[hns];
187
189
m_ReplaySnapshotMap[*r] = rs;
188
190
}
189
191
190
- // Now handle misses.
192
+ // map tracks to rows that begin a hold
193
+ vector<int > tempHoldsByTrack;
194
+ tempHoldsByTrack.reserve (pNoteData->GetNumTracks ());
195
+
196
+ // Now handle misses and holds.
191
197
// For every row in notedata...
192
198
FOREACH_NONEMPTY_ROW_ALL_TRACKS (*pNoteData, row)
193
199
{
@@ -200,6 +206,18 @@ PlayerAI::SetScoreData(HighScore* pHighScore, int firstRow, NoteData* pNoteData)
200
206
pTN = &iter->second ;
201
207
202
208
if (iter != pNoteData->end (track)) {
209
+ // Deal with holds here
210
+ if (pTN->type == TapNoteType_HoldTail) {
211
+ int startrow = tempHoldsByTrack.at (track);
212
+ if (IsHoldDroppedInRowRangeForTrack (startrow, row, track)) {
213
+ tempHNS[HNS_LetGo]++;
214
+ } else {
215
+ tempHNS[HNS_Held]++;
216
+ }
217
+ } else if (pTN->type == TapNoteType_HoldHead) {
218
+ tempHoldsByTrack.at (track) = row;
219
+ }
220
+
203
221
// It is impossible to "miss" these notes
204
222
if (pTN->type == TapNoteType_Mine ||
205
223
pTN->type == TapNoteType_Fake ||
@@ -222,21 +240,22 @@ PlayerAI::SetScoreData(HighScore* pHighScore, int firstRow, NoteData* pNoteData)
222
240
}
223
241
}
224
242
}
225
- // We have to update every single row with the new miss counts.
243
+ // We have to update every single row with the new miss & hns counts.
226
244
// This unfortunately takes more time.
227
245
// If current row is recorded in the snapshots, update the miss count
228
246
if (m_ReplaySnapshotMap.count (row) != 0 ) {
229
247
m_ReplaySnapshotMap[row].judgments [TNS_Miss] =
230
248
tempJudgments[TNS_Miss];
249
+ FOREACH_ENUM (HoldNoteScore, hns)
250
+ m_ReplaySnapshotMap[row].hns [hns] = tempHNS[hns];
231
251
} else {
232
252
// If the current row is after the last recorded row, make a new one
233
253
if (m_ReplaySnapshotMap.rbegin ()->first < row) {
234
254
ReplaySnapshot rs;
235
255
FOREACH_ENUM (TapNoteScore, tns)
236
- {
237
- rs.judgments [tns] = tempJudgments[tns];
238
- }
239
- rs.holdsDropped = holdsDropped;
256
+ rs.judgments [tns] = tempJudgments[tns];
257
+ FOREACH_ENUM (HoldNoteScore, hns)
258
+ rs.hns [hns] = tempHNS[hns];
240
259
m_ReplaySnapshotMap[row] = rs;
241
260
}
242
261
// If the current row is before the earliest recorded row, make a
@@ -251,11 +270,9 @@ PlayerAI::SetScoreData(HighScore* pHighScore, int firstRow, NoteData* pNoteData)
251
270
ReplaySnapshot rs;
252
271
const int prev = m_ReplaySnapshotMap.lower_bound (row)->first ;
253
272
FOREACH_ENUM (TapNoteScore, tns)
254
- {
255
- rs.judgments [tns] =
256
- m_ReplaySnapshotMap[prev].judgments [tns];
257
- }
258
- rs.holdsDropped = m_ReplaySnapshotMap[prev].holdsDropped ;
273
+ rs.judgments [tns] = m_ReplaySnapshotMap[prev].judgments [tns];
274
+ FOREACH_ENUM (HoldNoteScore, hns)
275
+ rs.hns [hns] = m_ReplaySnapshotMap[prev].hns [hns];
259
276
m_ReplaySnapshotMap[row] = rs;
260
277
}
261
278
}
@@ -391,6 +408,35 @@ PlayerAI::DetermineIfHoldDropped(int noteRow, int col)
391
408
return false ;
392
409
}
393
410
411
+ bool
412
+ PlayerAI::IsHoldDroppedInRowRangeForTrack (int firstRow, int endRow, int track)
413
+ {
414
+ // 2 is a replay with column data
415
+ if (pScoreData->GetReplayType () == 2 ) {
416
+ // Go over all holds in Replay Data
417
+ for (auto hiter = m_ReplayHoldMap.lower_bound (firstRow);
418
+ hiter != m_ReplayHoldMap.end ();
419
+ hiter++) {
420
+ // If this row is before the start, skip it
421
+ if (hiter->first < firstRow)
422
+ continue ;
423
+ // If this row is after the end, skip it
424
+ else if (hiter->first > endRow)
425
+ return false ;
426
+ // This row might work. Check what tracks might have dropped.
427
+ for (auto hrr : hiter->second ) {
428
+ if (hrr.track == track)
429
+ return true ;
430
+ }
431
+ }
432
+ // Iteration finished without finding a drop.
433
+ return false ;
434
+ } else {
435
+ // Replay Data doesn't contain hold data.
436
+ return false ;
437
+ }
438
+ }
439
+
394
440
bool
395
441
PlayerAI::TapExistsAtThisRow (int noteRow)
396
442
{
0 commit comments