home *** CD-ROM | disk | FTP | other *** search
/ GameStar 2006 March / Gamestar_82_2006-03_dvd.iso / DVDStar / Editace / quake4_sdkv10.exe / source / game / mp / Tourney.cpp < prev    next >
C/C++ Source or Header  |  2005-11-14  |  32KB  |  904 lines

  1. //----------------------------------------------------------------
  2. // Tourney.cpp
  3. //
  4. // Copyright 2002-2004 Raven Software
  5. //----------------------------------------------------------------
  6.  
  7. #include "../../idlib/precompiled.h"
  8. #pragma hdrstop
  9.  
  10. #include "Tourney.h"
  11.  
  12.  
  13. /*
  14. ===============================================================================
  15.  
  16. rvTourneyArena
  17.  
  18. ===============================================================================
  19. */
  20.  
  21. /*
  22. ================
  23. rvTourneyArena::rvTourneyArena
  24. ================
  25. */
  26. rvTourneyArena::rvTourneyArena() {
  27.     players[ 0 ] = NULL;
  28.     players[ 1 ] = NULL;
  29.     winner = NULL;
  30.     nextStateTime = 0;
  31.     fragLimitTimeout = 0;
  32.     matchStartTime = 0;
  33. }
  34.  
  35. /*
  36. ================
  37. rvTourneyArena::AddPlayer
  38. ================
  39. */
  40. void rvTourneyArena::AddPlayers( idPlayer* playerOne, idPlayer* playerTwo ) {
  41.     players[ 0 ] = playerOne;
  42.     players[ 1 ] = playerTwo;
  43.     if( playerOne ) {
  44.         playerOne->SetTourneyStatus( PTS_PLAYING );
  45.     }
  46.  
  47.     if( playerTwo ) {
  48.         playerTwo->SetTourneyStatus( PTS_PLAYING );
  49.     }
  50. }
  51.  
  52. /*
  53. ================
  54. rvTourneyArena::ClearPlayers
  55. Clears player references if clearPlayer is NULL (client-side)
  56. Clears specific player if clearPlayer is not NULL (server-side)
  57. ================
  58. */
  59. void rvTourneyArena::ClearPlayers( idPlayer* clearPlayer /* = NULL */ ) {
  60.     if( gameLocal.isServer ) {
  61.         if( clearPlayer ) {
  62.             assert( clearPlayer == players[ 0 ] || clearPlayer == players[ 1 ] );
  63.             if( clearPlayer == players[ 0 ] ) {
  64.                 players[ 0 ] = NULL;
  65.             } else {
  66.                 players[ 1 ] = NULL;
  67.             }
  68.         }
  69.         return;
  70.     } else {
  71.         players[ 0 ] = NULL;
  72.         players[ 1 ] = NULL;
  73.     }
  74. }
  75.  
  76. /*
  77. ================
  78. rvTourneyArena::Ready
  79. ================
  80. */
  81. void rvTourneyArena::Ready( void ) {
  82.     arenaState = AS_WARMUP;
  83.     nextStateTime = gameLocal.time + ( gameLocal.serverInfo.GetInt( "si_countDown" ) * 1000 ) + 5000;
  84.  
  85.     matchStartTime = 0;
  86.     // allow damage in warmup
  87.     //players[ 0 ]->fl.takedamage = false;
  88.     //players[ 1 ]->fl.takedamage = false;
  89. }
  90.  
  91. /*
  92. ================
  93. rvTourneyArena::Clear
  94. Clears player list and state, but not round # or arena ID
  95. ================
  96. */
  97. void rvTourneyArena::Clear( bool respawnPlayers ) {
  98.     if( gameLocal.isServer && respawnPlayers ) {
  99.         if( players[ 0 ] ) {
  100.             gameLocal.mpGame.SetPlayerTeamScore( players[ 0 ], 0 );        
  101.             players[ 0 ]->JoinInstance( ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetNextActiveArena( arenaID ) );
  102.             players[ 0 ]->ServerSpectate( true );
  103.         }
  104.  
  105.         if( players[ 1 ] ) {
  106.             gameLocal.mpGame.SetPlayerTeamScore( players[ 1 ], 0 );        
  107.             players[ 1 ]->JoinInstance( ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetNextActiveArena( arenaID ) );
  108.             players[ 1 ]->ServerSpectate( true );
  109.         }
  110.  
  111.         // This arena is being cleared so we must also clear out any spectators
  112.         for( int i = 0; i < MAX_CLIENTS; i++ ) {
  113.             idPlayer* player = (idPlayer*)gameLocal.entities[ i ];
  114.  
  115.             if( player == NULL ) {
  116.                 continue;
  117.             }
  118.  
  119.             if( player->GetArena() == arenaID ) {
  120.                 player->JoinInstance( ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetNextActiveArena( arenaID ) );
  121.             }
  122.         }
  123.     }
  124.  
  125.     players[ 0 ] = NULL;
  126.     players[ 1 ] = NULL;
  127.     winner = NULL;
  128.     nextStateTime = 0;
  129.     fragLimitTimeout = 0;
  130.     matchStartTime = 0;
  131.     SetState( AS_INACTIVE );
  132. }
  133.  
  134. /*
  135. ================
  136. rvTourneyArena::GetLeader
  137. Returns winning player, or NULL if there's a tie/or its undefined
  138. ================
  139. */
  140. idPlayer* rvTourneyArena::GetLeader( void ) {
  141.     if( players[ 0 ] == NULL || players[ 1 ] == NULL ) {
  142.         return NULL;
  143.     }
  144.  
  145.     int playerOneScore = gameLocal.mpGame.GetTeamScore( players[ 0 ]->entityNumber );
  146.     int playerTwoScore = gameLocal.mpGame.GetTeamScore( players[ 1 ]->entityNumber );
  147.  
  148.     if ( playerOneScore == playerTwoScore ) {
  149.         return NULL;
  150.     }
  151.  
  152.     return ( playerOneScore > playerTwoScore ? players[ 0 ] : players[ 1 ] );
  153. }
  154.  
  155. /*
  156. ================
  157. rvTourneyArena::GetLoser
  158. Returns losing player, or NULL if there's a tie/or its undefined
  159. ================
  160. */
  161. idPlayer* rvTourneyArena::GetLoser( void ) {
  162.     if( winner == NULL ) {
  163.         return NULL;
  164.     } else {
  165.         return ( winner == players[ 0 ] ? players[ 1 ] : players[ 0 ] );
  166.     }
  167. }
  168.  
  169. /*
  170. ================
  171. rvTourneyArena::UpdateState
  172. Updates this arena's state
  173. ================
  174. */
  175. void rvTourneyArena::UpdateState( void ) {
  176.     if( players[ 0 ] == NULL || players[ 1 ] == NULL ) {
  177.         gameLocal.Error( "rvTourneyArena::UpdateState() - UpdateState() called on non-full arena\n" );
  178.         return;
  179.     }
  180.  
  181.     switch( arenaState ) {
  182.         case AS_WARMUP: {
  183.             if( gameLocal.time > nextStateTime ) {
  184.                 SetState( AS_ROUND );
  185.                 
  186.                 // allow damage in warmup
  187.                 //players[ 0 ]->fl.takedamage = true;
  188.                 //players[ 1 ]->fl.takedamage = true;
  189.                 // respawn the players
  190.                 //players[ 0 ]->ServerSpectate( false );
  191.                 //players[ 1 ]->ServerSpectate( false );
  192.                 // respawn items
  193.                 gameLocal.mpGame.EnableDamage( true );
  194.                 gameLocal.LocalMapRestart( arenaID );
  195.  
  196.                 gameLocal.mpGame.SetPlayerTeamScore( players[ 0 ], 0 );
  197.                 gameLocal.mpGame.SetPlayerTeamScore( players[ 1 ], 0 );
  198.                 matchStartTime = gameLocal.time;
  199.             }
  200.  
  201.             break;
  202.         }
  203.  
  204.         case AS_ROUND: {
  205.             if( GetLeader() && gameLocal.serverInfo.GetInt( "si_fragLimit" ) > 0 && gameLocal.mpGame.GetTeamScore( GetLeader()->entityNumber ) >= gameLocal.serverInfo.GetInt( "si_fraglimit" ) ) {
  206.                 if( fragLimitTimeout && fragLimitTimeout < gameLocal.time ) {
  207.                     NewState( AS_DONE );
  208.                 } else if ( !fragLimitTimeout ) {
  209.                     fragLimitTimeout = gameLocal.time + FRAGLIMIT_DELAY;
  210.                 }
  211.             } else if( fragLimitTimeout ) {
  212.                 //if we got here, that means that either the teams are tied at the fraglimit, or someone must have 
  213.                 //reached the frag limit but then dropped below it before the frag timer
  214.                 //expired. Tourney must be won cleanly though, so...
  215.                 if( GetLeader() )
  216.                 fragLimitTimeout = 0;
  217.                 //back to normal play?
  218.             } else if ( TimeLimitHit() ) {
  219.                 gameLocal.mpGame.PrintMessageEvent( players[ 0 ]->entityNumber, MSG_TIMELIMIT );
  220.                 gameLocal.mpGame.PrintMessageEvent( players[ 1 ]->entityNumber, MSG_TIMELIMIT );
  221.                 if( GetLeader() == NULL ) {
  222.                     // if tied at timelimit hit, goto sudden death
  223.                     NewState( AS_SUDDEN_DEATH );
  224.                 } else {
  225.                     // or just end the game
  226.                     NewState( AS_DONE );
  227.                 }
  228.             }
  229.             break;
  230.         }
  231.         case AS_SUDDEN_DEATH: {
  232.             if ( GetLeader() ) {
  233.                 if ( !fragLimitTimeout ) {
  234.                     common->DPrintf( "enter sudden death FragLeader timeout, player %d is leader\n", GetLeader()->entityNumber );
  235.                     fragLimitTimeout = gameLocal.time + FRAGLIMIT_DELAY;
  236.                 }
  237.                 if ( gameLocal.time > fragLimitTimeout ) {
  238.                     NewState( AS_DONE );
  239.                     gameLocal.mpGame.PrintMessageEvent( -1, MSG_FRAGLIMIT, GetLeader()->entityNumber );
  240.                 }
  241.             } else if ( fragLimitTimeout ) {
  242.                 gameLocal.mpGame.PrintMessageEvent( -1, MSG_HOLYSHIT );
  243.                 fragLimitTimeout = 0;
  244.             }
  245.             break;
  246.         }
  247.     }
  248. }
  249.  
  250. /*
  251. ================
  252. rvTourneyArena::NewState
  253. ================
  254. */
  255. void rvTourneyArena::NewState( arenaState_t newState ) {
  256.     switch( newState ) {
  257.         case AS_DONE: {
  258.             winner = GetLeader();
  259.             assert( winner );
  260.             gameLocal.Printf( "rvTourneyArena::UpdateState() - %s has won this arena\n", GetLeader()->GetUserInfo()->GetString( "ui_name" ) );    
  261.  
  262.             winner->SetTourneyStatus( PTS_ADVANCED );
  263.             GetLoser()->SetTourneyStatus( PTS_ELIMINATED );
  264.  
  265.             if( players[ 0 ] ) {
  266.                 players[ 0 ]->ServerSpectate( true );
  267.                 players[ 0 ]->JoinInstance( ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetNextActiveArena( arenaID ) );
  268.             }
  269.  
  270.             if( players[ 1 ] ) {
  271.                 players[ 1 ]->ServerSpectate( true );
  272.                 players[ 1 ]->JoinInstance( ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetNextActiveArena( arenaID ) );
  273.             }
  274.  
  275.             // when we're done, put anyone who was spectating into another arena
  276.             for( int i = 0; i < MAX_CLIENTS; i++ ) {
  277.                 idPlayer* player = (idPlayer*)gameLocal.entities[ i ];
  278.  
  279.                 if( player == NULL ) {
  280.                     continue;
  281.                 }
  282.  
  283.                 if( player->GetArena() == arenaID ) {
  284.                     player->JoinInstance( ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetNextActiveArena( arenaID ) );
  285.                 }
  286.             }
  287.  
  288.             matchStartTime = 0;
  289.             break;
  290.         }
  291.         case AS_SUDDEN_DEATH: {
  292.             fragLimitTimeout = 0;
  293.  
  294.             // respawn the arena
  295.             players[ 0 ]->ServerSpectate( false );
  296.             players[ 1 ]->ServerSpectate( false );
  297.             gameLocal.LocalMapRestart( arenaID );
  298.             break;
  299.         }
  300.         default: {
  301.             gameLocal.Error( "rvTourneyArena::NewState() - Unknown state '%d'\n", newState );
  302.             return;
  303.         }
  304.     }
  305.     SetState( newState );    
  306. }
  307.  
  308. /*
  309. ================
  310. rvTourneyArena::RemovePlayer
  311. The specified client is being removed from the server
  312. ================
  313. */
  314. void rvTourneyArena::RemovePlayer( idPlayer* player, bool disconnecting ) {
  315.     if( disconnecting ) {
  316.         // when we call Clear() the arena will clean up (set player instances to 0, spectate them, etc)
  317.         // we don't want it to do this for the disconnecting player, since he may not be entirely valid
  318.         // anymore.  If we NULL out the disconnecting player, Clear() will properly reset the remaining player
  319.         // but will leave the volatile disconnecting player's data lone.
  320.         
  321.         bool playerInArena = false;
  322.         if( player == players[ 0 ] ) {
  323.             players[ 0 ] = NULL;
  324.             playerInArena = true;
  325.         } 
  326.         
  327.         if( player == players[ 1 ] ) {
  328.             players[ 1 ] = NULL;
  329.             playerInArena = true;
  330.         }
  331.         
  332.         if( !playerInArena ) {
  333.             gameLocal.Error( "rvTourneyArena::RemovePlayer() - Called on player who is not in arena '%d'\n", arenaID );
  334.         }
  335.     }
  336.     
  337.     Clear();
  338. }
  339.  
  340. /*
  341. ================
  342. rvTourneyArena::PackState
  343. ================
  344. */
  345. void rvTourneyArena::PackState( idBitMsg& outMsg ) {
  346.     if( players[ 0 ] ) {
  347.         outMsg.WriteByte( players[ 0 ]->entityNumber );
  348.     } else {
  349.         outMsg.WriteByte( -1 );
  350.     }
  351.     
  352.     if( players[ 1 ] ) {
  353.         outMsg.WriteByte( players[ 1 ]->entityNumber );
  354.     } else {
  355.         outMsg.WriteByte( -1 );
  356.     }
  357.  
  358.     if( winner ) {
  359.         outMsg.WriteByte( winner->entityNumber );
  360.     } else {
  361.         outMsg.WriteByte( -1 );
  362.     }
  363.     
  364.     outMsg.WriteByte( arenaState );
  365.     outMsg.WriteLong( nextStateTime );
  366.     outMsg.WriteLong( fragLimitTimeout );
  367.     outMsg.WriteLong( matchStartTime );
  368. }
  369.  
  370. /*
  371. ================
  372. rvTourneyArena::UnpackState
  373. ================
  374. */
  375. void rvTourneyArena::UnpackState( const idBitMsg& inMsg ) {
  376.     int playerOneNum = inMsg.ReadByte();
  377.     int playerTwoNum = inMsg.ReadByte();
  378.     int winnerNum = inMsg.ReadByte();
  379.  
  380.     if( playerOneNum >= 0 && playerOneNum < MAX_CLIENTS ) {
  381.         players[ 0 ] = (idPlayer*)gameLocal.entities[ playerOneNum ];
  382.     } else {
  383.         players[ 0 ] = NULL;
  384.     }
  385.  
  386.     if( playerTwoNum >= 0 && playerTwoNum < MAX_CLIENTS ) {
  387.         players[ 1 ] = (idPlayer*)gameLocal.entities[ playerTwoNum ];
  388.     } else {
  389.         players[ 1 ] = NULL;
  390.     }
  391.  
  392.     if( winnerNum >= 0 && winnerNum < MAX_CLIENTS ) {
  393.         winner = (idPlayer*)gameLocal.entities[ winnerNum ];
  394.     } else {
  395.         winner = NULL;
  396.     }
  397.  
  398.     arenaState = (arenaState_t)inMsg.ReadByte();
  399.     nextStateTime = inMsg.ReadLong();
  400.     fragLimitTimeout = inMsg.ReadLong();
  401.     matchStartTime = inMsg.ReadLong();
  402. }
  403.  
  404. /*
  405. ================
  406. rvTourneyArena::SetState
  407. Set's this arena's state - client side only based on UpdateState() results from server
  408. ================
  409. */
  410. void rvTourneyArena::SetState( arenaState_t newState ) {
  411.     arenaState = newState;
  412. }
  413.  
  414. /*
  415. ================
  416. rvTourneyArena::SetNextStateTime
  417. ================
  418. */
  419. void rvTourneyArena::SetNextStateTime( int time ) {
  420.     nextStateTime = time;
  421. }
  422.  
  423. /*
  424. ================
  425. rvTourneyArena::GetNextStateTime
  426. ================
  427. */
  428. int rvTourneyArena::GetNextStateTime( void ) {
  429.     return nextStateTime;
  430. }
  431.  
  432.  
  433. /*
  434. ================
  435. rvTourneyArena::GetState
  436. ================
  437. */
  438. arenaState_t rvTourneyArena::GetState( void ) const {
  439.     return arenaState;
  440. }
  441.  
  442. /*
  443. ================
  444. rvTourneyArena::GetPlayerName
  445. ================
  446. */
  447. const char* rvTourneyArena::GetPlayerName( int player ) {
  448.     assert( player >= 0 && player < 2 );
  449.  
  450.     if( players[ player ] ) {
  451.         return players[ player ]->GetUserInfo()->GetString( "ui_name" );
  452.     } else {
  453.         return NULL;
  454.     }
  455. }
  456.  
  457. /*
  458. ================
  459. rvTourneyArena::GetPlayerScore
  460. ================
  461. */
  462. int rvTourneyArena::GetPlayerScore( int player ) {
  463.     assert( player >= 0 && player < 2 );
  464.  
  465.  
  466.     if( players[ player ] ) {
  467.         return gameLocal.mpGame.GetTeamScore( players[ player ] );
  468.     } else {
  469.         return 0;
  470.     }
  471. }
  472.  
  473. /*
  474. ================
  475. rvTourneyArena::TimeLimitHit
  476. ================
  477. */
  478. bool rvTourneyArena::TimeLimitHit( void ) {    
  479.     int timeLimit = gameLocal.serverInfo.GetInt( "si_timeLimit" );
  480.     if ( timeLimit ) {
  481.         if ( gameLocal.time >= matchStartTime + timeLimit * 60000 ) {
  482.             return true;
  483.         }
  484.     }
  485.     return false;
  486. }
  487.  
  488. /*
  489. ===============================================================================
  490.  
  491. rvTourneyGUI
  492.  
  493. ===============================================================================
  494. */
  495.  
  496. rvTourneyGUI::rvTourneyGUI() {
  497.     tourneyGUI = NULL;
  498.     tourneyScoreboard = NULL;
  499. }
  500.  
  501. void rvTourneyGUI::SetupTourneyGUI( idUserInterface* newTourneyGUI, idUserInterface* newTourneyScoreboard ) {
  502.     tourneyGUI = newTourneyGUI;
  503.     tourneyScoreboard = newTourneyScoreboard;
  504. }
  505.  
  506. void rvTourneyGUI::RoundStart( void ) {
  507.     if( tourneyGUI == NULL ) {
  508.         common->Warning( "rvTourneyGUI::RoundStart() - Invalid tourneyGUI" );
  509.         return;
  510.     }
  511.  
  512.     tourneyGUI->SetStateInt( "round", ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound() );
  513.     tourneyGUI->StateChanged( gameLocal.time );
  514.     tourneyGUI->HandleNamedEvent( "roundTransitionIn" );
  515.  
  516.     if( tourneyScoreboard == NULL ) {
  517.         common->Warning( "rvTourneyGUI::RoundStart() - Invalid tourneyScoreboard" );
  518.         return;
  519.     }
  520.  
  521.     tourneyScoreboard->SetStateInt( "round", ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound() );
  522.     tourneyScoreboard->StateChanged( gameLocal.time );
  523.     tourneyScoreboard->HandleNamedEvent( "roundTransitionIn" );
  524.  
  525.     // set bye player for new round - the actual byePlayer may not have changed, so the gamestate won't move him over
  526.     UpdateByePlayer();
  527. }
  528.  
  529. void rvTourneyGUI::ArenaStart( int arena ) {
  530.     if( tourneyGUI == NULL ) {
  531.         common->Warning( "rvTourneyGUI::ArenaStart() - Invalid tourneyGUI" );
  532.         return;
  533.     }
  534.  
  535.     //arenaInit sets names to white and scores to orange. needs values "gui::round" , "gui::bracket" and "gui::empty"
  536.     idPlayer** players = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetArenaPlayers( arena );
  537.     int round = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound();
  538.  
  539.     tourneyGUI->SetStateInt( "round", round );
  540.     tourneyGUI->SetStateInt( "bracket", arena + 1 );
  541.     if( players[ 0 ] == NULL || players[ 1 ] == NULL ) {
  542.         tourneyGUI->SetStateBool( "empty", true );
  543.     } else {
  544.         tourneyGUI->SetStateBool( "empty", false );    
  545.         tourneyGUI->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), players[ 0 ] ? players[ 0 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  546.         tourneyGUI->SetStateString( va( "score1_round%d_bracket%d", round, arena + 1 ), players[ 0 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 0 ] ) ) : "" );
  547.  
  548.         tourneyGUI->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), players[ 1 ] ? players[ 1 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  549.         tourneyGUI->SetStateString( va( "score2_round%d_bracket%d", round, arena + 1 ), players[ 1 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 1 ] ) ) : "" );
  550.     }
  551.     tourneyGUI->StateChanged( gameLocal.time );
  552.  
  553.     tourneyGUI->HandleNamedEvent( "arenaInit" );
  554.  
  555.  
  556.     if( tourneyScoreboard == NULL ) {
  557.         common->Warning( "rvTourneyGUI::ArenaStart() - Invalid tourneyScoreboard" );
  558.         return;
  559.     }
  560.  
  561.     tourneyScoreboard->SetStateInt( "round", round );
  562.     tourneyScoreboard->SetStateInt( "bracket", arena + 1 );
  563.     if( players[ 0 ] == NULL || players[ 1 ] == NULL ) {
  564.         tourneyScoreboard->SetStateBool( "empty", true );
  565.     } else {
  566.         tourneyScoreboard->SetStateBool( "empty", false );    
  567.         tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), players[ 0 ] ? players[ 0 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  568.         tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", round, arena + 1 ), players[ 0 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 0 ] ) ) : "" );
  569.  
  570.         tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), players[ 1 ] ? players[ 1 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  571.         tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", round, arena + 1 ), players[ 1 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 1 ] ) ) : "" );
  572.     }
  573.     tourneyScoreboard->StateChanged( gameLocal.time );
  574.  
  575.     tourneyScoreboard->HandleNamedEvent( "arenaInit" );
  576. }
  577.  
  578. void rvTourneyGUI::ArenaDone( int arena ) {
  579.     if( tourneyGUI == NULL ) {
  580.         common->Warning( "rvTourneyGUI::ArenaDone() - Invalid tourneyGUI" );
  581.         return;
  582.     }
  583.  
  584.     // arenaDone transitions the blue flash/fade and names of winner/loser. needs values "gui::round" , "gui::bracket" and "gui::winner" (winner is a 1 or 2 value, 1 top 2 bottom)
  585.     tourneyGUI->SetStateInt( "round", ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound() );
  586.     tourneyGUI->SetStateInt( "bracket", arena + 1 );
  587.  
  588.     rvTourneyArena& tourneyArena = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetArena( arena );
  589.     
  590.     idPlayer* winner = tourneyArena.GetWinner();
  591.     idPlayer** players = tourneyArena.GetPlayers();
  592.  
  593.     if( winner == NULL ) {
  594.         common->Error( "rvTourneyGUI::ArenaDone() - Called on arena '%d' which is not done!\n", arena );
  595.         return;
  596.     }
  597.  
  598.     if( winner != players[ 0 ] && winner != players[ 1 ] ) {
  599.         common->Error( "rvTourneyGUI::ArenaDone() - Arena '%d' is reporting a winner that is not in the arena!\n", arena );
  600.         return;
  601.     }
  602.  
  603.     tourneyGUI->SetStateInt( "winner", winner == players[ 0 ] ? 1 : 2 );
  604.     tourneyGUI->StateChanged( gameLocal.time );
  605.     tourneyGUI->HandleNamedEvent( "arenaDone" );
  606.  
  607.     if( tourneyScoreboard == NULL ) {
  608.         common->Warning( "rvTourneyGUI::ArenaDone() - Invalid tourneyScoreboard" );
  609.         return;
  610.     }
  611.  
  612.     // arenaDone transitions the blue flash/fade and names of winner/loser. needs values "gui::round" , "gui::bracket" and "gui::winner" (winner is a 1 or 2 value, 1 top 2 bottom)
  613.     tourneyScoreboard->SetStateInt( "round", ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound() );
  614.     tourneyScoreboard->SetStateInt( "bracket", arena + 1 );
  615.  
  616.     tourneyScoreboard->SetStateInt( "winner", winner == players[ 0 ] ? 1 : 2 );
  617.     tourneyScoreboard->StateChanged( gameLocal.time );
  618.     tourneyScoreboard->HandleNamedEvent( "arenaDone" );
  619. }
  620.  
  621. void rvTourneyGUI::ArenaSelect( int arena, tourneyGUIHighlight_t highlightType ) {
  622.     if( tourneyGUI == NULL ) {
  623.         common->Warning( "rvTourneyGUI::ArenaSelect() - Invalid tourneyGUI" );
  624.         return;
  625.     }
  626.  
  627.     //arenaFocus sets the green background on bracket, player 1 or player2 using value "gui::sel". ( 0 = bracket, 1 = player1, 2 = player2) arenaFocus also needs "gui::round" and "gui::bracket" values.
  628.     tourneyGUI->SetStateInt( "round", ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound() );
  629.     tourneyGUI->SetStateInt( "bracket", arena + 1 );    
  630.     tourneyGUI->SetStateInt( "sel", (int)highlightType );
  631.     tourneyGUI->StateChanged( gameLocal.time );
  632.     tourneyGUI->HandleNamedEvent( "arenaFocus" );
  633.  
  634.     if( tourneyScoreboard == NULL ) {
  635.         common->Warning( "rvTourneyGUI::ArenaSelect() - Invalid tourneyScoreboard" );
  636.         return;
  637.     }
  638.  
  639.     //arenaFocus sets the green background on bracket, player 1 or player2 using value "gui::sel". ( 0 = bracket, 1 = player1, 2 = player2) arenaFocus also needs "gui::round" and "gui::bracket" values.
  640.     tourneyScoreboard->SetStateInt( "round", ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound() );
  641.     tourneyScoreboard->SetStateInt( "bracket", arena + 1 );    
  642.     tourneyScoreboard->SetStateInt( "sel", (int)highlightType );
  643.     tourneyScoreboard->StateChanged( gameLocal.time );
  644.     tourneyScoreboard->HandleNamedEvent( "arenaFocus" );
  645. }
  646.  
  647. void rvTourneyGUI::UpdateScores( void ) {
  648.     if( tourneyGUI == NULL ) {
  649.         common->Warning( "rvTourneyGUI::UpdateScore() - Invalid tourneyGUI" );
  650.         return;
  651.     }
  652.  
  653.     int round = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound();
  654.  
  655.     for( int i = 0; i < MAX_ARENAS; i++ ) {
  656.         rvTourneyArena& arena = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetArena( i );
  657.         idPlayer** players = arena.GetPlayers();
  658.  
  659.         if( arena.GetState() != AS_DONE && arena.GetState() != AS_INACTIVE ) {
  660.             tourneyGUI->SetStateString( va( "name1_round%d_bracket%d", round, i + 1 ), players[ 0 ] ? players[ 0 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  661.             tourneyGUI->SetStateString( va( "score1_round%d_bracket%d", round, i + 1 ), players[ 0 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 0 ] ) ) : "" );
  662.  
  663.             tourneyGUI->SetStateString( va( "name2_round%d_bracket%d", round, i + 1 ), players[ 1 ] ? players[ 1 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  664.             tourneyGUI->SetStateString( va( "score2_round%d_bracket%d", round, i + 1 ), players[ 1 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 1 ] ) ) : "" );        
  665.         }
  666.     }
  667.  
  668.     tourneyGUI->StateChanged( gameLocal.time );
  669.  
  670.     if( tourneyScoreboard == NULL ) {
  671.         common->Warning( "rvTourneyGUI::UpdateScore() - Invalid tourneyScoreboard" );
  672.         return;
  673.     }
  674.  
  675.     for( int i = 0; i < MAX_ARENAS; i++ ) {
  676.         rvTourneyArena& arena = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetArena( i );
  677.         idPlayer** players = arena.GetPlayers();
  678.  
  679.         if( arena.GetState() != AS_DONE && arena.GetState() != AS_INACTIVE ) {
  680.             tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, i + 1 ), players[ 0 ] ? players[ 0 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  681.             tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", round, i + 1 ), players[ 0 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 0 ] ) ) : "" );
  682.  
  683.             tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", round, i + 1 ), players[ 1 ] ? players[ 1 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  684.             tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", round, i + 1 ), players[ 1 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 1 ] ) ) : "" );        
  685.         }
  686.     }
  687.  
  688.     tourneyScoreboard->StateChanged( gameLocal.time );
  689. }
  690.  
  691. void rvTourneyGUI::PreTourney( void ) {
  692.     if( tourneyGUI == NULL ) {
  693.         common->Warning( "rvTourneyGUI::PreTourney() - Invalid tourneyGUI" );
  694.         return;
  695.     }
  696.  
  697.     tourneyGUI->HandleNamedEvent( "warmupTransitionIn" );
  698. }
  699.  
  700. void rvTourneyGUI::TourneyStart( void ) {
  701.     if( tourneyGUI == NULL ) {
  702.         common->Warning( "rvTourneyGUI::TourneyStart() - Invalid tourneyGUI" );
  703.         return;
  704.     }
  705.  
  706.     int round = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound();
  707.     int maxRound = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetMaxRound();
  708.  
  709.     tourneyGUI->SetStateInt( "round", round );
  710.     tourneyGUI->StateChanged( gameLocal.time );
  711.  
  712.     tourneyGUI->HandleNamedEvent( "warmupTransitionOut" );
  713.  
  714.     // setup and clear the scoreboard
  715.     if( tourneyScoreboard == NULL ) {
  716.         common->Warning( "rvTourneyGUI::TourneyStart() - Invalid tourneyScoreboard" );
  717.         return;
  718.     }
  719.  
  720.     for( int i = 1; i <= maxRound; i++ ) {
  721.         for( int j = 0; j < MAX_ARENAS; j++ ) {
  722.             tourneyScoreboard->SetStateInt( "round", i );
  723.             tourneyScoreboard->SetStateInt( "bracket", j + 1 );
  724.  
  725.             if( i < round ) {
  726.                 // we aren't using these brackets
  727.                 tourneyScoreboard->SetStateBool( "empty", true );
  728.                 tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", i, j + 1 ), "" );
  729.                 tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", i, j + 1 ), "" );
  730.                 tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", i, j + 1 ), "" );
  731.                 tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", i, j + 1 ), "" );
  732.             } else if ( i == round ) {
  733.                 // this is our initial round
  734.                 idPlayer** players = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetArenaPlayers( j );
  735.  
  736.                 if( players[ 0 ] == NULL || players[ 1 ] == NULL ) {
  737.                     tourneyScoreboard->SetStateBool( "empty", true );
  738.                 } else {
  739.                     tourneyScoreboard->SetStateBool( "empty", false );    
  740.                     tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", i, j + 1 ), players[ 0 ] ? players[ 0 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  741.                     tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", i, j + 1 ), players[ 0 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 0 ] ) ) : "" );
  742.  
  743.                     tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", i, j + 1 ), players[ 1 ] ? players[ 1 ]->GetUserInfo()->GetString( "ui_name" ) : "" );
  744.                     tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", i, j + 1 ), players[ 1 ] ? va( "%d", gameLocal.mpGame.GetTeamScore( players[ 1 ] ) ) : "" );
  745.                 }
  746.             } else {    
  747.                 // this is our future bracket
  748.                 tourneyScoreboard->SetStateBool( "empty", false );
  749.                 tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", i, j + 1 ), "" );
  750.                 tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", i, j + 1 ), "" );
  751.                 tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", i, j + 1 ), "" );
  752.                 tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", i, j + 1 ), "" );
  753.             }    
  754.             tourneyScoreboard->StateChanged( gameLocal.time );
  755.             tourneyScoreboard->HandleNamedEvent( "arenaInit" );
  756.         }
  757.     }
  758.  
  759.     // we might have overwritten a bye player, so update it again
  760.     UpdateByePlayer();
  761. }
  762.  
  763. void rvTourneyGUI::UpdateByePlayer( void ) {
  764.     if( tourneyGUI == NULL ) {
  765.         common->Warning( "rvTourneyGUI::UpdateByePlayer() - Invalid tourneyGUI" );
  766.         return;
  767.     }
  768.  
  769.     int arena;
  770.     for( arena = 0; arena < MAX_ARENAS; arena++ ) {
  771.         if( ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetArena( arena ).GetState() == AS_INACTIVE ) {
  772.             break;
  773.         }
  774.     }
  775.  
  776.     if( arena >= MAX_ARENAS ) {
  777.         common->Warning( "rvTourneyGUI::UpdateByePlayer() - Bye player with no inactive arenas!" );
  778.         return;
  779.     }
  780.  
  781.     idPlayer* byePlayer = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetByePlayer();
  782.  
  783.     int round = ((rvTourneyGameState*)gameLocal.mpGame.GetGameState())->GetRound();
  784.     tourneyGUI->SetStateInt( "round", round );
  785.     tourneyGUI->SetStateInt( "bracket", arena + 1 );
  786.  
  787.     if( byePlayer ) {
  788.         tourneyGUI->SetStateBool( "empty", false );    
  789.         tourneyGUI->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), byePlayer->GetUserInfo()->GetString( "ui_name" ) );
  790.         tourneyGUI->SetStateString( va( "score1_round%d_bracket%d", round, arena + 1 ), "" );
  791.  
  792.         tourneyGUI->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), common->GetLocalizedString( "#str_107705" ) );
  793.         tourneyGUI->SetStateString( va( "score2_round%d_bracket%d", round, arena + 1 ), "" );
  794.     } else {
  795.         tourneyGUI->SetStateBool( "empty", true );    
  796.         tourneyGUI->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), "" );
  797.         tourneyGUI->SetStateString( va( "score1_round%d_bracket%d", round, arena + 1 ), "" );
  798.  
  799.         tourneyGUI->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), "" );
  800.         tourneyGUI->SetStateString( va( "score2_round%d_bracket%d", round, arena + 1 ), "" );
  801.     }
  802.  
  803.  
  804.     tourneyGUI->StateChanged( gameLocal.time );
  805.  
  806.     tourneyGUI->HandleNamedEvent( "arenaInit" );
  807.  
  808.     if( tourneyScoreboard == NULL ) {
  809.         common->Warning( "rvTourneyGUI::UpdateByePlayer() - Invalid tourneyScoreboard" );
  810.         return;
  811.     }
  812.  
  813.     tourneyScoreboard->SetStateInt( "round", round );
  814.     tourneyScoreboard->SetStateInt( "bracket", arena + 1 );
  815.  
  816.     if( byePlayer ) {
  817.         tourneyScoreboard->SetStateBool( "empty", false );    
  818.         tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), byePlayer->GetUserInfo()->GetString( "ui_name" ) );
  819.         tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", round, arena + 1 ), "" );
  820.  
  821.         tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), common->GetLocalizedString( "#str_107705" ) );
  822.         tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", round, arena + 1 ), "" );
  823.     } else {
  824.         tourneyScoreboard->SetStateBool( "empty", true );    
  825.         tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), "" );
  826.         tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", round, arena + 1 ), "" );
  827.  
  828.         tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), "" );
  829.         tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", round, arena + 1 ), "" );
  830.     }
  831.  
  832.     tourneyScoreboard->StateChanged( gameLocal.time );
  833.  
  834.     tourneyScoreboard->HandleNamedEvent( "arenaInit" );
  835. }
  836.  
  837. void rvTourneyGUI::SetupTourneyHistory( int startHistory, int endHistory, arenaOutcome_t tourneyHistory[ MAX_ROUNDS ][ MAX_ARENAS ] ) {
  838.     if ( tourneyScoreboard == NULL ) {
  839.         common->Warning( "rvTourneyGUI::SetupTourneyHistory() - Invalid tourneyScoreboard" );
  840.         return;
  841.     }
  842.  
  843.     if( startHistory <= 0 ) {
  844.         return;
  845.     }
  846.  
  847.     for ( int round = startHistory; round <= endHistory; round++ ) {
  848.         tourneyScoreboard->SetStateInt( "round", round );
  849.  
  850.         for ( int arena = 0; arena < MAX_ARENAS / round; arena++ ) {
  851.             tourneyScoreboard->SetStateInt( "bracket", arena + 1 );
  852.  
  853.             // whether we want to send arenaDone to this arena
  854.             // don't send for empty brackets or bye rounds
  855.             bool arenaNotDone = tourneyHistory[ round - 1 ][ arena ].playerOneNum == -1 && tourneyHistory[ round - 1 ][ arena ].playerTwoNum == -1 && !(*tourneyHistory[ round - 1 ][ arena ].playerOne) && !(*tourneyHistory[ round - 1 ][ arena ].playerTwo);
  856.  
  857.             if( arenaNotDone ) {
  858.                 tourneyScoreboard->SetStateBool( "empty", true );
  859.             } else {
  860.                 tourneyScoreboard->SetStateBool( "empty", false );    
  861.  
  862.                 if( tourneyHistory[ round - 1 ][ arena ].playerTwoNum == -1 && !(*tourneyHistory[ round - 1 ][ arena ].playerTwo) ) {
  863.                     // this was a bye round
  864.                     if( tourneyHistory[ round - 1 ][ arena ].playerOneNum == -1 || !gameLocal.GetUserInfo( tourneyHistory[ round - 1 ][ arena ].playerOneNum ) ) {
  865.                         tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), tourneyHistory[ round - 1 ][ arena ].playerOne );
  866.                     } else {
  867.                         tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), gameLocal.GetUserInfo( tourneyHistory[ round - 1 ][ arena ].playerOneNum )->GetString( "ui_name" ) );
  868.                     }
  869.                     
  870.                     tourneyScoreboard->SetStateString( va( "score1_round%d_bracket%d", round, arena + 1 ), "" );
  871.  
  872.                     tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), common->GetLocalizedString( "#str_107705" ) );
  873.                     tourneyScoreboard->SetStateString( va( "score2_round%d_bracket%d", round, arena + 1 ), "" );
  874.                     arenaNotDone = true;
  875.                 } else {
  876.                     // regular round
  877.                     if( tourneyHistory[ round - 1 ][ arena ].playerOneNum == -1 || !gameLocal.GetUserInfo( tourneyHistory[ round - 1 ][ arena ].playerOneNum ) ) {
  878.                         tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), tourneyHistory[ round - 1 ][ arena ].playerOne );
  879.                     } else {
  880.                         tourneyScoreboard->SetStateString( va( "name1_round%d_bracket%d", round, arena + 1 ), gameLocal.GetUserInfo( tourneyHistory[ round - 1 ][ arena ].playerOneNum )->GetString( "ui_name" ) );
  881.                     }
  882.                     
  883.                     tourneyScoreboard->SetStateInt( va( "score1_round%d_bracket%d", round, arena + 1 ), tourneyHistory[ round - 1 ][ arena ].playerOneScore );
  884.  
  885.                     if( tourneyHistory[ round - 1 ][ arena ].playerTwoNum == -1 || !gameLocal.GetUserInfo( tourneyHistory[ round - 1 ][ arena ].playerTwoNum ) ) {
  886.                         tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), tourneyHistory[ round - 1 ][ arena ].playerTwo );
  887.                     } else {
  888.                         tourneyScoreboard->SetStateString( va( "name2_round%d_bracket%d", round, arena + 1 ), gameLocal.GetUserInfo( tourneyHistory[ round - 1 ][ arena ].playerTwoNum )->GetString( "ui_name" ) );
  889.                     }
  890.  
  891.                     tourneyScoreboard->SetStateInt( va( "score2_round%d_bracket%d", round, arena + 1 ), tourneyHistory[ round - 1 ][ arena ].playerTwoScore );
  892.  
  893.                     tourneyScoreboard->SetStateInt( "winner", tourneyHistory[ round - 1 ][ arena ].playerOneScore > tourneyHistory[ round - 1 ][ arena ].playerTwoScore ? 1 : 2 );
  894.                 }
  895.             }
  896.             tourneyScoreboard->StateChanged( gameLocal.time );
  897.             tourneyScoreboard->HandleNamedEvent( "arenaInit" );
  898.             if( !arenaNotDone ) {
  899.                 tourneyScoreboard->HandleNamedEvent( "arenaDone" );
  900.             }
  901.         }
  902.     }
  903. }
  904.