Advertisement
Guest User

gamelogic

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