/***************************************************************************** ** ** ** Neversoft Entertainment. ** ** ** ** Copyright (C) 2000 - All Rights Reserved ** ** ** ****************************************************************************** ** ** ** Project: skate3 ** ** ** ** Module: skate ** ** ** ** File name: competition.cpp ** ** ** ** Created by: 18/06/01 - Mick ** ** ** ** Description: handles playing single player competitions ** ** ** *****************************************************************************/ /***************************************************************************** ** Includes ** *****************************************************************************/ #include #include // for Mth::Rnd2() #include #include #include #include #include #include #include #include #include #include /***************************************************************************** ** DBG Information ** *****************************************************************************/ namespace Mdl { /***************************************************************************** ** Externals ** *****************************************************************************/ /***************************************************************************** ** Defines ** *****************************************************************************/ /***************************************************************************** ** Private Types ** *****************************************************************************/ /***************************************************************************** ** Private Data ** *****************************************************************************/ /***************************************************************************** ** Public Data ** *****************************************************************************/ /***************************************************************************** ** Private Prototypes ** *****************************************************************************/ /***************************************************************************** ** Private Functions ** *****************************************************************************/ /***************************************************************************** ** Public Functions ** *****************************************************************************/ CCompetition::CCompetition( Script::CStruct* pParams ) { mp_params = new Script::CStruct(); } CCompetition::~CCompetition() { } void CCompetition::EditParams( Script::CStruct* pParams ) { mp_params->AppendStructure( pParams ); } void CCompetition::ResetJudgement() { m_total_score = 0.0f; m_bail_points = 0.0f; } int CLeaderBoardEntry::GetTotalScore(int round) { int score1 = 0; int score2 = 0; for (int i=0;i score1) { score2 = score1; score1 = m_score[i]; } else if (m_score[i] > score2) { score2 = m_score[i]; } } return score1 + score2; } // start the competition, and pre-calculate all // the scores void CCompetition::StartCompetition(float bronze, float silver, float gold, float bronze_score, float silver_score, float gold_score, float bail) { // store the defining parameters m_bronze = bronze; m_silver = silver; m_gold = gold; m_bronze_score = bronze_score; m_silver_score = silver_score; m_gold_score = gold_score; m_bail = bail; m_end_competition = false; // Get the current profile Mdl::Skate * pSkate = Mdl::Skate::Instance(); Obj::CPlayerProfileManager* pPlayerProfileManager=pSkate->GetPlayerProfileManager(); Obj::CSkaterProfile* pSkaterProfile=pPlayerProfileManager->GetCurrentProfile(); // need to use GetDisplayName() wrapper function instead of GetUIString(), bec. ui string can now theoretically be empty m_leader_board[0].m_name = pSkaterProfile->GetDisplayName(); // Let's count how many pros there are, so we can pcik from them at random int possible_pros = pPlayerProfileManager->GetNumProfileTemplates(); // get an array of pros, except the one that has the same name as me int pro_order[100]; int num_pros = 0; for (int i = 0;iGetProfileTemplateByIndex(i); // printf ("Pro=%d, Secret = %d, name = %s",pProfile->IsPro(), pProfile->IsSecret(), pProfile->GetDisplayName()); if (!pProfile->IsPro() || pProfile->IsSecret() || Script::GenerateCRC(m_leader_board[0].m_name.getString()) == Script::GenerateCRC(pProfile->GetDisplayName())) { // skip over this one } else { pro_order[num_pros++] = i; } } // shuffle them for (int i = 0;i= gold) { silver = gold - 0.1f; } if (bronze >= silver) { bronze = silver - 0.1f; } // go through all remaining players, and fill in the blanks for (int i = 0;iGetArray( CRCD(0x1cc6f48d,"leader_board_names"), &pLeaderBoardNames, Script::NO_ASSERT ) ) { Dbg_MsgAssert( pLeaderBoardNames->GetSize() == vMAX_PLAYERS - 1, ( "leader_board_names has wrong size. Needs to be %i", vMAX_PLAYERS - 1 ) ); m_leader_board[player].m_name = pLeaderBoardNames->GetString( i ); } else m_leader_board[player].m_name = pPlayerProfileManager->GetProfileTemplate(pPlayerProfileManager->GetProfileTemplateChecksum(pro_order[i]))->GetDisplayName(); // now calculate the score float score = 0.0f; if (i == 0) score = gold; else if (i == 1) score = silver; else if (i == 2) score = bronze; else { // scores for the player after bronze are essentially any random number less than bronze score = bronze - (bronze/8) + Mth::PlusOrMinus(bronze/8); if (score >= bronze) { score = bronze - 0.1f; } } // now we have the total score, we calculate the random components that // will add up to that score // the final sore is calculated as the average of the best of two scores // So... calculate two scores that add up to twice the total score // then add a third that is less than both of these // and put these in random order // float score1 = score + Mth::PlusOrMinus(2.0f); float score2 = score*2.0f - score1; float lower = score1; if (score2 GetString( CRCD(0xfaf19012,"first_place_name"), &p_first_place_name, Script::NO_ASSERT ) ) { m_leader_board[0].m_name = p_first_place_name; } printf ("\nSorted\n"); // let up now print out the fruits of our efforts for (int i = 0;i 99.9f) m_total_score = 99.9f; // we calculate a "varience", which is the maximum amount // a score can be randomly varied // this ranges from 10 to 0 as the actual score goes from 0 to 99.9 float variance = ( 99.9f - m_total_score ) / 10.0f; // perform some initial varying by half the variance // to make the score seen more random m_total_score += Mth::PlusOrMinus(variance/2); // clamp it, just to be safe if (m_total_score > 99.9f) m_total_score = 99.9f; if (m_total_score < 0.0f) m_total_score = 0.0f; // and find the n Judges scores // here the final score is the average of the top three scores. // so we need to generate three scores that add up to the // total score m_score[0] = m_total_score + Mth::PlusOrMinus(variance); if (m_score[0] > 99.85f) m_score[0] = 99.9f; if (m_score[0] < 0.0f) m_score[0] = 0.0f; m_score[1] = m_total_score + Mth::PlusOrMinus(variance); if (m_score[1] > 99.85f) m_score[1] = 99.9f; if (m_score[1] < 0.0f) m_score[1] = 0.0f; m_score[2] = (m_total_score * 3.0f) - (m_score[0] + m_score[1]); if (m_score[2] < 0.0f) m_score[2] = 0.0f; if (m_score[2] > 99.85f) m_score[2] = 99.9f; m_score[0] = (float)( (int) (m_score[0] * 10.0f)) /10.0f + 0.0001f; m_score[1] = (float)( (int) (m_score[1] * 10.0f)) /10.0f + 0.0001f; m_score[2] = (float)( (int) (m_score[2] * 10.0f)) /10.0f + 0.0001f; m_score[0] = (int)Mth::Round(m_score[0]); m_score[1] = (int)Mth::Round(m_score[1]); m_score[2] = (int)Mth::Round(m_score[2]); if ( m_score[0] > 99 ) m_score[0] = 99; if ( m_score[1] > 99 ) m_score[1] = 99; if ( m_score[2] > 99 ) m_score[2] = 99; // recalculate the total score m_total_score = ((float)(m_score[0]) + (float)(m_score[1]) + (float)(m_score[2])) / 3; m_total_score = (int)Mth::Round( m_total_score ); if ( m_total_score > 99 ) m_total_score = 99; // m_judge_score[m_current_round] = (int)(10.0f * m_total_score + 0.5f); m_judge_score[m_current_round] = (int)m_total_score; printf ("3 scores are %f,%f,%f, total is %f\n",m_score[0],m_score[1],m_score[2],m_total_score); // Stick the total score in the correct place in the leaderboard for (i = 0;iIsInCompetition() ) { // and let us have a look at what we come up with; Script::CStruct* p_run_scores = new Script::CStruct(); // pack the scores in a carray to make them easy to deal with in script Script::CArray* p_run_scores_array = new Script::CArray(); p_run_scores_array->SetSizeAndType( vNUM_JUDGES, ESYMBOLTYPE_STRUCTURE ); printf( "\nJudgement Day\n\n" ); for ( i = 0; i < vNUM_JUDGES; i++ ) { // add an integer version of this score to the params, so it's // easy to deal with in script Script::CStruct* p_temp = new Script::CStruct(); p_temp->AddInteger( "score", (int)Mth::Round( m_score[i] ) ); // add a flag to the top judges if ( IsTopJudge( i ) ) { p_temp->AddChecksum( NONAME, CRCD( 0x7b1b959f, "top_judge" ) ); } p_run_scores_array->SetStructure( i, p_temp ); printf ("%d: %f Top=%d\n",i,m_score[i],IsTopJudge(i)); } p_run_scores->AddArray( "scores", p_run_scores_array ); // add the total score // p_run_scores->AddInteger( "total_score", (int)Mth::Round( ( m_total_score * 10 ) ) ); p_run_scores->AddInteger( "total_score", (int)Mth::Round( ( m_total_score ) ) ); Script::CleanUpArray( p_run_scores_array ); delete p_run_scores_array; #ifdef __NOPT_ASSERT__ Script::CScript *p_script=Script::SpawnScript( "goal_comp_show_run_scores", p_run_scores ); p_script->SetCommentString("Spawned from CCompetition::EndRun(...)"); #else Script::SpawnScript( "goal_comp_show_run_scores", p_run_scores ); #endif delete p_run_scores; } } // This function should be called every time the skater bails void CCompetition::Bail() { m_bail_points += m_bail + Mth::PlusOrMinus(m_bail/2); } void CCompetition::Sort() { // sort the list, based on total score int round = m_current_round; // if the competition has ended (maybe early), then total up for all the rounds if (CompetitionEnded()) { round = 2; } for (int i=0;i m_leader_board[high].GetTotalScore(round)) { high = j; } // give the player the higher position if there is a tie else if ( m_leader_board[j].m_player_number == 0 && m_leader_board[j].GetTotalScore(round) == m_leader_board[high].GetTotalScore(round) ) { high = j; } } if (high != i) { CLeaderBoardEntry t = m_leader_board[high]; m_leader_board[high] = m_leader_board[i]; m_leader_board[i] = t; } } } int CCompetition::GetPosition(int player) { return 0; } char * CCompetition::GetJudgeName(int judge) { return m_judge_name[judge]; } float CCompetition::GetJudgeScore(int judge) { return m_score[judge]; } void CCompetition::SetupJudgeText() { Game::CGoalManager* pGoalManager = Game::GetGoalManager(); Dbg_Assert( pGoalManager ); if ( pGoalManager->IsInCompetition() ) { Script::CStruct* p_score_params = new Script::CStruct(); Script::CArray* p_score_array = new Script::CArray(); p_score_array->SetSizeAndType( vNUM_JUDGES , ESYMBOLTYPE_STRUCTURE ); printf ("\nSetupJudgeText\n"); // let up now print out the fruits of our efforts for (int i = 0;iAddString( "name", m_leader_board[i].m_name.getString() ); printf("m_current_round: %i\n", m_current_round); p_leader_board_entry->AddInteger( "score", m_leader_board[i].GetTotalScore(m_current_round) ); if ( m_leader_board[i].m_player_number == 0 ) { p_leader_board_entry->AddChecksum( NONAME, CRCD( 0x67e6859a, "player" ) ); } p_score_array->SetStructure( i, p_leader_board_entry ); } p_score_params->AddArray( "leader_board", p_score_array ); Script::CleanUpArray( p_score_array ); delete p_score_array; #ifdef __NOPT_ASSERT__ Script::CScript *p_script=Script::SpawnScript( "goal_comp_add_leader_board", p_score_params ); p_script->SetCommentString("Spawned from CCompetition::SetupJudgeText()"); #else Script::SpawnScript( "goal_comp_add_leader_board", p_score_params ); #endif delete p_score_params; } /*// int i_total = 0; for (int i = 0;i=1) { if (round == 2 && small == 1) sprintf(Script::GetScriptString(12 + line * 5 + 2),xpC21f, (float)(m_leader_board[line].m_score[1]/10.0f)); else sprintf(Script::GetScriptString(12 + line * 5 + 2),pC21f, (float)(m_leader_board[line].m_score[1]/10.0f)); } else sprintf(Script::GetScriptString(12 + line * 5 + 2), pC,"-"); if (round >=2) { if (round == 2 && small == 2) sprintf(Script::GetScriptString(12 + line * 5 + 3),xpC21f, (float)(m_leader_board[line].m_score[2]/10.0f)); else sprintf(Script::GetScriptString(12 + line * 5 + 3),pC21f, (float)(m_leader_board[line].m_score[2]/10.0f)); } else { sprintf(Script::GetScriptString(12 + line * 5 + 3),pC, "-"); } sprintf(Script::GetScriptString(12 + line * 5 + 4),pC21f, (float)(m_leader_board[line].GetTotalScore(round)/10.0f)); } Mdl::Skate * pSkate = Mdl::Skate::Instance(); Obj::CPlayerProfileManager* pPlayerProfileManager=pSkate->GetPlayerProfileManager(); Obj::CSkaterProfile* pSkaterProfile=pPlayerProfileManager->GetCurrentProfile(); sprintf (Script::GetScriptString(12 + line *5), pSkaterProfile->GetDisplayName()); */ } // Return true if this is a top 3 judge // note, has to handle cases where score is the same // works by sorting the judges, and then seeing if we are in the top three bool CCompetition::IsTopJudge(int judge) { int judge_order[vNUM_JUDGES]; for (int i=0;i