Advertisement
Guest User

admin menu.

a guest
Oct 14th, 2010
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 56.77 KB | None | 0 0
  1. #include maps\mp\_utility;
  2. #include maps\mp\gametypes\_hud_util;
  3. #include common_scripts\utility;
  4.  
  5. FACTION_REF_COL                     = 0;
  6. FACTION_NAME_COL                    = 1;
  7. FACTION_SHORT_NAME_COL              = 1;
  8. FACTION_WIN_GAME_COL                = 3;
  9. FACTION_WIN_ROUND_COL               = 4;
  10. FACTION_MISSION_ACCOMPLISHED_COL    = 5;
  11. FACTION_ELIMINATED_COL              = 6;
  12. FACTION_FORFEITED_COL               = 7;
  13. FACTION_ICON_COL                    = 8;
  14. FACTION_HUD_ICON_COL                = 9;
  15. FACTION_VOICE_PREFIX_COL            = 10;
  16. FACTION_SPAWN_MUSIC_COL             = 11;
  17. FACTION_WIN_MUSIC_COL               = 12;
  18. FACTION_COLOR_R_COL                 = 13;
  19. FACTION_COLOR_G_COL                 = 14;
  20. FACTION_COLOR_B_COL                 = 15;
  21.  
  22. // when a team leaves completely, that team forfeited, team left wins round, ends game
  23. onForfeit( team )
  24. {
  25.     if ( isDefined( level.forfeitInProgress ) )
  26.         return;
  27.  
  28.     level endon( "abort_forfeit" );         //end if the team is no longer in forfeit status
  29.  
  30.     level.forfeitInProgress = true;
  31.    
  32.     // in 1v1 DM, give players time to change teams
  33.     if ( !level.teambased && level.players.size > 1 )
  34.         wait 10;
  35.    
  36.     forfeit_delay = 20.0;                       //forfeit wait, for switching teams and such
  37.    
  38.     foreach ( player in level.players )
  39.     {
  40.         player setLowerMessage( "forfeit_warning", game["strings"]["opponent_forfeiting_in"], forfeit_delay, 100 );
  41.         player thread forfeitWaitforAbort();
  42.     }
  43.        
  44.     wait ( forfeit_delay );
  45.    
  46.     endReason = &"";
  47.     if ( !isDefined( team ) )
  48.     {
  49.         endReason = game["strings"]["players_forfeited"];
  50.         winner = level.players[0];
  51.     }
  52.     else if ( team == "allies" )
  53.     {
  54.         endReason = game["strings"]["allies_forfeited"];
  55.         winner = "axis";
  56.     }
  57.     else if ( team == "axis" )
  58.     {
  59.         endReason = game["strings"]["axis_forfeited"];
  60.         winner = "allies";
  61.     }
  62.     else
  63.     {
  64.         //shouldn't get here
  65.         assertEx( isdefined( team ), "Forfeited team is not defined" );
  66.         assertEx( 0, "Forfeited team " + team + " is not allies or axis" );
  67.         winner = "tie";
  68.     }
  69.     //exit game, last round, no matter if round limit reached or not
  70.     level.forcedEnd = true;
  71.    
  72.     if ( isPlayer( winner ) )
  73.         logString( "forfeit, win: " + winner getXuid() + "(" + winner.name + ")" );
  74.     else
  75.         logString( "forfeit, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] );
  76.     thread endGame( winner, endReason );
  77. }
  78.  
  79.  
  80. forfeitWaitforAbort()
  81. {
  82.     self endon ( "disconnect" );
  83.     level endon ( "game_ended" );
  84.    
  85.     level waittill ( "abort_forfeit" );
  86.    
  87.     self clearLowerMessage( "forfeit_warning" );
  88. }
  89.  
  90.  
  91. default_onDeadEvent( team )
  92. {
  93.     if ( team == "allies" )
  94.     {
  95.         iPrintLn( game["strings"]["allies_eliminated"] );
  96.  
  97.         logString( "team eliminated, win: opfor, allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] );
  98.        
  99.         thread endGame( "axis", game["strings"]["allies_eliminated"] );
  100.     }
  101.     else if ( team == "axis" )
  102.     {
  103.         iPrintLn( game["strings"]["axis_eliminated"] );
  104.  
  105.         logString( "team eliminated, win: allies, allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] );
  106.  
  107.         thread endGame( "allies", game["strings"]["axis_eliminated"] );
  108.     }
  109.     else
  110.     {
  111.         logString( "tie, allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] );
  112.  
  113.         if ( level.teamBased )
  114.             thread endGame( "tie", game["strings"]["tie"] );
  115.         else
  116.             thread endGame( undefined, game["strings"]["tie"] );
  117.     }
  118. }
  119.  
  120.  
  121. default_onOneLeftEvent( team )
  122. {
  123.     if ( level.teamBased )
  124.     {      
  125.         assert( team == "allies" || team == "axis" );
  126.        
  127.         lastPlayer = getLastLivingPlayer( team );
  128.         lastPlayer thread giveLastOnTeamWarning();
  129.     }
  130.     else
  131.     {
  132.         lastPlayer = getLastLivingPlayer();
  133.        
  134.         logString( "last one alive, win: " + lastPlayer.name );
  135.         thread endGame( lastPlayer, &"MP_ENEMIES_ELIMINATED" );
  136.     }
  137.  
  138.     return true;
  139. }
  140.  
  141.  
  142. default_onTimeLimit()
  143. {
  144.     winner = undefined;
  145.    
  146.     if ( level.teamBased )
  147.     {
  148.         if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] )
  149.             winner = "tie";
  150.         else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] )
  151.             winner = "axis";
  152.         else
  153.             winner = "allies";
  154.  
  155.         logString( "time limit, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] );
  156.     }
  157.     else
  158.     {
  159.         winner = maps\mp\gametypes\_gamescore::getHighestScoringPlayer();
  160.  
  161.         if ( isDefined( winner ) )
  162.             logString( "time limit, win: " + winner.name );
  163.         else
  164.             logString( "time limit, tie" );
  165.     }
  166.    
  167.     thread endGame( winner, game["strings"]["time_limit_reached"] );
  168. }
  169.  
  170.  
  171. default_onHalfTime()
  172. {
  173.     winner = undefined;
  174.    
  175.     thread endGame( "halftime", game["strings"]["time_limit_reached"] );
  176. }
  177.  
  178.  
  179. forceEnd()
  180. {
  181.     if ( level.hostForcedEnd || level.forcedEnd )
  182.         return;
  183.  
  184.     winner = undefined;
  185.    
  186.     if ( level.teamBased )
  187.     {
  188.         if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] )
  189.             winner = "tie";
  190.         else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] )
  191.             winner = "axis";
  192.         else
  193.             winner = "allies";
  194.         logString( "host ended game, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] );
  195.     }
  196.     else
  197.     {
  198.         winner = maps\mp\gametypes\_gamescore::getHighestScoringPlayer();
  199.         if ( isDefined( winner ) )
  200.             logString( "host ended game, win: " + winner.name );
  201.         else
  202.             logString( "host ended game, tie" );
  203.     }
  204.    
  205.     level.forcedEnd = true;
  206.     level.hostForcedEnd = true;
  207.    
  208.     if ( level.splitscreen )
  209.         endString = &"MP_ENDED_GAME";
  210.     else
  211.         endString = &"MP_HOST_ENDED_GAME";
  212.    
  213.     thread endGame( winner, endString );
  214. }
  215.  
  216.  
  217. onScoreLimit()
  218. {
  219.     scoreText = game["strings"]["score_limit_reached"];
  220.     winner = undefined;
  221.    
  222.     if ( level.teamBased )
  223.     {
  224.         if ( game["teamScores"]["allies"] == game["teamScores"]["axis"] )
  225.             winner = "tie";
  226.         else if ( game["teamScores"]["axis"] > game["teamScores"]["allies"] )
  227.             winner = "axis";
  228.         else
  229.             winner = "allies";
  230.         logString( "scorelimit, win: " + winner + ", allies: " + game["teamScores"]["allies"] + ", opfor: " + game["teamScores"]["axis"] );
  231.     }
  232.     else
  233.     {
  234.         winner = maps\mp\gametypes\_gamescore::getHighestScoringPlayer();
  235.         if ( isDefined( winner ) )
  236.             logString( "scorelimit, win: " + winner.name );
  237.         else
  238.             logString( "scorelimit, tie" );
  239.     }
  240.    
  241.     thread endGame( winner, scoreText );
  242.     return true;
  243. }
  244.  
  245.  
  246. updateGameEvents()
  247. {
  248.     if ( matchMakingGame() && !level.inGracePeriod )
  249.     {
  250.         if ( level.teamBased )
  251.         {
  252.             // if allies disconnected, and axis still connected, axis wins round and game ends to lobby
  253.             if ( level.teamCount["allies"] < 1 && level.teamCount["axis"] > 0 && game["state"] == "playing" )
  254.             {
  255.                 //allies forfeited
  256.                 thread onForfeit( "allies" );
  257.                 return;
  258.             }
  259.            
  260.             // if axis disconnected, and allies still connected, allies wins round and game ends to lobby
  261.             if ( level.teamCount["axis"] < 1 && level.teamCount["allies"] > 0 && game["state"] == "playing" )
  262.             {
  263.                 //axis forfeited
  264.                 thread onForfeit( "axis" );
  265.                 return;
  266.             }
  267.    
  268.             if ( level.teamCount["axis"] > 0 && level.teamCount["allies"] > 0 )
  269.             {
  270.                 level.forfeitInProgress = undefined;
  271.                 level notify( "abort_forfeit" );
  272.             }
  273.         }
  274.         else
  275.         {
  276.             if ( level.teamCount["allies"] + level.teamCount["axis"] == 1 && level.maxPlayerCount > 1 )
  277.             {
  278.                 thread onForfeit();
  279.                 return;
  280.             }
  281.  
  282.             if ( level.teamCount["axis"] + level.teamCount["allies"] > 1 )
  283.             {
  284.                 level.forfeitInProgress = undefined;
  285.                 level notify( "abort_forfeit" );
  286.             }
  287.         }
  288.     }
  289.  
  290.     if ( !getGametypeNumLives() && (!isDefined( level.disableSpawning ) || !level.disableSpawning) )
  291.         return;
  292.        
  293.     if ( !gameHasStarted() )
  294.         return;
  295.    
  296.     if ( level.inGracePeriod )
  297.         return;
  298.  
  299.     if ( level.teamBased )
  300.     {
  301.         livesCount["allies"] = level.livesCount["allies"];
  302.         livesCount["axis"] = level.livesCount["axis"];
  303.  
  304.         if ( isDefined( level.disableSpawning ) && level.disableSpawning )
  305.         {
  306.             livesCount["allies"] = 0;
  307.             livesCount["axis"] = 0;
  308.         }
  309.        
  310.         // if both allies and axis were alive and now they are both dead in the same instance
  311.         if ( !level.aliveCount["allies"] && !level.aliveCount["axis"] && !livesCount["allies"] && !livesCount["axis"] )
  312.         {
  313.             return [[level.onDeadEvent]]( "all" );
  314.         }
  315.  
  316.         // if allies were alive and now they are not
  317.         if ( !level.aliveCount["allies"] && !livesCount["allies"] )
  318.         {
  319.             return [[level.onDeadEvent]]( "allies" );
  320.         }
  321.  
  322.         // if axis were alive and now they are not
  323.         if ( !level.aliveCount["axis"] && !livesCount["axis"] )
  324.         {
  325.             return [[level.onDeadEvent]]( "axis" );
  326.         }
  327.  
  328.         // one ally left
  329.         if ( level.aliveCount["allies"] == 1 && !livesCount["allies"] )
  330.         {
  331.             if ( !isDefined( level.oneLeftTime["allies"] ) )
  332.             {
  333.                 level.oneLeftTime["allies"] = getTime();
  334.                 return [[level.onOneLeftEvent]]( "allies" );
  335.             }
  336.         }
  337.  
  338.         // one axis left
  339.         if ( level.aliveCount["axis"] == 1 && !livesCount["axis"] )
  340.         {
  341.             if ( !isDefined( level.oneLeftTime["axis"] ) )
  342.             {
  343.                 level.oneLeftTime["axis"] = getTime();
  344.                 return [[level.onOneLeftEvent]]( "axis" );
  345.             }
  346.         }
  347.     }
  348.     else
  349.     {
  350.         // everyone is dead
  351.         if ( (!level.aliveCount["allies"] && !level.aliveCount["axis"]) && (!level.livesCount["allies"] && !level.livesCount["axis"]) )
  352.         {
  353.             return [[level.onDeadEvent]]( "all" );
  354.         }
  355.  
  356.         livePlayers = getPotentialLivingPlayers();
  357.        
  358.         if ( livePlayers.size == 1 )
  359.         {
  360.             return [[level.onOneLeftEvent]]( "all" );
  361.         }
  362.     }
  363. }
  364.  
  365.  
  366. waittillFinalKillcamDone()
  367. {
  368.     if ( !level.showingFinalKillcam )
  369.         return false;
  370.    
  371.     while ( level.showingFinalKillcam )
  372.         wait ( 0.05 );
  373.    
  374.     return true;
  375. }
  376.  
  377.  
  378. timeLimitClock_Intermission( waitTime )
  379. {
  380.     setGameEndTime( getTime() + int(waitTime*1000) );
  381.     clockObject = spawn( "script_origin", (0,0,0) );
  382.     clockObject hide();
  383.    
  384.     if ( waitTime >= 10.0 )
  385.         wait ( waitTime - 10.0 );
  386.        
  387.     for ( ;; )
  388.     {
  389.         clockObject playSound( "ui_mp_timer_countdown" );
  390.         wait ( 1.0 );
  391.     }  
  392. }
  393.  
  394.  
  395. waitForPlayers( maxTime )
  396. {
  397.     endTime = gettime() + maxTime * 1000 - 200;
  398.    
  399.     if ( level.teamBased )
  400.         while( (!level.hasSpawned[ "axis" ] || !level.hasSpawned[ "allies" ]) && gettime() < endTime )
  401.             wait ( 0.05 );
  402.     else
  403.         while ( level.maxPlayerCount < 2 && gettime() < endTime )
  404.             wait ( 0.05 );
  405. }
  406.  
  407.  
  408. prematchPeriod()
  409. {
  410.     level endon( "game_ended" );
  411.  
  412.     if ( level.prematchPeriod > 0 )
  413.     {
  414.         if ( level.console )
  415.         {
  416.             thread matchStartTimer( "match_starting_in", level.prematchPeriod );
  417.             wait ( level.prematchPeriod );
  418.         }
  419.         else
  420.         {
  421.             matchStartTimerPC();
  422.         }
  423.     }
  424.     else
  425.     {
  426.         matchStartTimerSkip();
  427.     }
  428.    
  429.     for ( index = 0; index < level.players.size; index++ )
  430.     {
  431.         level.players[index] freezeControlsWrapper( false );
  432.         level.players[index] enableWeapons();
  433.  
  434.         hintMessage = getObjectiveHintText( level.players[index].pers["team"] );
  435.         if ( !isDefined( hintMessage ) || !level.players[index].hasSpawned )
  436.             continue;
  437.  
  438.         level.players[index] setClientDvar( "scr_objectiveText", hintMessage );
  439.         level.players[index] thread maps\mp\gametypes\_hud_message::hintMessage( hintMessage );
  440.     }
  441.  
  442.     if ( game["state"] != "playing" )
  443.         return;
  444. }
  445.  
  446.  
  447. gracePeriod()
  448. {
  449.     level endon("game_ended");
  450.    
  451.     while ( level.inGracePeriod )
  452.     {
  453.         wait ( 1.0 );
  454.         level.inGracePeriod--;
  455.     }
  456.  
  457.     //wait ( level.gracePeriod );
  458.    
  459.     level notify ( "grace_period_ending" );
  460.     wait ( 0.05 );
  461.    
  462.     gameFlagSet( "graceperiod_done" );
  463.     level.inGracePeriod = false;
  464.    
  465.     if ( game["state"] != "playing" )
  466.         return;
  467.    
  468.     if ( getGametypeNumLives() )
  469.     {
  470.         // Players on a team but without a weapon show as dead since they can not get in this round
  471.         players = level.players;
  472.        
  473.         for ( i = 0; i < players.size; i++ )
  474.         {
  475.             player = players[i];
  476.            
  477.             if ( !player.hasSpawned && player.sessionteam != "spectator" && !isAlive( player ) )
  478.                 player.statusicon = "hud_status_dead";
  479.         }
  480.     }
  481.    
  482.     level thread updateGameEvents();
  483. }
  484.  
  485.  
  486. updateWinStats( winner )
  487. {
  488.     if ( !winner rankingEnabled() )
  489.         return;
  490.    
  491.     winner maps\mp\gametypes\_persistence::statAdd( "losses", -1 );
  492.    
  493.     println( "setting winner: " + winner maps\mp\gametypes\_persistence::statGet( "wins" ) );
  494.     winner maps\mp\gametypes\_persistence::statAdd( "wins", 1 );
  495.     winner updatePersRatio( "winLossRatio", "wins", "losses" );
  496.     winner maps\mp\gametypes\_persistence::statAdd( "currentWinStreak", 1 );
  497.    
  498.     cur_win_streak = winner maps\mp\gametypes\_persistence::statGet( "currentWinStreak" );
  499.     if ( cur_win_streak > winner maps\mp\gametypes\_persistence::statGet( "winStreak" ) )
  500.         winner maps\mp\gametypes\_persistence::statSet( "winStreak", cur_win_streak );
  501.    
  502.     winner maps\mp\gametypes\_persistence::statSetChild( "round", "win", true );
  503.     winner maps\mp\gametypes\_persistence::statSetChild( "round", "loss", false );
  504. }
  505.  
  506.  
  507. updateLossStats( loser )
  508. {
  509.     if ( !loser rankingEnabled() )
  510.         return;
  511.    
  512.     loser maps\mp\gametypes\_persistence::statAdd( "losses", 1 );
  513.     loser updatePersRatio( "winLossRatio", "wins", "losses" );
  514.     loser maps\mp\gametypes\_persistence::statSetChild( "round", "loss", true );
  515. }
  516.  
  517.  
  518. updateTieStats( loser )
  519. {  
  520.     if ( !loser rankingEnabled() )
  521.         return;
  522.    
  523.     loser maps\mp\gametypes\_persistence::statAdd( "losses", -1 );
  524.    
  525.     loser maps\mp\gametypes\_persistence::statAdd( "ties", 1 );
  526.     loser updatePersRatio( "winLossRatio", "wins", "losses" );
  527.     loser maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 );
  528. }
  529.  
  530.  
  531. updateWinLossStats( winner )
  532. {
  533.     if ( privateMatch() )
  534.         return;
  535.        
  536.     if ( !wasLastRound() )
  537.         return;
  538.        
  539.     players = level.players;
  540.  
  541.     if ( !isDefined( winner ) || ( isDefined( winner ) && isString( winner ) && winner == "tie" ) )
  542.     {
  543.         foreach ( player in level.players )
  544.         {
  545.             if ( isDefined( player.connectedPostGame ) )
  546.                 continue;
  547.  
  548.             if ( level.hostForcedEnd && player isHost() )
  549.             {
  550.                 player maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 );
  551.                 continue;
  552.             }
  553.                
  554.             updateTieStats( player );
  555.         }      
  556.     }
  557.     else if ( isPlayer( winner ) )
  558.     {
  559.         if ( level.hostForcedEnd && winner isHost() )
  560.         {
  561.             winner maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 );
  562.             return;
  563.         }
  564.                
  565.         updateWinStats( winner );
  566.     }
  567.     else if ( isString( winner ) )
  568.     {
  569.         foreach ( player in level.players )
  570.         {
  571.             if ( isDefined( player.connectedPostGame ) )
  572.                 continue;
  573.  
  574.             if ( level.hostForcedEnd && player isHost() )
  575.             {
  576.                 player maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 );
  577.                 continue;
  578.             }
  579.  
  580.             if ( winner == "tie" )
  581.                 updateTieStats( player );
  582.             else if ( player.pers["team"] == winner )
  583.                 updateWinStats( player );
  584.             else
  585.                 player maps\mp\gametypes\_persistence::statSet( "currentWinStreak", 0 );
  586.         }
  587.     }
  588. }
  589.  
  590.  
  591. freezePlayerForRoundEnd( delay )
  592. {
  593.     self endon ( "disconnect" );
  594.     self clearLowerMessages();
  595.    
  596.     if ( !isDefined( delay ) )
  597.         delay = 0.05;
  598.    
  599.     self closepopupMenu();
  600.     self closeInGameMenu();
  601.    
  602.     wait ( delay );
  603.     self freezeControlsWrapper( true );
  604. //  self disableWeapons();
  605. }
  606.  
  607.  
  608. updateMatchBonusScores( winner )
  609. {
  610.     if ( !game["timePassed"] )
  611.         return;
  612.  
  613.     if ( !matchMakingGame() )
  614.         return;
  615.  
  616.     if ( !getTimeLimit() || level.forcedEnd )
  617.     {
  618.         gameLength = getTimePassed() / 1000;       
  619.         // cap it at 20 minutes to avoid exploiting
  620.         gameLength = min( gameLength, 1200 );
  621.     }
  622.     else
  623.     {
  624.         gameLength = getTimeLimit() * 60;
  625.     }
  626.        
  627.     if ( level.teamBased )
  628.     {
  629.         if ( winner == "allies" )
  630.         {
  631.             winningTeam = "allies";
  632.             losingTeam = "axis";
  633.         }
  634.         else if ( winner == "axis" )
  635.         {
  636.             winningTeam = "axis";
  637.             losingTeam = "allies";
  638.         }
  639.         else
  640.         {
  641.             winningTeam = "tie";
  642.             losingTeam = "tie";
  643.         }
  644.  
  645.         if ( winningTeam != "tie" )
  646.         {
  647.             winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "win" );
  648.             loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "loss" );
  649.             setWinningTeam( winningTeam );
  650.         }
  651.         else
  652.         {
  653.             winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" );
  654.             loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" );
  655.         }
  656.        
  657.         foreach ( player in level.players )
  658.         {
  659.             if ( isDefined( player.connectedPostGame ) )
  660.                 continue;
  661.            
  662.             if ( !player rankingEnabled() )
  663.                 continue;
  664.            
  665.             if ( player.timePlayed["total"] < 1 || player.pers["participation"] < 1 )
  666.             {
  667.                 player thread maps\mp\gametypes\_rank::endGameUpdate();
  668.                 continue;
  669.             }
  670.    
  671.             // no bonus for hosts who force ends
  672.             if ( level.hostForcedEnd && player isHost() )
  673.                 continue;
  674.  
  675.             spm = player maps\mp\gametypes\_rank::getSPM();            
  676.             if ( winningTeam == "tie" )
  677.             {
  678.                 playerScore = int( (winnerScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) );
  679.                 player thread giveMatchBonus( "tie", playerScore );
  680.                 player.matchBonus = playerScore;
  681.             }
  682.             else if ( isDefined( player.pers["team"] ) && player.pers["team"] == winningTeam )
  683.             {
  684.                 playerScore = int( (winnerScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) );
  685.                 player thread giveMatchBonus( "win", playerScore );
  686.                 player.matchBonus = playerScore;
  687.             }
  688.             else if ( isDefined(player.pers["team"] ) && player.pers["team"] == losingTeam )
  689.             {
  690.                 playerScore = int( (loserScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) );
  691.                 player thread giveMatchBonus( "loss", playerScore );
  692.                 player.matchBonus = playerScore;
  693.             }
  694.         }
  695.     }
  696.     else
  697.     {
  698.         if ( isDefined( winner ) )
  699.         {
  700.             winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "win" );
  701.             loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "loss" );
  702.         }
  703.         else
  704.         {
  705.             winnerScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" );
  706.             loserScale = maps\mp\gametypes\_rank::getScoreInfoValue( "tie" );
  707.         }
  708.        
  709.         foreach ( player in level.players )
  710.         {
  711.             if ( isDefined( player.connectedPostGame ) )
  712.                 continue;
  713.            
  714.             if ( player.timePlayed["total"] < 1 || player.pers["participation"] < 1 )
  715.             {
  716.                 player thread maps\mp\gametypes\_rank::endGameUpdate();
  717.                 continue;
  718.             }
  719.            
  720.             spm = player maps\mp\gametypes\_rank::getSPM();
  721.  
  722.             isWinner = false;
  723.             for ( pIdx = 0; pIdx < min( level.placement["all"].size, 3 ); pIdx++ )
  724.             {
  725.                 if ( level.placement["all"][pIdx] != player )
  726.                     continue;
  727.                 isWinner = true;               
  728.             }
  729.            
  730.             if ( isWinner )
  731.             {
  732.                 playerScore = int( (winnerScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) );
  733.                 player thread giveMatchBonus( "win", playerScore );
  734.                 player.matchBonus = playerScore;
  735.             }
  736.             else
  737.             {
  738.                 playerScore = int( (loserScale * ((gameLength/60) * spm)) * (player.timePlayed["total"] / gameLength) );
  739.                 player thread giveMatchBonus( "loss", playerScore );
  740.                 player.matchBonus = playerScore;
  741.             }
  742.         }
  743.     }
  744. }
  745.  
  746.  
  747. giveMatchBonus( scoreType, score )
  748. {
  749.     self endon ( "disconnect" );
  750.  
  751.     level waittill ( "give_match_bonus" );
  752.    
  753.     self maps\mp\gametypes\_rank::giveRankXP( scoreType, score );
  754.     //logXPGains();
  755.    
  756.     self maps\mp\gametypes\_rank::endGameUpdate();
  757. }
  758.  
  759.  
  760. setXenonRanks( winner )
  761. {
  762.     players = level.players;
  763.  
  764.     for ( i = 0; i < players.size; i++ )
  765.     {
  766.         player = players[i];
  767.  
  768.         if( !isdefined(player.score) || !isdefined(player.pers["team"]) )
  769.             continue;
  770.  
  771.     }
  772.  
  773.     for ( i = 0; i < players.size; i++ )
  774.     {
  775.         player = players[i];
  776.  
  777.         if( !isdefined(player.score) || !isdefined(player.pers["team"]) )
  778.             continue;      
  779.        
  780.         setPlayerTeamRank( player, player.clientid, player.score - 5 * player.deaths );
  781.     }
  782.     sendranks();
  783. }
  784.  
  785.  
  786. checkTimeLimit( prevTimePassed )
  787. {
  788.     if ( isDefined( level.timeLimitOverride ) && level.timeLimitOverride )
  789.         return;
  790.    
  791.     if ( game["state"] != "playing" )
  792.     {
  793.         setGameEndTime( 0 );
  794.         return;
  795.     }
  796.        
  797.     if ( getTimeLimit() <= 0 )
  798.     {
  799.         if ( isDefined( level.startTime ) )
  800.             setGameEndTime( level.startTime );
  801.         else
  802.             setGameEndTime( 0 );
  803.         return;
  804.     }
  805.        
  806.     if ( !gameFlag( "prematch_done" ) )
  807.     {
  808.         setGameEndTime( 0 );
  809.         return;
  810.     }
  811.    
  812.     if ( !isdefined( level.startTime ) )
  813.         return;
  814.    
  815.     timeLeft = getTimeRemaining();
  816.    
  817.     // want this accurate to the millisecond
  818. //  if ( getHalfTime() && game["status"] != "halftime" )
  819. //      setGameEndTime( getTime() + (int(timeLeft) - int(getTimeLimit()*60*1000*0.5)) );
  820. //  else
  821.         setGameEndTime( getTime() + int(timeLeft) );
  822.  
  823.     if ( timeLeft > 0 )
  824.     {
  825.         if ( getHalfTime() && checkHalfTime( prevTimePassed ) )
  826.             [[level.onHalfTime]]();
  827.  
  828.         return;
  829.     }
  830.    
  831.     [[level.onTimeLimit]]();
  832. }
  833.  
  834.  
  835. checkHalfTime( prevTimePassed )
  836. {
  837.     if ( !level.teamBased )
  838.         return false;
  839.        
  840.     if ( getTimeLimit() )
  841.     {
  842.         halfTime = (getTimeLimit() * 60 * 1000) * 0.5;
  843.        
  844.         if ( getTimePassed() >= halfTime && prevTimePassed < halfTime && prevTimePassed > 0 )
  845.         {
  846.             game["roundMillisecondsAlreadyPassed"] = getTimePassed();
  847.             return true;
  848.         }
  849.     }
  850.    
  851.     return false;
  852. }
  853.  
  854.  
  855.  
  856. getTimeRemaining()
  857. {
  858.     return getTimeLimit() * 60 * 1000 - getTimePassed();
  859. }
  860.  
  861.  
  862. checkTeamScoreLimitSoon( team )
  863. {
  864.     assert( isDefined( team ) );
  865.  
  866.     if ( getWatchedDvar( "scorelimit" ) <= 0 || isObjectiveBased() )
  867.         return;
  868.        
  869.     if ( isDefined( level.scoreLimitOverride ) && level.scoreLimitOverride )
  870.         return;
  871.        
  872.     if ( !level.teamBased )
  873.         return;
  874.  
  875.     // No checks until a minute has passed to let wild data settle
  876.     if ( getTimePassed() < (60 * 1000) ) // 1 min
  877.         return;
  878.    
  879.     timeLeft = estimatedTimeTillScoreLimit( team );
  880.  
  881.     if ( timeLeft < 2 )
  882.         level notify( "match_ending_soon", "score" );
  883. }
  884.  
  885.  
  886. checkPlayerScoreLimitSoon()
  887. {
  888.     if ( getWatchedDvar( "scorelimit" ) <= 0 || isObjectiveBased() )
  889.         return;
  890.        
  891.     if ( level.teamBased )
  892.         return;
  893.  
  894.     // No checks until a minute has passed to let wild data settle
  895.     if ( getTimePassed() < (60 * 1000) ) // 1 min
  896.         return;
  897.  
  898.     timeLeft = self estimatedTimeTillScoreLimit();
  899.  
  900.     if ( timeLeft < 2 )
  901.         level notify( "match_ending_soon", "score" );
  902. }
  903.  
  904.  
  905. checkScoreLimit()
  906. {
  907.     if ( isObjectiveBased() )
  908.         return false;
  909.  
  910.     if ( isDefined( level.scoreLimitOverride ) && level.scoreLimitOverride )
  911.         return false;
  912.    
  913.     if ( game["state"] != "playing" )
  914.         return false;
  915.  
  916.     if ( getWatchedDvar( "scorelimit" ) <= 0 )
  917.         return false;
  918.  
  919.     if ( level.teamBased )
  920.     {
  921.         if( game["teamScores"]["allies"] < getWatchedDvar( "scorelimit" ) && game["teamScores"]["axis"] < getWatchedDvar( "scorelimit" ) )
  922.             return false;
  923.     }
  924.     else
  925.     {
  926.         if ( !isPlayer( self ) )
  927.             return false;
  928.  
  929.         if ( self.score < getWatchedDvar( "scorelimit" ) )
  930.             return false;
  931.     }
  932.  
  933.     return onScoreLimit();
  934. }
  935.  
  936.  
  937. updateGameTypeDvars()
  938. {
  939.     level endon ( "game_ended" );
  940.    
  941.     while ( game["state"] == "playing" )
  942.     {
  943.         // make sure we check time limit right when game ends
  944.         if ( isdefined( level.startTime ) )
  945.         {
  946.             if ( getTimeRemaining() < 3000 )
  947.             {
  948.                 wait .1;
  949.                 continue;
  950.             }
  951.         }
  952.         wait 1;
  953.     }
  954. }
  955.  
  956.  
  957. matchStartTimerPC()
  958. {
  959.     thread matchStartTimer( "waiting_for_teams", level.prematchPeriod + level.prematchPeriodEnd );
  960.    
  961.     waitForPlayers( level.prematchPeriod );
  962.    
  963.     if ( level.prematchPeriodEnd > 0 )
  964.         matchStartTimer( "match_starting_in", level.prematchPeriodEnd );
  965. }
  966.  
  967. matchStartTimer_Internal( countTime, matchStartTimer )
  968. {
  969.     waittillframeend; // wait till cleanup of previous start timer if multiple happen at once
  970.     visionSetNaked( "mpIntro", 0 );
  971.    
  972.     level endon( "match_start_timer_beginning" );
  973.     while ( countTime > 0 && !level.gameEnded )
  974.     {
  975.         matchStartTimer thread maps\mp\gametypes\_hud::fontPulse( level );
  976.         wait ( matchStartTimer.inFrames * 0.05 );
  977.         matchStartTimer setValue( countTime );
  978.         if ( countTime == 2 )
  979.             visionSetNaked( getDvar( "mapname" ), 3.0 );
  980.         countTime--;
  981.         wait ( 1 - (matchStartTimer.inFrames * 0.05) );
  982.     }
  983. }
  984.  
  985. matchStartTimer( type, duration )
  986. {
  987.     level notify( "match_start_timer_beginning" );
  988.    
  989.     matchStartText = createServerFontString( "objective", 1.5 );
  990.     matchStartText setPoint( "CENTER", "CENTER", 0, -40 );
  991.     matchStartText.sort = 1001;
  992.     matchStartText setText( game["strings"]["waiting_for_teams"] );
  993.     matchStartText.foreground = false;
  994.     matchStartText.hidewheninmenu = true;
  995.    
  996.     matchStartText setText( game["strings"][type] ); // "match begins in:"
  997.    
  998.     matchStartTimer = createServerFontString( "hudbig", 1 );
  999.     matchStartTimer setPoint( "CENTER", "CENTER", 0, 0 );
  1000.     matchStartTimer.sort = 1001;
  1001.     matchStartTimer.color = (1,1,0);
  1002.     matchStartTimer.foreground = false;
  1003.     matchStartTimer.hidewheninmenu = true;
  1004.    
  1005.     matchStartTimer maps\mp\gametypes\_hud::fontPulseInit();
  1006.  
  1007.     countTime = int( duration );
  1008.    
  1009.     if ( countTime >= 2 )
  1010.     {
  1011.         matchStartTimer_Internal( countTime, matchStartTimer );
  1012.         visionSetNaked( getDvar( "mapname" ), 3.0 );
  1013.     }
  1014.     else
  1015.     {
  1016.         visionSetNaked( "mpIntro", 0 );
  1017.         visionSetNaked( getDvar( "mapname" ), 1.0 );
  1018.     }
  1019.    
  1020.     matchStartTimer destroyElem();
  1021.     matchStartText destroyElem();
  1022. }
  1023.  
  1024. matchStartTimerSkip()
  1025. {
  1026.     visionSetNaked( getDvar( "mapname" ), 0 );
  1027. }
  1028.  
  1029.  
  1030. onRoundSwitch()
  1031. {
  1032.     if ( !isDefined( game["switchedsides"] ) )
  1033.         game["switchedsides"] = false;
  1034.    
  1035.     // overtime
  1036.     if ( game["roundsWon"]["allies"] == getWatchedDvar( "winlimit" ) - 1 && game["roundsWon"]["axis"] == getWatchedDvar( "winlimit" ) - 1 )
  1037.     {
  1038.         aheadTeam = getBetterTeam();
  1039.         if ( aheadTeam != game["defenders"] )
  1040.         {
  1041.             game["switchedsides"] = !game["switchedsides"];
  1042.         }
  1043.         else
  1044.         {
  1045.             level.halftimeSubCaption = "";
  1046.         }
  1047.         level.halftimeType = "overtime";
  1048.     }
  1049.     else
  1050.     {
  1051.         level.halftimeType = "halftime";
  1052.         game["switchedsides"] = !game["switchedsides"];
  1053.     }
  1054. }
  1055.  
  1056.  
  1057. checkRoundSwitch()
  1058. {
  1059.     if ( !level.teamBased )
  1060.         return false;
  1061.        
  1062.     if ( !isDefined( level.roundSwitch ) || !level.roundSwitch )
  1063.         return false;
  1064.        
  1065.     assert( game["roundsPlayed"] > 0 );
  1066.     if ( game["roundsPlayed"] % level.roundSwitch == 0 )
  1067.     {
  1068.         onRoundSwitch();
  1069.         return true;
  1070.     }
  1071.        
  1072.     return false;
  1073. }
  1074.  
  1075.  
  1076. // returns the best guess of the exact time until the scoreboard will be displayed and player control will be lost.
  1077. // returns undefined if time is not known
  1078. timeUntilRoundEnd()
  1079. {
  1080.     if ( level.gameEnded )
  1081.     {
  1082.         timePassed = (getTime() - level.gameEndTime) / 1000;
  1083.         timeRemaining = level.postRoundTime - timePassed;
  1084.        
  1085.         if ( timeRemaining < 0 )
  1086.             return 0;
  1087.        
  1088.         return timeRemaining;
  1089.     }
  1090.    
  1091.     if ( getTimeLimit() <= 0 )
  1092.         return undefined;
  1093.    
  1094.     if ( !isDefined( level.startTime ) )
  1095.         return undefined;
  1096.    
  1097.     tl = getTimeLimit();
  1098.    
  1099.     timePassed = (getTime() - level.startTime)/1000;
  1100.     timeRemaining = (getTimeLimit() * 60) - timePassed;
  1101.    
  1102.     if ( isDefined( level.timePaused ) )
  1103.         timeRemaining += level.timePaused;
  1104.    
  1105.     return timeRemaining + level.postRoundTime;
  1106. }
  1107.  
  1108.  
  1109.  
  1110. freeGameplayHudElems()
  1111. {
  1112.     // free up some hud elems so we have enough for other things.
  1113.    
  1114.     // perk icons
  1115.     if ( isdefined( self.perkicon ) )
  1116.     {
  1117.         if ( isdefined( self.perkicon[0] ) )
  1118.         {
  1119.             self.perkicon[0] destroyElem();
  1120.             self.perkname[0] destroyElem();
  1121.         }
  1122.         if ( isdefined( self.perkicon[1] ) )
  1123.         {
  1124.             self.perkicon[1] destroyElem();
  1125.             self.perkname[1] destroyElem();
  1126.         }
  1127.         if ( isdefined( self.perkicon[2] ) )
  1128.         {
  1129.             self.perkicon[2] destroyElem();
  1130.             self.perkname[2] destroyElem();
  1131.         }
  1132.     }
  1133.     self notify("perks_hidden"); // stop any threads that are waiting to hide the perk icons
  1134.    
  1135.     // lower message
  1136.     self.lowerMessage destroyElem();
  1137.     self.lowerTimer destroyElem();
  1138.    
  1139.     // progress bar
  1140.     if ( isDefined( self.proxBar ) )
  1141.         self.proxBar destroyElem();
  1142.     if ( isDefined( self.proxBarText ) )
  1143.         self.proxBarText destroyElem();
  1144. }
  1145.  
  1146.  
  1147. getHostPlayer()
  1148. {
  1149.     players = getEntArray( "player", "classname" );
  1150.    
  1151.     for ( index = 0; index < players.size; index++ )
  1152.     {
  1153.         if ( players[index] isHost() )
  1154.             return players[index];
  1155.     }
  1156. }
  1157.  
  1158.  
  1159. hostIdledOut()
  1160. {
  1161.     hostPlayer = getHostPlayer();
  1162.    
  1163.     // host never spawned
  1164.     if ( isDefined( hostPlayer ) && !hostPlayer.hasSpawned && !isDefined( hostPlayer.selectedClass ) )
  1165.         return true;
  1166.  
  1167.     return false;
  1168. }
  1169.  
  1170.  
  1171.  
  1172. roundEndWait( defaultDelay, matchBonus )
  1173. {
  1174.     //setSlowMotion( 1.0, 0.15, defaultDelay / 2 );
  1175.  
  1176.     notifiesDone = false;
  1177.     while ( !notifiesDone )
  1178.     {
  1179.         players = level.players;
  1180.         notifiesDone = true;
  1181.        
  1182.         foreach ( player in players )
  1183.         {
  1184.             if ( !isDefined( player.doingSplash ) )
  1185.                 continue;
  1186.  
  1187.             if ( !player maps\mp\gametypes\_hud_message::isDoingSplash() )
  1188.                 continue;
  1189.  
  1190.             notifiesDone = false;
  1191.         }
  1192.         wait ( 0.5 );
  1193.     }
  1194.  
  1195.     if ( !matchBonus )
  1196.     {
  1197.         wait ( defaultDelay );
  1198.         level notify ( "round_end_finished" );
  1199.         //setSlowMotion( 1.0, 1.0, 0.05 );
  1200.         return;
  1201.     }
  1202.  
  1203.     wait ( defaultDelay / 2 );
  1204.     level notify ( "give_match_bonus" );
  1205.     wait ( defaultDelay / 2 );
  1206.  
  1207.     notifiesDone = false;
  1208.     while ( !notifiesDone )
  1209.     {
  1210.         players = level.players;
  1211.         notifiesDone = true;
  1212.         foreach ( player in players )
  1213.         {
  1214.             if ( !isDefined( player.doingSplash ) )
  1215.                 continue;
  1216.  
  1217.             if ( !player maps\mp\gametypes\_hud_message::isDoingSplash() )
  1218.                 continue;
  1219.  
  1220.             notifiesDone = false;
  1221.         }
  1222.         wait ( 0.5 );
  1223.     }
  1224.     //setSlowMotion( 1.0, 1.0, 0.05);
  1225.    
  1226.     level notify ( "round_end_finished" );
  1227. }
  1228.  
  1229.  
  1230. roundEndDOF( time )
  1231. {
  1232.     self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
  1233. }
  1234.  
  1235.  
  1236. Callback_StartGameType()
  1237. {
  1238.     maps\mp\_load::main();
  1239.    
  1240.     levelFlagInit( "round_over", false );
  1241.     levelFlagInit( "game_over", false );
  1242.     levelFlagInit( "block_notifies", false );
  1243.  
  1244.     level.prematchPeriod = 0;
  1245.     level.prematchPeriodEnd = 0;
  1246.     level.postGameNotifies = 0;
  1247.    
  1248.     level.intermission = false;
  1249.    
  1250.     makeDvarServerInfo( "cg_thirdPersonAngle", 356 );
  1251.  
  1252.     makeDvarServerInfo( "scr_gameended", 0 );
  1253.  
  1254.     if ( !isDefined( game["gamestarted"] ) )
  1255.     {
  1256.         game["clientid"] = 0;
  1257.        
  1258.         alliesCharSet = getMapCustom( "allieschar" );
  1259.         if ( (!isDefined( alliesCharSet ) || alliesCharSet == "") )
  1260.         {
  1261.             if ( !isDefined( game["allies"] ) )
  1262.                 alliesCharSet = "us_army";
  1263.             else
  1264.                 alliesCharSet = game["allies"];
  1265.         }
  1266.  
  1267.         axisCharSet = getMapCustom( "axischar" );
  1268.         if ( (!isDefined( axisCharSet ) || axisCharSet == "") )
  1269.         {
  1270.             if ( !isDefined( game["axis"] ) )
  1271.                 axisCharSet = "opforce_composite";
  1272.             else
  1273.                 axisCharSet = game["axis"];
  1274.         }
  1275.  
  1276.         game["allies"] = alliesCharSet;
  1277.         game["axis"] = axisCharSet;
  1278.  
  1279.         if ( !isDefined( game["attackers"] ) || !isDefined( game["defenders"]  ) )
  1280.             thread error( "No attackers or defenders team defined in level .gsc." );
  1281.  
  1282.         if (  !isDefined( game["attackers"] ) )
  1283.             game["attackers"] = "allies";
  1284.         if (  !isDefined( game["defenders"] ) )
  1285.             game["defenders"] = "axis";
  1286.  
  1287.         if ( !isDefined( game["state"] ) )
  1288.             game["state"] = "playing";
  1289.    
  1290.         precacheStatusIcon( "hud_status_dead" );
  1291.         precacheStatusIcon( "hud_status_connecting" );
  1292.         precacheString( &"MPUI_REVIVING" );
  1293.         precacheString( &"MPUI_BEING_REVIVED" );
  1294.        
  1295.         precacheRumble( "damage_heavy" );
  1296.  
  1297.         precacheShader( "white" );
  1298.         precacheShader( "black" );
  1299.            
  1300.         game["strings"]["press_to_spawn"] = &"PLATFORM_PRESS_TO_SPAWN";
  1301.         if ( level.teamBased )
  1302.         {
  1303.             game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_TEAMS";
  1304.             game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
  1305.         }
  1306.         else
  1307.         {
  1308.             game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_MORE_PLAYERS";
  1309.             game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
  1310.         }
  1311.         game["strings"]["match_starting_in"] = &"MP_MATCH_STARTING_IN";
  1312.         game["strings"]["match_resuming_in"] = &"MP_MATCH_RESUMING_IN";
  1313.         game["strings"]["waiting_for_players"] = &"MP_WAITING_FOR_PLAYERS";
  1314.         game["strings"]["spawn_next_round"] = &"MP_SPAWN_NEXT_ROUND";
  1315.         game["strings"]["waiting_to_spawn"] = &"MP_WAITING_TO_SPAWN";
  1316.         game["strings"]["waiting_to_safespawn"] = &"MP_WAITING_TO_SAFESPAWN";
  1317.         game["strings"]["match_starting"] = &"MP_MATCH_STARTING";
  1318.         game["strings"]["change_class"] = &"MP_CHANGE_CLASS_NEXT_SPAWN";
  1319.         game["strings"]["last_stand"] = &"MPUI_LAST_STAND";
  1320.         game["strings"]["final_stand"] = &"MPUI_FINAL_STAND";
  1321.         game["strings"]["c4_death"] = &"MPUI_C4_DEATH";
  1322.        
  1323.         game["strings"]["cowards_way"] = &"PLATFORM_COWARDS_WAY_OUT";
  1324.        
  1325.         game["strings"]["tie"] = &"MP_MATCH_TIE";
  1326.         game["strings"]["round_draw"] = &"MP_ROUND_DRAW";
  1327.  
  1328.         game["strings"]["grabbed_flag"] = &"MP_GRABBED_FLAG_FIRST";
  1329.         game["strings"]["enemies_eliminated"] = &"MP_ENEMIES_ELIMINATED";
  1330.         game["strings"]["score_limit_reached"] = &"MP_SCORE_LIMIT_REACHED";
  1331.         game["strings"]["round_limit_reached"] = &"MP_ROUND_LIMIT_REACHED";
  1332.         game["strings"]["time_limit_reached"] = &"MP_TIME_LIMIT_REACHED";
  1333.         game["strings"]["players_forfeited"] = &"MP_PLAYERS_FORFEITED";
  1334.         game["strings"]["S.A.S Win"] = &"SAS_WIN";
  1335.         game["strings"]["Spetsnaz Win"] = &"SPETSNAZ_WIN";
  1336.  
  1337.         game["colors"]["blue"] = (0.25,0.25,0.75);
  1338.         game["colors"]["red"] = (0.75,0.25,0.25);
  1339.         game["colors"]["white"] = (1.0,1.0,1.0);
  1340.         game["colors"]["black"] = (0.0,0.0,0.0);
  1341.         game["colors"]["green"] = (0.25,0.75,0.25);
  1342.         game["colors"]["yellow"] = (0.65,0.65,0.0);
  1343.         game["colors"]["orange"] = (1.0,0.45,0.0);
  1344.  
  1345.         game["strings"]["allies_eliminated"] = maps\mp\gametypes\_teams::getTeamEliminatedString( "allies" );
  1346.         game["strings"]["allies_forfeited"] = maps\mp\gametypes\_teams::getTeamForfeitedString( "allies" );
  1347.         game["strings"]["allies_name"] = maps\mp\gametypes\_teams::getTeamName( "allies" );
  1348.         game["icons"]["allies"] = maps\mp\gametypes\_teams::getTeamIcon( "allies" );   
  1349.         game["colors"]["allies"] = maps\mp\gametypes\_teams::getTeamColor( "allies" ); 
  1350.  
  1351.         game["strings"]["axis_eliminated"] = maps\mp\gametypes\_teams::getTeamEliminatedString( "axis" );
  1352.         game["strings"]["axis_forfeited"] = maps\mp\gametypes\_teams::getTeamForfeitedString( "axis" );
  1353.         game["strings"]["axis_name"] = maps\mp\gametypes\_teams::getTeamName( "axis" );
  1354.         game["icons"]["axis"] = maps\mp\gametypes\_teams::getTeamIcon( "axis" );   
  1355.         game["colors"]["axis"] = maps\mp\gametypes\_teams::getTeamColor( "axis" ); 
  1356.        
  1357.         if ( game["colors"]["allies"] == (0,0,0) )
  1358.             game["colors"]["allies"] = (0.5,0.5,0.5);
  1359.  
  1360.         if ( game["colors"]["axis"] == (0,0,0) )
  1361.             game["colors"]["axis"] = (0.5,0.5,0.5);
  1362.  
  1363.         [[level.onPrecacheGameType]]();
  1364.  
  1365.         if ( level.console )
  1366.         {
  1367.             if ( !level.splitscreen )
  1368.                 level.prematchPeriod = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "graceperiod" );
  1369.         }
  1370.         else
  1371.         {
  1372.             // first round, so set up prematch
  1373.             level.prematchPeriod = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "playerwaittime" );
  1374.             level.prematchPeriodEnd = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "matchstarttime" );
  1375.         }
  1376.     }
  1377.  
  1378.     if ( !isDefined( game["status"] ) )
  1379.         game["status"] = "normal";
  1380.  
  1381.     makeDvarServerInfo( "ui_overtime", (game["status"] == "overtime") );
  1382.  
  1383.     if ( game["status"] != "overtime" && game["status"] != "halftime" )
  1384.     {
  1385.         game["teamScores"]["allies"] = 0;
  1386.         game["teamScores"]["axis"] = 0;
  1387.     }
  1388.    
  1389.     if( !isDefined( game["timePassed"] ) )
  1390.         game["timePassed"] = 0;
  1391.  
  1392.     if( !isDefined( game["roundsPlayed"] ) )
  1393.         game["roundsPlayed"] = 0;
  1394.  
  1395.     if ( !isDefined( game["roundsWon"] ) )
  1396.         game["roundsWon"] = [];
  1397.  
  1398.     if ( level.teamBased )
  1399.     {
  1400.         if ( !isDefined( game["roundsWon"]["axis"] ) )
  1401.             game["roundsWon"]["axis"] = 0;
  1402.         if ( !isDefined( game["roundsWon"]["allies"] ) )       
  1403.             game["roundsWon"]["allies"] = 0;
  1404.     }
  1405.    
  1406.     level.gameEnded = false;
  1407.     level.forcedEnd = false;
  1408.     level.hostForcedEnd = false;
  1409.  
  1410.     level.hardcoreMode = getDvarInt( "g_hardcore" );
  1411.     if ( level.hardcoreMode )
  1412.         logString( "game mode: hardcore" );
  1413.  
  1414.     level.dieHardMode = getDvarInt( "scr_diehard" );
  1415.    
  1416.     if ( !level.teamBased )
  1417.         level.dieHardMode = 0;
  1418.  
  1419.     if ( level.dieHardMode )
  1420.         logString( "game mode: diehard" );
  1421.  
  1422.     level.killstreakRewards = getDvarInt( "scr_game_hardpoints" );
  1423.  
  1424.     /#
  1425.     printLn( "SESSION INFO" );
  1426.     printLn( "=====================================" );
  1427.     printLn( "  Map:         " + level.script );
  1428.     printLn( "  Script:      " + level.gametype );
  1429.     printLn( "  HardCore:    " + level.hardcoreMode );
  1430.     printLn( "  Diehard:     " + level.dieHardMode );
  1431.     printLn( "  3rd Person:  " + getDvarInt( "camera_thirdperson" ) );
  1432.     printLn( "  Round:       " + game[ "roundsPlayed" ] );
  1433.     printLn( "  scr_" + level.gametype + "_scorelimit " + getDvar( "scr_" + level.gametype + "_scorelimit" ) );
  1434.     printLn( "  scr_" + level.gametype + "_roundlimit " +getDvar( "scr_" + level.gametype + "_roundlimit" ) );
  1435.     printLn( "  scr_" + level.gametype + "_winlimit " + getDvar( "scr_" + level.gametype + "_winlimit" ) );
  1436.     printLn( "  scr_" + level.gametype + "_timelimit " + getDvar( "scr_" + level.gametype + "_timelimit" ) );
  1437.     printLn( "  scr_" + level.gametype + "_numlives " + getDvar( "scr_" + level.gametype + "_numlives" ) );
  1438.     printLn( "  scr_" + level.gametype + "_halftime " + getDvar( "scr_" + level.gametype + "_halftime" ) );
  1439.     printLn( "  scr_" + level.gametype + "_roundswitch " + getDvar( "scr_" + level.gametype + "_roundswitch" ) );
  1440.     printLn( "=====================================" );
  1441.     #/
  1442.  
  1443.     // this gets set to false when someone takes damage or a gametype-specific event happens.
  1444.     level.useStartSpawns = true;
  1445.  
  1446.     // multiplier for score from objectives
  1447.     level.objectivePointsMod = 1;
  1448.  
  1449.     if ( matchMakingGame() )   
  1450.         level.maxAllowedTeamKills = 2;
  1451.     else
  1452.         level.maxAllowedTeamKills = -1;
  1453.        
  1454.     thread maps\mp\gametypes\_persistence::init();
  1455.     thread maps\mp\gametypes\_menus::init();
  1456.     thread maps\mp\gametypes\_hud::init();
  1457.     thread maps\mp\gametypes\_serversettings::init();
  1458.     thread maps\mp\gametypes\_teams::init();
  1459.     thread maps\mp\gametypes\_weapons::init();
  1460.     thread maps\mp\gametypes\_killcam::init();
  1461.     thread maps\mp\gametypes\_shellshock::init();
  1462.     thread maps\mp\gametypes\_deathicons::init();
  1463.     thread maps\mp\gametypes\_damagefeedback::init();
  1464.     thread maps\mp\gametypes\_healthoverlay::init();
  1465.     thread maps\mp\gametypes\_spectating::init();
  1466.     thread maps\mp\gametypes\_objpoints::init();
  1467.     thread maps\mp\gametypes\_gameobjects::init();
  1468.     thread maps\mp\gametypes\_spawnlogic::init();
  1469.     thread maps\mp\gametypes\_battlechatter_mp::init();
  1470.     thread maps\mp\gametypes\_music_and_dialog::init();
  1471.     thread maps\mp\_matchdata::init();
  1472.     thread maps\mp\_awards::init();
  1473.     thread maps\mp\_skill::init();
  1474.     thread maps\mp\_areas::init();
  1475.     thread maps\mp\killstreaks\_killstreaks::init();
  1476.     //thread maps\mp\_perks::init(); // No longer in use, removed from common scripts. (smart arrow)
  1477.     thread maps\mp\perks\_perks::init();
  1478.     thread maps\mp\_events::init();
  1479.     thread maps\mp\_defcon::init();
  1480.    
  1481.     if ( level.teamBased )
  1482.         thread maps\mp\gametypes\_friendicons::init();
  1483.        
  1484.     thread maps\mp\gametypes\_hud_message::init();
  1485.  
  1486.     if ( !level.console )
  1487.         thread maps\mp\gametypes\_quickmessages::init();
  1488.  
  1489.     foreach ( locString in game["strings"] )
  1490.         precacheString( locString );
  1491.  
  1492.     foreach ( icon in game["icons"] )
  1493.         precacheShader( icon );
  1494.  
  1495.     game["gamestarted"] = true;
  1496.  
  1497.     level.maxPlayerCount = 0;
  1498.     level.waveDelay["allies"] = 0;
  1499.     level.waveDelay["axis"] = 0;
  1500.     level.lastWave["allies"] = 0;
  1501.     level.lastWave["axis"] = 0;
  1502.     level.wavePlayerSpawnIndex["allies"] = 0;
  1503.     level.wavePlayerSpawnIndex["axis"] = 0;
  1504.     level.alivePlayers["allies"] = [];
  1505.     level.alivePlayers["axis"] = [];
  1506.     level.activePlayers = [];
  1507.  
  1508.     makeDvarServerInfo( "ui_scorelimit", 0 );
  1509.     makeDvarServerInfo( "ui_allow_classchange", getDvar( "ui_allow_classchange" ) );
  1510.     makeDvarServerInfo( "ui_allow_teamchange", 1 );
  1511.     setDvar( "ui_allow_teamchange", 1 );
  1512.    
  1513.     if ( getGametypeNumLives() )
  1514.         setdvar( "g_deadChat", 0 );
  1515.     else
  1516.         setdvar( "g_deadChat", 1 );
  1517.    
  1518.     waveDelay = getDvarInt( "scr_" + level.gameType + "_waverespawndelay" );
  1519.     if ( waveDelay )
  1520.     {
  1521.         level.waveDelay["allies"] = waveDelay;
  1522.         level.waveDelay["axis"] = waveDelay;
  1523.         level.lastWave["allies"] = 0;
  1524.         level.lastWave["axis"] = 0;
  1525.        
  1526.         level thread maps\mp\gametypes\_gamelogic::waveSpawnTimer();
  1527.     }
  1528.    
  1529.     gameFlagInit( "prematch_done", false );
  1530.    
  1531.     level.gracePeriod = 15;
  1532.    
  1533.     level.inGracePeriod = level.gracePeriod;
  1534.     gameFlagInit( "graceperiod_done", false );
  1535.    
  1536.     level.roundEndDelay = 4;
  1537.     level.halftimeRoundEndDelay = 4;
  1538.  
  1539.    
  1540.     if ( level.teamBased )
  1541.     {
  1542.         maps\mp\gametypes\_gamescore::updateTeamScore( "axis" );
  1543.         maps\mp\gametypes\_gamescore::updateTeamScore( "allies" );
  1544.     }
  1545.     else
  1546.     {
  1547.         thread maps\mp\gametypes\_gamescore::initialDMScoreUpdate();
  1548.     }
  1549.  
  1550.     thread updateUIScoreLimit();
  1551.     level notify ( "update_scorelimit" );
  1552.  
  1553.    
  1554.     [[level.onStartGameType]]();
  1555.    
  1556.     // this must be after onstartgametype for scr_showspawns to work when set at start of game
  1557.     /#
  1558.     thread maps\mp\gametypes\_dev::init();
  1559.     #/
  1560.    
  1561.     thread startGame();
  1562.  
  1563.     level thread updateWatchedDvars();
  1564.     level thread timeLimitThread();
  1565. }
  1566.  
  1567.  
  1568. Callback_CodeEndGame()
  1569. {
  1570.     endparty();
  1571.  
  1572.     if ( !level.gameEnded )
  1573.         level thread maps\mp\gametypes\_gamelogic::forceEnd();
  1574. }
  1575.  
  1576.  
  1577. timeLimitThread()
  1578. {
  1579.     level endon ( "game_ended" );
  1580.    
  1581.     prevTimePassed = getTimePassed();
  1582.    
  1583.     while ( game["state"] == "playing" )
  1584.     {
  1585.         thread checkTimeLimit( prevTimePassed );
  1586.         prevTimePassed = getTimePassed();
  1587.        
  1588.         // make sure we check time limit right when game ends
  1589.         if ( isdefined( level.startTime ) )
  1590.         {
  1591.             if ( getTimeRemaining() < 3000 )
  1592.             {
  1593.                 wait .1;
  1594.                 continue;
  1595.             }
  1596.         }
  1597.         wait 1;
  1598.     }  
  1599. }
  1600.  
  1601.  
  1602. updateUIScoreLimit()
  1603. {
  1604.     for ( ;; )
  1605.     {
  1606.         level waittill_either ( "update_scorelimit", "update_winlimit" );
  1607.        
  1608.         if ( !isRoundBased() || !isObjectiveBased() )
  1609.         {
  1610.             setDvar( "ui_scorelimit", getWatchedDvar( "scorelimit" ) );
  1611.             thread checkScoreLimit();
  1612.         }
  1613.         else
  1614.         {
  1615.             setDvar( "ui_scorelimit", getWatchedDvar( "winlimit" ) );
  1616.         }
  1617.     }
  1618. }
  1619.  
  1620.  
  1621. playTickingSound()
  1622. {
  1623.     self endon("death");
  1624.     self endon("stop_ticking");
  1625.     level endon("game_ended");
  1626.    
  1627.     time = level.bombTimer;
  1628.    
  1629.     while(1)
  1630.     {
  1631.         self playSound( "ui_mp_suitcasebomb_timer" );
  1632.        
  1633.         if ( time > 10 )
  1634.         {
  1635.             time -= 1;
  1636.             wait 1;
  1637.         }
  1638.         else if ( time > 4 )
  1639.         {
  1640.             time -= .5;
  1641.             wait .5;
  1642.         }
  1643.         else if ( time > 1 )
  1644.         {
  1645.             time -= .4;
  1646.             wait .4;
  1647.         }
  1648.         else
  1649.         {
  1650.             time -= .3;
  1651.             wait .3;
  1652.         }
  1653.         maps\mp\gametypes\_hostmigration::waitTillHostMigrationDone();
  1654.     }
  1655. }
  1656.  
  1657. stopTickingSound()
  1658. {
  1659.     self notify("stop_ticking");
  1660. }
  1661.  
  1662. timeLimitClock()
  1663. {
  1664.     level endon ( "game_ended" );
  1665.    
  1666.     wait .05;
  1667.    
  1668.     clockObject = spawn( "script_origin", (0,0,0) );
  1669.     clockObject hide();
  1670.    
  1671.     while ( game["state"] == "playing" )
  1672.     {
  1673.         if ( !level.timerStopped && getTimeLimit() )
  1674.         {
  1675.             timeLeft = getTimeRemaining() / 1000;
  1676.             timeLeftInt = int(timeLeft + 0.5); // adding .5 and flooring rounds it.
  1677.            
  1678.             if ( getHalfTime() && timeLeftInt > (getTimeLimit()*60) * 0.5 )
  1679.                 timeLeftInt -= int((getTimeLimit()*60) * 0.5);
  1680.            
  1681.             if ( (timeLeftInt >= 30 && timeLeftInt <= 60) )
  1682.                 level notify ( "match_ending_soon", "time" );
  1683.  
  1684.             if ( timeLeftInt <= 10 || (timeLeftInt <= 30 && timeLeftInt % 2 == 0) )
  1685.             {
  1686.                 level notify ( "match_ending_very_soon" );
  1687.                 // don't play a tick at exactly 0 seconds, that's when something should be happening!
  1688.                 if ( timeLeftInt == 0 )
  1689.                     break;
  1690.                
  1691.                 clockObject playSound( "ui_mp_timer_countdown" );
  1692.             }
  1693.            
  1694.             // synchronize to be exactly on the second
  1695.             if ( timeLeft - floor(timeLeft) >= .05 )
  1696.                 wait timeLeft - floor(timeLeft);
  1697.         }
  1698.  
  1699.         wait ( 1.0 );
  1700.     }
  1701. }
  1702.  
  1703.  
  1704. gameTimer()
  1705. {
  1706.     level endon ( "game_ended" );
  1707.    
  1708.     level waittill("prematch_over");
  1709.    
  1710.     level.startTime = getTime();
  1711.     level.discardTime = 0;
  1712.    
  1713.     if ( isDefined( game["roundMillisecondsAlreadyPassed"] ) )
  1714.     {
  1715.         level.startTime -= game["roundMillisecondsAlreadyPassed"];
  1716.         game["roundMillisecondsAlreadyPassed"] = undefined;
  1717.     }
  1718.    
  1719.     prevtime = gettime();
  1720.    
  1721.     while ( game["state"] == "playing" )
  1722.     {
  1723.         if ( !level.timerStopped )
  1724.         {
  1725.             // the wait isn't always exactly 1 second. dunno why.
  1726.             game["timePassed"] += gettime() - prevtime;
  1727.         }
  1728.         prevtime = gettime();
  1729.         wait ( 1.0 );
  1730.     }
  1731. }
  1732.  
  1733. UpdateTimerPausedness()
  1734. {
  1735.     shouldBeStopped = level.timerStoppedForGameMode || isDefined( level.hostMigrationTimer );
  1736.     if ( !gameFlag( "prematch_done" ) )
  1737.         shouldBeStopped = false;
  1738.    
  1739.     if ( !level.timerStopped && shouldBeStopped )
  1740.     {
  1741.         level.timerStopped = true;
  1742.         level.timerPauseTime = gettime();
  1743.     }
  1744.     else if ( level.timerStopped && !shouldBeStopped )
  1745.     {
  1746.         level.timerStopped = false;
  1747.         level.discardTime += gettime() - level.timerPauseTime;
  1748.     }
  1749. }
  1750.  
  1751. pauseTimer()
  1752. {
  1753.     level.timerStoppedForGameMode = true;
  1754.     UpdateTimerPausedness();
  1755. }
  1756.  
  1757. resumeTimer()
  1758. {
  1759.     level.timerStoppedForGameMode = false;
  1760.     UpdateTimerPausedness();
  1761. }
  1762.  
  1763.  
  1764. startGame()
  1765. {
  1766.     thread gameTimer();
  1767.     level.timerStopped = false;
  1768.     level.timerStoppedForGameMode = false;
  1769.     thread maps\mp\gametypes\_spawnlogic::spawnPerFrameUpdate();
  1770.  
  1771.     prematchPeriod();
  1772.     gameFlagSet( "prematch_done" );
  1773.     level notify("prematch_over");
  1774.    
  1775.     UpdateTimerPausedness();
  1776.    
  1777.     thread timeLimitClock();
  1778.     thread gracePeriod();
  1779.  
  1780.     thread maps\mp\gametypes\_missions::roundBegin();  
  1781. }
  1782.  
  1783.  
  1784. waveSpawnTimer()
  1785. {
  1786.     level endon( "game_ended" );
  1787.  
  1788.     while ( game["state"] == "playing" )
  1789.     {
  1790.         time = getTime();
  1791.        
  1792.         if ( time - level.lastWave["allies"] > (level.waveDelay["allies"] * 1000) )
  1793.         {
  1794.             level notify ( "wave_respawn_allies" );
  1795.             level.lastWave["allies"] = time;
  1796.             level.wavePlayerSpawnIndex["allies"] = 0;
  1797.         }
  1798.  
  1799.         if ( time - level.lastWave["axis"] > (level.waveDelay["axis"] * 1000) )
  1800.         {
  1801.             level notify ( "wave_respawn_axis" );
  1802.             level.lastWave["axis"] = time;
  1803.             level.wavePlayerSpawnIndex["axis"] = 0;
  1804.         }
  1805.        
  1806.         wait ( 0.05 );
  1807.     }
  1808. }
  1809.  
  1810.  
  1811. getBetterTeam()
  1812. {
  1813.     kills["allies"] = 0;
  1814.     kills["axis"] = 0;
  1815.     deaths["allies"] = 0;
  1816.     deaths["axis"] = 0;
  1817.    
  1818.     foreach ( player in level.players )
  1819.     {
  1820.         team = player.pers["team"];
  1821.         if ( isDefined( team ) && (team == "allies" || team == "axis") )
  1822.         {
  1823.             kills[ team ] += player.kills;
  1824.             deaths[ team ] += player.deaths;
  1825.         }
  1826.     }
  1827.    
  1828.     if ( kills["allies"] > kills["axis"] )
  1829.         return "allies";
  1830.     else if ( kills["axis"] > kills["allies"] )
  1831.         return "axis";
  1832.    
  1833.     // same number of kills
  1834.  
  1835.     if ( deaths["allies"] < deaths["axis"] )
  1836.         return "allies";
  1837.     else if ( deaths["axis"] < deaths["allies"] )
  1838.         return "axis";
  1839.    
  1840.     // same number of deaths
  1841.    
  1842.     if ( randomint(2) == 0 )
  1843.         return "allies";
  1844.     return "axis";
  1845. }
  1846.  
  1847.  
  1848. rankedMatchUpdates( winner )
  1849. {
  1850.     if ( matchMakingGame() )
  1851.     {
  1852.         setXenonRanks();
  1853.        
  1854.         if ( hostIdledOut() )
  1855.         {
  1856.             level.hostForcedEnd = true;
  1857.             logString( "host idled out" );
  1858.             endLobby();
  1859.         }
  1860.  
  1861.         updateMatchBonusScores( winner );
  1862.     }
  1863.  
  1864.     updateWinLossStats( winner );
  1865. }
  1866.  
  1867.  
  1868. displayRoundEnd( winner, endReasonText )
  1869. {
  1870.     foreach ( player in level.players )
  1871.     {
  1872.         if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" )
  1873.             continue;
  1874.        
  1875.         if ( level.teamBased )
  1876.             player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( winner, true, endReasonText );
  1877.         else
  1878.             player thread maps\mp\gametypes\_hud_message::outcomeNotify( winner, endReasonText );
  1879.     }
  1880.  
  1881.     if ( !wasLastRound() )
  1882.         level notify ( "round_win", winner );
  1883.    
  1884.     if ( wasLastRound() )
  1885.         roundEndWait( level.roundEndDelay, false );
  1886.     else
  1887.         roundEndWait( level.roundEndDelay, true ); 
  1888. }
  1889.  
  1890.  
  1891. displayGameEnd( winner, endReasonText )
  1892. {  
  1893.     // catching gametype, since DM forceEnd sends winner as player entity, instead of string
  1894.     foreach ( player in level.players )
  1895.     {
  1896.         if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" )
  1897.             continue;
  1898.        
  1899.         if ( level.teamBased )
  1900.             player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( winner, false, endReasonText );
  1901.         else
  1902.             player thread maps\mp\gametypes\_hud_message::outcomeNotify( winner, endReasonText );
  1903.     }
  1904.    
  1905.     level notify ( "game_win", winner );
  1906.    
  1907.     roundEndWait( level.postRoundTime, true );
  1908. }
  1909.  
  1910.  
  1911. displayRoundSwitch()
  1912. {
  1913.     switchType = level.halftimeType;
  1914.     if ( switchType == "halftime" )
  1915.     {
  1916.         if ( getWatchedDvar( "roundlimit" ) )
  1917.         {
  1918.             if ( (game["roundsPlayed"] * 2) == getWatchedDvar( "roundlimit" ) )
  1919.                 switchType = "halftime";
  1920.             else
  1921.                 switchType = "intermission";
  1922.         }
  1923.         else if ( getWatchedDvar( "winlimit" ) )
  1924.         {
  1925.             if ( game["roundsPlayed"] == (getWatchedDvar( "winlimit" ) - 1) )
  1926.                 switchType = "halftime";
  1927.             else
  1928.                 switchType = "intermission";
  1929.         }
  1930.         else
  1931.         {
  1932.             switchType = "intermission";
  1933.         }
  1934.     }
  1935.  
  1936.     level notify ( "round_switch", switchType );
  1937.  
  1938.     foreach ( player in level.players )
  1939.     {
  1940.         if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" )
  1941.             continue;
  1942.        
  1943.         player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( switchType, true, level.halftimeSubCaption );
  1944.     }
  1945.    
  1946.     roundEndWait( level.halftimeRoundEndDelay, false );
  1947. }
  1948.  
  1949.  
  1950. endGameOvertime( winner, endReasonText )
  1951. {
  1952.     // freeze players
  1953.     foreach ( player in level.players )
  1954.     {
  1955.         player thread freezePlayerForRoundEnd( 0 );
  1956.         player thread roundEndDoF( 4.0 );
  1957.        
  1958.         player freeGameplayHudElems();
  1959.  
  1960.         player setClientDvars( "cg_everyoneHearsEveryone", 1 );
  1961.         player setClientDvars( "cg_drawSpectatorMessages", 0,
  1962.                                "g_compassShowEnemies", 0 );
  1963.                                
  1964.         if ( player.pers["team"] == "spectator" )
  1965.             player thread maps\mp\gametypes\_playerlogic::spawnIntermission();
  1966.     }
  1967.  
  1968.     level notify ( "round_switch", "overtime" );
  1969.  
  1970.     // catching gametype, since DM forceEnd sends winner as player entity, instead of string
  1971.     foreach ( player in level.players )
  1972.     {
  1973.         if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" )
  1974.             continue;
  1975.        
  1976.         if ( level.teamBased )
  1977.             player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( winner, false, endReasonText );
  1978.         else
  1979.             player thread maps\mp\gametypes\_hud_message::outcomeNotify( winner, endReasonText );
  1980.     }
  1981.    
  1982.     roundEndWait( level.roundEndDelay, false );
  1983.  
  1984.     game["status"] = "overtime";
  1985.     level notify ( "restarting" );
  1986.     game["state"] = "playing";
  1987.     map_restart( true );
  1988. }
  1989.  
  1990.  
  1991.  
  1992. endGameHalfTime()
  1993. {
  1994.     visionSetNaked( "mpOutro", 0.5 );      
  1995.     setDvar( "scr_gameended", 2 );
  1996.  
  1997.     game["switchedsides"] = !game["switchedsides"];
  1998.  
  1999.     // freeze players
  2000.     foreach ( player in level.players )
  2001.     {
  2002.         player thread freezePlayerForRoundEnd( 0 );
  2003.         player thread roundEndDoF( 4.0 );
  2004.        
  2005.         player freeGameplayHudElems();
  2006.  
  2007.         player setClientDvars( "cg_everyoneHearsEveryone", 1 );
  2008.         player setClientDvars( "cg_drawSpectatorMessages", 0,
  2009.                                "g_compassShowEnemies", 0 );
  2010.                                
  2011.         if ( player.pers["team"] == "spectator" )
  2012.             player thread maps\mp\gametypes\_playerlogic::spawnIntermission();
  2013.     }
  2014.  
  2015.     foreach ( player in level.players )
  2016.         player.pers["stats"] = player.stats;
  2017.  
  2018.     level notify ( "round_switch", "halftime" );
  2019.        
  2020.     foreach ( player in level.players )
  2021.     {
  2022.         if ( isDefined( player.connectedPostGame ) || player.pers["team"] == "spectator" )
  2023.             continue;
  2024.  
  2025.         player thread maps\mp\gametypes\_hud_message::teamOutcomeNotify( "halftime", true, level.halftimeSubCaption );
  2026.     }
  2027.    
  2028.     roundEndWait( level.roundEndDelay, false );
  2029.  
  2030.     game["status"] = "halftime";
  2031.     level notify ( "restarting" );
  2032.     game["state"] = "playing";
  2033.     map_restart( true );
  2034. }
  2035.  
  2036.  
  2037. endGame( winner, endReasonText, nukeDetonated )
  2038. {
  2039.     if ( !isDefined(nukeDetonated) )
  2040.         nukeDetonated = false;
  2041.    
  2042.     // return if already ending via host quit or victory, or nuke incoming
  2043.     if ( game["state"] == "postgame" || level.gameEnded || (isDefined(level.nukeIncoming) && !nukeDetonated) && ( !isDefined( level.gtnw ) || !level.gtnw ) )
  2044.         return;
  2045.  
  2046.     game["state"] = "postgame";
  2047.  
  2048.     level.gameEndTime = getTime();
  2049.     level.gameEnded = true;
  2050.     level.inGracePeriod = false;
  2051.     level notify ( "game_ended", winner );
  2052.     levelFlagSet( "game_over" );
  2053.     levelFlagSet( "block_notifies" );
  2054.     waitframe(); // give "game_ended" notifies time to process
  2055.    
  2056.     setGameEndTime( 0 ); // stop/hide the timers
  2057.    
  2058.     maps\mp\gametypes\_playerlogic::printPredictedSpawnpointCorrectness();
  2059.    
  2060.     if ( isDefined( winner ) && isString( winner ) && winner == "overtime" )
  2061.     {
  2062.         endGameOvertime( winner, endReasonText );
  2063.         return;
  2064.     }
  2065.    
  2066.     if ( isDefined( winner ) && isString( winner ) && winner == "halftime" )
  2067.     {
  2068.         endGameHalftime();
  2069.         return;
  2070.     }
  2071.  
  2072.     game["roundsPlayed"]++;
  2073.    
  2074.     if ( level.teamBased )
  2075.     {
  2076.         if ( winner == "axis" || winner == "allies" )
  2077.             game["roundsWon"][winner]++;
  2078.  
  2079.         maps\mp\gametypes\_gamescore::updateTeamScore( "axis" );
  2080.         maps\mp\gametypes\_gamescore::updateTeamScore( "allies" );
  2081.     }
  2082.     else
  2083.     {
  2084.         if ( isDefined( winner ) && isPlayer( winner ) )
  2085.             game["roundsWon"][winner.guid]++;
  2086.     }
  2087.    
  2088.     maps\mp\gametypes\_gamescore::updatePlacement();
  2089.  
  2090.     rankedMatchUpdates( winner );
  2091.  
  2092.     foreach ( player in level.players )
  2093.     {
  2094.         player setClientDvar( "ui_opensummary", 1 );
  2095.     }
  2096.    
  2097.     setDvar( "g_deadChat", 1 );
  2098.     setDvar( "ui_allow_teamchange", 0 );
  2099.  
  2100.     // freeze players
  2101.     foreach ( player in level.players )
  2102.     {
  2103.         player thread freezePlayerForRoundEnd( 1.0 );
  2104.         player thread roundEndDoF( 4.0 );
  2105.        
  2106.         player freeGameplayHudElems();
  2107.  
  2108.         player setClientDvars( "cg_everyoneHearsEveryone", 1 );
  2109.         player setClientDvars( "cg_drawSpectatorMessages", 0,
  2110.                                "g_compassShowEnemies", 0,
  2111.                                "cg_fovScale", 1 );
  2112.                                
  2113.         if ( player.pers["team"] == "spectator" )
  2114.             player thread maps\mp\gametypes\_playerlogic::spawnIntermission();
  2115.     }
  2116.  
  2117.     if( !nukeDetonated )
  2118.         visionSetNaked( "mpOutro", 0.5 );      
  2119.    
  2120.     // End of Round
  2121.     if ( !wasOnlyRound() && !nukeDetonated )
  2122.     {
  2123.         setDvar( "scr_gameended", 2 );
  2124.    
  2125.         displayRoundEnd( winner, endReasonText );
  2126.  
  2127.         if ( level.showingFinalKillcam )
  2128.         {
  2129.             foreach ( player in level.players )
  2130.                 player notify ( "reset_outcome" );
  2131.  
  2132.             level notify ( "game_cleanup" );
  2133.  
  2134.             waittillFinalKillcamDone();
  2135.         }
  2136.                
  2137.         if ( !wasLastRound() )
  2138.         {
  2139.             levelFlagClear( "block_notifies" );
  2140.             if ( checkRoundSwitch() )
  2141.                 displayRoundSwitch();
  2142.  
  2143.             foreach ( player in level.players )
  2144.                 player.pers["stats"] = player.stats;
  2145.  
  2146.             level notify ( "restarting" );
  2147.             game["state"] = "playing";
  2148.             map_restart( true );
  2149.             return;
  2150.         }
  2151.        
  2152.         if ( !level.forcedEnd )
  2153.             endReasonText = updateEndReasonText( winner );
  2154.     }              
  2155.  
  2156.     foreach ( player in level.players )
  2157.     {
  2158.         player thread maps\mp\gametypes\_missions::DispNextMap();
  2159.     }
  2160.  
  2161.     setDvar( "scr_gameended", 1 );
  2162.    
  2163.     if ( !isDefined( game["clientMatchDataDef"] ) )
  2164.     {
  2165.         game["clientMatchDataDef"] = "mp/clientmatchdata.def";
  2166.         setClientMatchDataDef( game["clientMatchDataDef"] );
  2167.     }
  2168.  
  2169.     maps\mp\gametypes\_missions::roundEnd( winner );
  2170.  
  2171.     displayGameEnd( winner, endReasonText );
  2172.  
  2173.     if ( level.showingFinalKillcam && wasOnlyRound() )
  2174.     {
  2175.         foreach ( player in level.players )
  2176.             player notify ( "reset_outcome" );
  2177.  
  2178.         level notify ( "game_cleanup" );
  2179.  
  2180.         waittillFinalKillcamDone();
  2181.     }
  2182.    
  2183.     levelFlagClear( "block_notifies" );
  2184.  
  2185.     level.intermission = true;
  2186.  
  2187.     level notify ( "spawning_intermission" );
  2188.    
  2189.     foreach ( player in level.players )
  2190.     {
  2191.         player closepopupMenu();
  2192.         player closeInGameMenu();
  2193.         player notify ( "reset_outcome" );
  2194.         player thread maps\mp\gametypes\_playerlogic::spawnIntermission();
  2195.     }
  2196.  
  2197.     processLobbyData();
  2198.  
  2199.     wait ( 1.0 );
  2200.  
  2201.     if ( matchMakingGame() )
  2202.         sendMatchData();
  2203.  
  2204.     foreach ( player in level.players )
  2205.         player.pers["stats"] = player.stats;
  2206.  
  2207.     //logString( "game ended" );
  2208.     if( !nukeDetonated && !level.postGameNotifies )
  2209.     {
  2210.         if ( !wasOnlyRound() )
  2211.             wait 6.0;
  2212.         else
  2213.             wait 3.0;
  2214.     }
  2215.     else
  2216.     {
  2217.         wait ( min( 10.0, 4.0 + level.postGameNotifies ) );
  2218.     }
  2219.    
  2220.     if(getDvar("sv_maprotation")=="")
  2221.     {
  2222.         level notify( "exitLevel_called" );
  2223.         exitLevel( false );
  2224.     }
  2225.     else
  2226.     {
  2227.         mapname = getDvar("sv_maprotation");
  2228.         level notify( "exitLevel_called" );
  2229.         map(mapname);
  2230.     }
  2231. }
  2232.  
  2233. updateEndReasonText( winner )
  2234. {
  2235.     if ( !level.teamBased )
  2236.         return true;
  2237.  
  2238.     if ( hitRoundLimit() )
  2239.         return &"MP_ROUND_LIMIT_REACHED";
  2240.    
  2241.     if ( hitWinLimit() )
  2242.         return &"MP_SCORE_LIMIT_REACHED";
  2243.    
  2244.     if ( winner == "axis" )
  2245.         return &"SPETSNAZ_WIN";
  2246.     else
  2247.         return &"SAS_WIN";
  2248. }
  2249.  
  2250. estimatedTimeTillScoreLimit( team )
  2251. {
  2252.     assert( isPlayer( self ) || isDefined( team ) );
  2253.  
  2254.     scorePerMinute = getScorePerMinute( team );
  2255.     scoreRemaining = getScoreRemaining( team );
  2256.  
  2257.     estimatedTimeLeft = 999999;
  2258.     if ( scorePerMinute )
  2259.         estimatedTimeLeft = scoreRemaining / scorePerMinute;
  2260.    
  2261.     //println( "estimatedTimeLeft: " + estimatedTimeLeft );
  2262.     return estimatedTimeLeft;
  2263. }
  2264.  
  2265. getScorePerMinute( team )
  2266. {
  2267.     assert( isPlayer( self ) || isDefined( team ) );
  2268.  
  2269.     scoreLimit = getWatchedDvar( "scorelimit" );
  2270.     timeLimit = getTimeLimit();
  2271.     minutesPassed = (getTimePassed() / (60*1000)) + 0.0001;
  2272.  
  2273.     if ( isPlayer( self ) )
  2274.         scorePerMinute = self.score / minutesPassed;
  2275.     else
  2276.         scorePerMinute = getTeamScore( team ) / minutesPassed;
  2277.        
  2278.     return scorePerMinute;
  2279. }
  2280.  
  2281. getScoreRemaining( team )
  2282. {
  2283.     assert( isPlayer( self ) || isDefined( team ) );
  2284.  
  2285.     scoreLimit = getWatchedDvar( "scorelimit" );
  2286.  
  2287.     if ( isPlayer( self ) )
  2288.         scoreRemaining = scoreLimit - self.score;
  2289.     else
  2290.         scoreRemaining = scoreLimit - getTeamScore( team );
  2291.        
  2292.     return scoreRemaining;
  2293. }
  2294.  
  2295. giveLastOnTeamWarning()
  2296. {
  2297.     self endon("death");
  2298.     self endon("disconnect");
  2299.     level endon( "game_ended" );
  2300.  
  2301.     self waitTillRecoveredHealth( 3 );
  2302.  
  2303.     otherTeam = getOtherTeam( self.pers["team"] );
  2304.     thread teamPlayerCardSplash( "callout_lastteammemberalive", self, self.pers["team"] );
  2305.     thread teamPlayerCardSplash( "callout_lastenemyalive", self, otherTeam );
  2306.     level notify ( "last_alive", self );
  2307. }
  2308.  
  2309. processLobbyData()
  2310. {
  2311.     curPlayer = 0;
  2312.     foreach ( player in level.players )
  2313.     {
  2314.         if ( !isDefined( player ) )
  2315.             continue;
  2316.  
  2317.         player.clientMatchDataId = curPlayer;
  2318.         curPlayer++;
  2319.  
  2320.         // on PS3 cap long names
  2321.         if ( level.ps3 && (player.name.size > level.MaxNameLength) )
  2322.         {
  2323.             playerName = "";
  2324.             for ( i = 0; i < level.MaxNameLength-3; i++ )
  2325.                 playerName += player.name[i];
  2326.  
  2327.             playerName += "...";
  2328.         }
  2329.         else
  2330.         {
  2331.             playerName = player.name;
  2332.         }
  2333.        
  2334.         setClientMatchData( "players", player.clientMatchDataId, "xuid", playerName );     
  2335.     }
  2336.    
  2337.     maps\mp\_awards::assignAwards();
  2338.     maps\mp\_scoreboard::processLobbyScoreboards();
  2339.    
  2340.     sendClientMatchData();
  2341. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement