diff --git a/src/Course.cpp b/src/Course.cpp index 73528353e0..8b291d7b6a 100644 --- a/src/Course.cpp +++ b/src/Course.cpp @@ -404,6 +404,9 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail ) trail.Init(); // XXX: Why are beginner and challenge excluded here? -Wolfman2000 + // No idea, probably an obsolete design decision from ITG, removing + // exclusion here, but there's some other area that prevents it too. -Kyz + /* switch( cd ) { case Difficulty_Beginner: @@ -412,6 +415,7 @@ bool Course::GetTrailUnsorted( StepsType st, CourseDifficulty cd, Trail &trail ) return false; default: break; } + */ // Construct a new Trail, add it to the cache, then return it. // Different seed for each course, but the same for the whole round: @@ -848,9 +852,9 @@ bool Course::CourseHasBestOrWorst() const { FOREACH_CONST( CourseEntry, m_vEntries, e ) { - if( e->iChooseIndex == SongSort_MostPlays && e->iChooseIndex != -1 ) + if( e->songSort == SongSort_MostPlays && e->iChooseIndex != -1 ) return true; - if( e->iChooseIndex == SongSort_FewestPlays && e->iChooseIndex != -1 ) + if( e->songSort == SongSort_FewestPlays && e->iChooseIndex != -1 ) return true; } diff --git a/src/GameState.cpp b/src/GameState.cpp index eb993a701e..370cdb6ef3 100644 --- a/src/GameState.cpp +++ b/src/GameState.cpp @@ -2109,6 +2109,11 @@ Difficulty GameState::GetHardestStepsDifficulty() const return dc; } +void GameState::SetNewStageSeed() +{ + m_iStageSeed= rand(); +} + bool GameState::IsEventMode() const { return m_bTemporaryEventMode || PREFSMAN->m_bEventMode; diff --git a/src/GameState.h b/src/GameState.h index 3b6bf60345..3c463e0e69 100644 --- a/src/GameState.h +++ b/src/GameState.h @@ -117,6 +117,8 @@ public: int m_iGameSeed, m_iStageSeed; RString m_sStageGUID; + void SetNewStageSeed(); + /** * @brief Determine if a second player can join in at this time. * @return true if a player can still enter the game, false otherwise. */ diff --git a/src/ScreenGameplay.cpp b/src/ScreenGameplay.cpp index aff5d2b36a..2c1a96e36e 100644 --- a/src/ScreenGameplay.cpp +++ b/src/ScreenGameplay.cpp @@ -2618,6 +2618,72 @@ void ScreenGameplay::HandleScreenMessage( const ScreenMessage SM ) pi->m_pLifeMeter->OnSongEnded(); } + // If this is a repeating course, and we're at the end of it, repick and + // add new songs to the players' step and song queues. + if(GAMESTATE->IsCourseMode() && GAMESTATE->m_pCurCourse && + GAMESTATE->m_pCurCourse->m_bRepeat && + GAMESTATE->GetCourseSongIndex() >= (int)m_apSongsQueue.size()-1) + { + Course* course= GAMESTATE->m_pCurCourse; + ASSERT(course != NULL); + // Need to store these so they can be used to refetch the players' + // trails after they're invalidated. + vector trail_sts; + vector trail_cds; + FOREACH_EnabledPlayerInfo(m_vPlayerInfo, pi) + { + Trail* trail= GAMESTATE->m_pCurTrail[pi->GetStepsAndTrailIndex()]; + ASSERT(trail != NULL); + trail_sts.push_back(trail->m_StepsType); + trail_cds.push_back(trail->m_CourseDifficulty); + } + // Set a new stage seed so the order will be different. + GAMESTATE->SetNewStageSeed(); + course->InvalidateTrailCache(); + course->RegenerateNonFixedTrails(); + size_t info_id= 0; // Can't use the player number in the playerinfo + // because it won't match up in 2-player. + FOREACH_EnabledPlayerInfo(m_vPlayerInfo, pi) + { + Trail* trail= course->GetTrail(trail_sts[info_id], trail_cds[info_id]); + ASSERT(trail != NULL); + GAMESTATE->m_pCurTrail[pi->m_pn].Set(trail); + ++info_id; + } + PlayerNumber master_pn = GAMESTATE->GetMasterPlayerNumber(); + Trail *master_trail= GAMESTATE->m_pCurTrail[master_pn]; + ASSERT(master_trail != NULL); + FOREACH_CONST(TrailEntry, master_trail->m_vEntries, entry) + { + ASSERT(entry->pSong != NULL); + m_apSongsQueue.push_back(entry->pSong); + STATSMAN->m_CurStageStats.m_vpPossibleSongs.push_back(entry->pSong); + } + FOREACH_EnabledPlayerInfo(m_vPlayerInfo, pi) + { + Trail* trail= GAMESTATE->m_pCurTrail[pi->GetStepsAndTrailIndex()]; + ASSERT(trail != NULL); + FOREACH_CONST(TrailEntry, trail->m_vEntries, entry) + { + ASSERT(entry->pSteps != NULL); + pi->m_vpStepsQueue.push_back(entry->pSteps); + AttackArray a; + entry->GetAttackArray(a); + pi->m_asModifiersQueue.push_back(a); + pi->GetPlayerStageStats()->m_vpPossibleSteps.push_back(entry->pSteps); + } + // In a survival course, override stored mods + if(course->GetCourseType() == COURSE_TYPE_SURVIVAL && + SURVIVAL_MOD_OVERRIDE) + { + pi->GetPlayerState()->m_PlayerOptions.FromString(ModsLevel_Stage, + "clearall," + CommonMetrics::DEFAULT_NOTESKIN_NAME.GetValue() + + "," + CommonMetrics::DEFAULT_MODIFIERS.GetValue()); + pi->GetPlayerState()->RebuildPlayerOptionsFromActiveAttacks(); + } + } + } + GAMESTATE->m_bLoadingNextSong = true; MESSAGEMAN->Broadcast( "BeforeLoadingNextCourseSong" ); m_NextSong.Reset();