Advertisement
Guest User

Gamelogic

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