‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_globallogic.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\challenges_shared;
5 #using scripts\shared\demo_shared;
6 #using scripts\shared\gameobjects_shared;
7 #using scripts\shared\hud_shared;
8 #using scripts\shared\hud_message_shared;
9 #using scripts\shared\hud_util_shared;
10 #using scripts\shared\math_shared;
11 #using scripts\shared\medals_shared;
12 #using scripts\shared\music_shared;
13 #using scripts\shared\persistence_shared;
14 #using scripts\shared\popups_shared;
15 #using scripts\shared\rank_shared;
16 #using scripts\shared\tweakables_shared;
17 #using scripts\shared\util_shared;
18 #using scripts\shared\simple_hostmigration;
19 #using scripts\shared\bb_shared;
20 
21 #insert scripts\shared\shared.gsh;
22 
23 #using scripts\zm\gametypes\_dev;
24 #using scripts\zm\gametypes\_globallogic_audio;
25 #using scripts\zm\gametypes\_globallogic_defaults;
26 #using scripts\zm\gametypes\_globallogic_player;
27 #using scripts\zm\gametypes\_globallogic_score;
28 #using scripts\zm\gametypes\_globallogic_spawn;
29 #using scripts\zm\gametypes\_globallogic_ui;
30 #using scripts\zm\gametypes\_globallogic_utils;
31 #using scripts\zm\gametypes\_hostmigration;
32 #using scripts\zm\gametypes\_hud_message;
33 #using scripts\zm\gametypes\_spawnlogic;
34 #using scripts\zm\gametypes\_weaponobjects;
35 #using scripts\zm\gametypes\_weapon_utils;
36 #using scripts\zm\gametypes\_weapons;
37 
38 #using scripts\zm\_rat;
39 #using scripts\zm\_challenges;
40 #using scripts\zm\_util;
41 
42 // must match the stats.ddl quitTypes_e enum
43 #define MATCH_KICKED 2
44 #define MATCH_QUIT 3
45 #define MATCH_FINISHED 4
46 
47 #namespace globallogic;
48 
49 #precache( "model", "tag_origin" );
50 
51 #precache( "statusicon", "hud_status_dead" );
52 #precache( "statusicon", "hud_status_connecting" );
53 
54 #precache( "material", "white" );
55 #precache( "material", "black" );
56 #precache( "string", "PLATFORM_PRESS_TO_SPAWN" );
57 #precache( "string", "MP_WAITING_FOR_TEAMS" );
58 #precache( "string", "MP_OPPONENT_FORFEITING_IN" );
59 #precache( "string", "MP_WAITING_FOR_PLAYERS" );
60 #precache( "string", "MP_OPPONENT_FORFEITING_IN" );
61 #precache( "string", "MP_MATCH_STARTING_IN" );
62 #precache( "string", "MP_SPAWN_NEXT_ROUND" );
63 #precache( "string", "MP_WAITING_TO_SPAWN" );
64 #precache( "string", "MP_WAITING_TO_SPAWN_SS" );
65 #precache( "string", "MP_YOU_WILL_RESPAWN" );
66 #precache( "string", "MP_MATCH_STARTING" );
67 #precache( "string", "MP_CHANGE_CLASS_NEXT_SPAWN" );
68 #precache( "string", "MPUI_LAST_STAND" );
69 #precache( "string", "PLATFORM_COWARDS_WAY_OUT" );
70 #precache( "string", "MP_MATCH_TIE" );
71 #precache( "string", "MP_ROUND_DRAW" );
72 #precache( "string", "MP_ENEMIES_ELIMINATED" );
73 #precache( "string", "MP_SCORE_LIMIT_REACHED" );
74 #precache( "string", "MP_ROUND_LIMIT_REACHED" );
75 #precache( "string", "MP_TIME_LIMIT_REACHED" );
76 #precache( "string", "MP_PLAYERS_FORFEITED" );
77 
78 function ‪init()
79 {
80  level.language = GetDvarString( "language" );
81  level.splitscreen = isSplitScreen();
82  level.xenon = (GetDvarString( "xenonGame") == "true");
83  level.ps3 = (GetDvarString( "ps3Game") == "true");
84  level.wiiu = (GetDvarString( "wiiuGame") == "true");
85  level.orbis = (GetDvarString( "orbisGame") == "true");
86  level.durango = (GetDvarString( "durangoGame") == "true");
87 
88  level.createFX_disable_fx = (GetDvarInt("disable_fx") == 1);
89 
90  level.onlineGame = SessionModeIsOnlineGame(); level.systemLink = SessionModeIsSystemlink();
91  level.console = ( level.xenon || level.ps3 || level.wiiu || level.orbis || level.durango );
92 
93  level.rankedMatch = ( GameModeIsUsingXP() );
94  level.leagueMatch = false;
95  level.arenaMatch = false;
96 
97  level.wagerMatch = false;
98 
99  level.contractsEnabled = !GetGametypeSetting( "disableContracts" );
100 
101  level.contractsEnabled = false;
102 
103  level.script = toLower( GetDvarString( "mapname" ) );
104  level.gametype = toLower( GetDvarString( "g_gametype" ) );
105 
106  level.teamBased = false;
107  level.teamCount = GetGametypeSetting( "teamCount" );
108  level.multiTeam = ( level.teamCount > 2 );
109 
110  if ( SessionModeIsZombiesGame() )
111  {
112  level.zombie_team_index = level.teamCount + 1;
113  if ( 2 == level.zombie_team_index )
114  {
115  level.zombie_team = "axis";
116  }
117  else
118  {
119  level.zombie_team = "team" + level.zombie_team_index;
120  }
121  }
122 
123  // used to loop through all valid playing teams ( not spectator )
124  // can also be used to check if a team is valid ( isdefined( level.teams[team] ) )
125  // NOTE: added in the same order they are defined in code
126  level.teams = [];
127  level.teamIndex = [];
128 
129  teamCount = level.teamCount;
130 
131  level.teams[ "allies" ] = "allies";
132  level.teams[ "axis" ] = "axis";
133 
134  level.teamIndex[ "neutral" ] = 0; // Neutral team set to 0 so that it can be used by objectives
135  level.teamIndex[ "allies" ] = 1;
136  level.teamIndex[ "axis" ] = 2;
137 
138  for( teamIndex = 3; teamIndex <= teamCount; teamIndex++ )
139  {
140  level.teams[ "team" + teamIndex ] = "team" + teamIndex;
141  level.teamIndex[ "team" + teamIndex ] = teamIndex;
142  }
143 
144  level.overrideTeamScore = false;
145  level.overridePlayerScore = false;
146  level.displayHalftimeText = false;
147  level.displayRoundEndText = true;
148 
149  level.endGameOnScoreLimit = true;
150  level.endGameOnTimeLimit = true;
151  level.scoreRoundWinBased = false;
152  level.resetPlayerScoreEveryRound = false;
153 
154  level.gameForfeited= false;
155  level.forceAutoAssign = false;
156 
157  level.halftimeType = "halftime";
158  level.halftimeSubCaption = &"MP_SWITCHING_SIDES_CAPS";
159 
160  level.lastStatusTime = 0;
161  level.wasWinning = [];
162 
163  level.lastSlowProcessFrame = 0;
164 
165  level.placement = [];
166  foreach( team in level.teams )
167  {
168  level.placement[team] = [];
169  }
170  level.placement["all"] = [];
171 
172  level.postRoundTime = 7.0;//Kevin Sherwood changed to 9 to have enough time for music stingers
173 
174  level.inOvertime = false;
175 
176  level.defaultOffenseRadius = 560;
177 
178  level.dropTeam = GetDvarint( "sv_maxclients" );
179 
180  level.inFinalKillcam = false;
181 
183 // _class::initPerkDvars();
184 
185  level.oldschool = ( GetDvarint( "scr_oldschool" ) == 1 );
186  if ( level.oldschool )
187  {
188 
189 
190  SetDvar( "jump_height", 64 );
191  SetDvar( "jump_slowdownEnable", 0 );
192  SetDvar( "bg_fallDamageMinHeight", 256 );
193  SetDvar( "bg_fallDamageMaxHeight", 512 );
194  SetDvar( "player_clipSizeMultiplier", 2.0 );
195  }
196 
198 
199  // sets up the flame fx
200  //_burnplayer::initBurnPlayer();
201 
202  if ( !isdefined( game["tiebreaker"] ) )
203  game["tiebreaker"] = false;
204 
205  ‪globallogic_audio::registerDialogGroup( "item_destroyed", true );
206  ‪globallogic_audio::registerDialogGroup( "introboost", true );
208 
209  //thread _gameadvertisement::init();
210  //thread _gamerep::init();
211 
212  level.playersDrivingVehiclesBecomeInvulnerable = true;
213 
214  // for use in shared scripts that do not know which version of figure_out_attacker to use
215  level.figure_out_attacker = &‪globallogic_player::figureOutAttacker;
216  level.figure_out_friendly_fire = &‪globallogic_player::figureOutFriendlyFire;
217  level.get_base_weapon_param = &‪weapon_utils::getBaseWeaponParam; // used to figure out the weapon to as the parameter to GetBaseWeaponItemIndex()
218 }
219 
221 {
222  if ( GetDvarString( "scr_oldschool" ) == "" )
223  SetDvar( "scr_oldschool", "0" );
224 
225  //makeDvarServerInfo( "scr_oldschool" );
226 
227  if ( GetDvarString( "ui_guncycle" ) == "" )
228  SetDvar( "ui_guncycle", 0 );
229 
230  //makeDvarServerInfo( "ui_guncycle" );
231 
232  if ( GetDvarString( "ui_weapon_tiers" ) == "" )
233  SetDvar( "ui_weapon_tiers", 0 );
234  //makeDvarServerInfo( "ui_weapon_tiers" );
235 
236  SetDvar( "ui_text_endreason", "");
237  //makeDvarServerInfo( "ui_text_endreason", "" );
238 
239  setMatchFlag( "bomb_timer", 0 );
240 
241  //setMatchFlag( "enable_popups", 1 );
242 
243  if ( GetDvarString( "scr_vehicle_damage_scalar" ) == "" )
244  SetDvar( "scr_vehicle_damage_scalar", "1" );
245 
246  level.vehicleDamageScalar = GetDvarfloat( "scr_vehicle_damage_scalar");
247 
248  level.fire_audio_repeat_duration = GetDvarint( "fire_audio_repeat_duration" );
249  level.fire_audio_random_max_duration = GetDvarint( "fire_audio_random_max_duration" );
250 }
251 
252 function ‪blank( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 )
253 {
254 }
255 
257 {
258  level.spawnPlayer = &‪globallogic_spawn::spawnPlayer;
259  level.spawnPlayerPrediction = &‪globallogic_spawn::spawnPlayerPrediction;
260  level.spawnClient = &‪globallogic_spawn::spawnClient;
261  level.spawnSpectator = &‪globallogic_spawn::spawnSpectator;
262  level.spawnIntermission = &‪globallogic_spawn::spawnIntermission;
263  level.scoreOnGivePlayerScore = &‪globallogic_score::givePlayerScore;
264  level.onPlayerScore = &‪globallogic_score::default_onPlayerScore;
265  level.onTeamScore = &‪globallogic_score::default_onTeamScore;
266 
267  level.waveSpawnTimer =&‪waveSpawnTimer;
268  level.spawnMessage = &‪globallogic_spawn::default_spawnMessage;
269 
270  level.onSpawnPlayer =&‪blank;
271  level.onSpawnPlayerUnified =&‪blank;
272  level.onSpawnSpectator = &‪globallogic_defaults::default_onSpawnSpectator;
273  level.onSpawnIntermission = &‪globallogic_defaults::default_onSpawnIntermission;
274  level.onRespawnDelay =&‪blank;
275 
278  level.onScoreLimit = &‪globallogic_defaults::default_onScoreLimit;
279  level.onAliveCountChange = &‪globallogic_defaults::default_onAliveCountChange;
281  level.onOneLeftEvent = &‪globallogic_defaults::default_onOneLeftEvent;
282  level.giveTeamScore = &‪globallogic_score::giveTeamScore;
283  level.onLastTeamAliveEvent = undefined;
284 
285  level.getTimePassed = &‪globallogic_utils::getTimePassed;
286  level.getTimeLimit = &‪globallogic_defaults::default_getTimeLimit;
287  level.getTeamKillPenalty =&‪blank; // globallogic_defaults::default_getTeamKillPenalty;
288  level.getTeamKillScore =&‪blank; // globallogic_defaults::default_getTeamKillScore;
289 
290  level.isKillBoosting = &‪globallogic_score::default_isKillBoosting;
291 
292  level._setTeamScore = &‪globallogic_score::_setTeamScore;
293  level._setPlayerScore = &‪globallogic_score::_setPlayerScore;
294 
295  level._getTeamScore = &‪globallogic_score::_getTeamScore;
296  level._getPlayerScore = &‪globallogic_score::_getPlayerScore;
297 
298  level.onPrecacheGametype =&‪blank;
299  level.onStartGameType =&‪blank;
300  level.onPlayerConnect =&‪blank;
301  level.onPlayerDisconnect =&‪blank;
302  level.onPlayerDamage =&‪blank;
303  level.onPlayerKilled =&‪blank;
304  level.onPlayerKilledExtraUnthreadedCBs = [];
305 
306  level.onTeamOutcomeNotify = &‪hud_message::teamOutcomeNotify;
307  level.onOutcomeNotify = &‪hud_message::outcomeNotify;
308  level.onTeamWagerOutcomeNotify = &‪hud_message::teamWagerOutcomeNotify;
309  level.onWagerOutcomeNotify = &‪hud_message::wagerOutcomeNotify;
310  level.setMatchScoreHUDElemForTeam = &‪hud_message::setMatchScoreHUDElemForTeam;
311  level.onEndGame =&‪blank;
312  level.onRoundEndGame = &‪globallogic_defaults::default_onRoundEndGame;
313  level.onMedalAwarded = &‪blank;
314  level.dogManagerOnGetDogs = &‪blank;
315 
317 }
318 
320 {
321  if( SessionModeIsZombiesGame() )
322  return;
323 
324  if( !level.rankedMatch )
325  return;
326 
327  mapname = GetDvarString( "mapname" );
328 
329  globalLeaderboards = "LB_MP_GB_XPPRESTIGE LB_MP_GB_TOTALXP_AT LB_MP_GB_TOTALXP_LT LB_MP_GB_WINS_AT LB_MP_GB_WINS_LT LB_MP_GB_KILLS_AT LB_MP_GB_KILLS_LT LB_MP_GB_ACCURACY_AT LB_MP_GB_ACCURACY_LT";
330 
331  gamemodeLeaderboard = " LB_MP_GM_" + level.gametype;
332 
333  if( getDvarInt( "g_hardcore" ) )
334  gamemodeLeaderboard += "_HC";
335 
336  mapLeaderboard = " LB_MP_MAP_" + getsubstr( mapname, 3, mapname.size ); // strip the MP_ from the map name
337 
338  precacheLeaderboards( globalLeaderboards + gamemodeLeaderboard + mapLeaderboard );
339 }
340 
341 function ‪compareTeamByGameStat( gameStat, teamA, teamB, previous_winner_score )
342 {
343  winner = undefined;
344 
345  if ( teamA == "tie" )
346  {
347  winner = "tie";
348 
349  if ( previous_winner_score < game[gameStat][teamB] )
350  winner = teamB;
351  }
352  else if ( game[gameStat][teamA] == game[gameStat][teamB] )
353  winner = "tie";
354  else if ( game[gameStat][teamB] > game[gameStat][teamA] )
355  winner = teamB;
356  else
357  winner = teamA;
358 
359  return winner;
360 }
361 
363 {
364  teamKeys = GetArrayKeys(level.teams);
365  winner = teamKeys[0];
366  previous_winner_score = game[gameStat][winner];
367 
368  for ( teamIndex = 1; teamIndex < teamKeys.size; teamIndex++ )
369  {
370  winner = ‪compareTeamByGameStat( gameStat, winner, teamKeys[teamIndex], previous_winner_score);
371 
372  if ( winner != "tie" )
373  {
374  previous_winner_score = game[gameStat][winner];
375  }
376  }
377 
378  return winner;
379 }
380 
381 function ‪compareTeamByTeamScore( teamA, teamB, previous_winner_score )
382 {
383  winner = undefined;
384  teamBScore = [[level._getTeamScore]]( teamB );
385 
386  if ( teamA == "tie" )
387  {
388  winner = "tie";
389 
390  if ( previous_winner_score < teamBScore )
391  winner = teamB;
392 
393  return winner;
394  }
395 
396  teamAScore = [[level._getTeamScore]]( teamA );
397 
398  if ( teamBScore == teamAScore )
399  winner = "tie";
400  else if ( teamBScore > teamAScore )
401  winner = teamB;
402  else
403  winner = teamA;
404 
405  return winner;
406 }
407 
409 {
410  teamKeys = GetArrayKeys(level.teams);
411  winner = teamKeys[0];
412  previous_winner_score = [[level._getTeamScore]]( winner );
413 
414  for ( teamIndex = 1; teamIndex < teamKeys.size; teamIndex++ )
415  {
416  winner = ‪compareTeamByTeamScore( winner, teamKeys[teamIndex], previous_winner_score);
417 
418  if ( winner != "tie" )
419  {
420  previous_winner_score = [[level._getTeamScore]]( winner );
421  }
422  }
423 
424  return winner;
425 }
426 
427 function ‪forceEnd(hostsucks)
428 {
429  if (!isdefined(hostsucks))
430  hostsucks = false;
431 
432  if ( level.hostForcedEnd || level.forcedEnd )
433  return;
434 
435  winner = undefined;
436 
437  if ( level.teamBased )
438  {
439  winner = ‪determineTeamWinnerByGameStat("teamScores");
440  ‪globallogic_utils::logTeamWinString( "host ended game", winner );
441  }
442  else
443  {
445  }
446 
447  level.forcedEnd = true;
448  level.hostForcedEnd = true;
449 
450  if (hostsucks)
451  {
452  endString = &"MP_HOST_SUCKS";
453  }
454  else
455  {
456  if ( level.splitscreen )
457  endString = &"MP_ENDED_GAME";
458  else
459  endString = &"MP_HOST_ENDED_GAME";
460  }
461 
462  setMatchFlag( "disableIngameMenu", 1 );
463  //makeDvarServerInfo( "ui_text_endreason", endString );
464  SetDvar( "ui_text_endreason", endString );
465  thread ‪endGame( winner, endString );
466 }
467 
468 function ‪killserverPc()
469 {
470  if ( level.hostForcedEnd || level.forcedEnd )
471  return;
472 
473  winner = undefined;
474 
475  if ( level.teamBased )
476  {
477  winner = ‪determineTeamWinnerByGameStat("teamScores");
478  ‪globallogic_utils::logTeamWinString( "host ended game", winner );
479  }
480  else
481  {
483  }
484 
485  level.forcedEnd = true;
486  level.hostForcedEnd = true;
487 
488  level.killserver = true;
489 
490  endString = &"MP_HOST_ENDED_GAME";
491 
492  thread ‪endGame( winner, endString );
493 }
494 
496 {
497  foreach ( team in level.teams )
498  {
499  if ( level.playerCount[team] == 0 )
500  return false;
501  }
502 
503  return true;
504 }
505 
506 function ‪checkIfTeamForfeits( team )
507 {
508  if ( !level.everExisted[team] )
509  return false;
510 
511  if ( level.playerCount[team] < 1 && ‪util::totalPlayerCount() > 0 )
512  {
513  return true;
514  }
515 
516  return false;
517 }
518 
520 {
521  foreach( team in level.teams )
522  {
523  if ( ‪checkIfTeamForfeits( team ) )
524  {
525  //allies forfeited
526  thread [[level.onForfeit]]( team );
527  return true;
528  }
529  }
530 
531  return false;
532 }
533 
535 {
536  foreach( team in level.teams )
537  {
538  if ( level.spawnQueueModified[team] )
539  {
540  [[level.onAliveCountChange]]( team );
541  }
542  }
543 }
544 
545 function ‪isTeamAllDead( team )
546 {
547  return (level.everExisted[team] && !level.aliveCount[team] && !level.playerLives[team] );
548 }
549 
551 {
552  foreach( team in level.teams )
553  {
554  // if team was alive and now they are not
555  if ( !‪isTeamAllDead( team ) )
556  {
557  return false;
558  }
559  }
560 
561  return true;
562 }
563 
565 {
566  count = 0;
567  foreach( team in level.teams )
568  {
569  // if team was alive and now they are not
570  if ( ‪isTeamAllDead( team ) )
571  {
572  count++;
573  }
574  }
575 
576  return count;
577 }
578 
580 {
581  if ( level.teamBased )
582  {
583  // if all teams were alive and now they are all dead in the same instance
584  if ( ‪areAllTeamsDead( ) )
585  {
586  [[level.onDeadEvent]]( "all" );
587  return true;
588  }
589 
590  // TODO MTEAM - invert all onDeadEvent functions to be onLastTeamAliveEvent instead
591  if ( isdefined( level.onLastTeamAliveEvent ) )
592  {
593  if ( ‪allDeadTeamCount( ) == level.teams.size - 1 )
594  {
595  foreach( team in level.teams )
596  {
597  // if team is alive
598  if ( !‪isTeamAllDead( team ) )
599  {
600  [[level.onLastTeamAliveEvent]]( team );
601  return true;
602  }
603  }
604  }
605  }
606  else
607  {
608  foreach( team in level.teams )
609  {
610  // if team was alive and now they are not
611  if ( ‪isTeamAllDead( team ) )
612  {
613  [[level.onDeadEvent]]( team );
614  return true;
615  }
616  }
617  }
618  }
619  else
620  {
621  // everyone is dead
622  if ( (‪totalAliveCount() == 0) && (‪totalPlayerLives() == 0) && level.maxPlayerCount > 1 )
623  {
624  [[level.onDeadEvent]]( "all" );
625  return true;;
626  }
627  }
628 
629  return false;
630 }
631 
633 {
634  return (level.lastAliveCount[team] > 1 && level.aliveCount[team] == 1 && level.playerLives[team] == 1 );
635 }
636 
637 
639 {
640  if ( level.teamBased )
641  {
642  foreach( team in level.teams )
643  {
644  // one "team" left
645  if ( ‪isOnlyOneLeftAliveOnTeam( team ) )
646  {
647  [[level.onOneLeftEvent]]( team );
648  return true;;
649  }
650  }
651  }
652  else
653  {
654  // last man standing
655  if ( (‪totalAliveCount() == 1) && (‪totalPlayerLives() == 1) && level.maxPlayerCount > 1 )
656  {
657  [[level.onOneLeftEvent]]( "all" );
658  return true;;
659  }
660  }
661 
662  return false;
663 }
664 
666 {
667  if ( ( level.rankedMatch || level.wagerMatch || level.leagueMatch ) && !level.inGracePeriod )
668  {
669  if ( level.teamBased )
670  {
671  if (!level.gameForfeited )
672  {
673  if( game["state"] == "playing" && ‪checkForAnyTeamForfeit() )
674  {
675  return;
676  }
677  }
678  else // level.gameForfeited==true
679  {
680  if ( ‪someoneOnEachTeam() )
681  {
682  level.gameForfeited = false;
683  level notify( "abort forfeit" );
684  }
685  }
686  }
687  else
688  {
689  if (!level.gameForfeited)
690  {
691  if ( ‪util::totalPlayerCount() == 1 && level.maxPlayerCount > 1 )
692  {
693  thread [[level.onForfeit]]();
694  return;
695  }
696  }
697  else // level.gameForfeited==true
698  {
699  if ( ‪util::totalPlayerCount() > 1 )
700  {
701  level.gameForfeited = false;
702  level notify( "abort forfeit" );
703  }
704  }
705  }
706  }
707 
708  if ( !level.playerQueuedRespawn && !level.numLives && !level.inOverTime )
709  return;
710 
711  if ( level.inGracePeriod )
712  return;
713 
714  if ( level.playerQueuedRespawn )
715  {
717  }
718 
719  if ( ‪doDeadEventUpdates() )
720  return;
721 
722  if ( ‪doOneLeftEventUpdates() )
723  return;
724 }
725 
726 
728 {
729  matchStartText = ‪hud::createServerFontString( "objective", 1.5 );
730  matchStartText ‪hud::setPoint( "CENTER", "CENTER", 0, -40 );
731  matchStartText.sort = 1001;
732  matchStartText setText( game["strings"]["waiting_for_teams"] );
733  matchStartText.foreground = false;
734  matchStartText.hidewheninmenu = true;
735 
737  matchStartText setText( game["strings"]["match_starting_in"] );
738 
740  ‪matchStartTimer ‪hud::setPoint( "CENTER", "CENTER", 0, 0 );
741  ‪matchStartTimer.sort = 1001;
742  ‪matchStartTimer.color = (1,1,0);
743  ‪matchStartTimer.foreground = false;
744  ‪matchStartTimer.hidewheninmenu = true;
745 
746 
747  //Since the scaling is disabled, we cant see the pulse effect by scaling. We need to change keep switching between
748  //some small and big font to get the pulse effect. This will be fixed when we have fixed set of different sizes fonts.
749 
750  //matchStartTimer _hud::fontPulseInit();
751 
752  countTime = int( level.prematchPeriod );
753 
754  if ( countTime >= 2 )
755  {
756  while ( countTime > 0 && !level.gameEnded )
757  {
758  ‪matchStartTimer setValue( countTime );
759  //matchStartTimer thread _hud::fontPulse( level );
760  if ( countTime == 2 )
761  visionSetNaked( GetDvarString( "mapname" ), 3.0 );
762  countTime--;
763  wait ( 1.0 );
764  }
765  }
766  else
767  {
768  visionSetNaked( GetDvarString( "mapname" ), 1.0 );
769  }
770 
772  matchStartText ‪hud::destroyElem();
773 }
774 
776 {
777  visionSetNaked( GetDvarString( "mapname" ), 0 );
778 }
779 
780 function ‪notifyTeamWaveSpawn( team, time )
781 {
782  if ( time - level.lastWave[team] > (level.waveDelay[team] * 1000) )
783  {
784  level notify ( "wave_respawn_" + team );
785  level.lastWave[team] = time;
786  level.wavePlayerSpawnIndex[team] = 0;
787  }
788 }
789 
791 {
792  level endon( "game_ended" );
793 
794  while ( game["state"] == "playing" )
795  {
796  time = getTime();
797 
798  foreach( team in level.teams )
799  {
800  ‪notifyTeamWaveSpawn( team, time );
801  }
803  }
804 }
805 
806 
807 function ‪hostIdledOut()
808 {
809  hostPlayer = ‪util::getHostPlayer();
810 
811  // host never spawned
812  if ( isdefined( hostPlayer ) && !hostPlayer.hasSpawned && !isdefined( hostPlayer.selectedClass ) )
813  return true;
814 
815  return false;
816 }
817 
818 function ‪IncrementMatchCompletionStat( gameMode, playedOrHosted, stat )
819 {
820  self AddDStat( "gameHistory", gameMode, "modeHistory", playedOrHosted, stat, 1 );
821 }
822 
823 function ‪SetMatchCompletionStat( gameMode, playedOrHosted, stat )
824 {
825  self SetDStat( "gameHistory", gameMode, "modeHistory", playedOrHosted, stat, 1 );
826 }
827 
828 function ‪displayRoundEnd( winner, endReasonText )
829 {
830  if ( level.displayRoundEndText )
831  {
832  if ( winner == "tie" )
833  {
834  ‪demo::gameResultBookmark( "round_result", level.teamIndex[ "neutral" ], level.teamIndex[ "neutral" ] );
835  }
836  else
837  {
838  ‪demo::gameResultBookmark( "round_result", level.teamIndex[ winner ], level.teamIndex[ "neutral" ] );
839  }
840 
841  setmatchflag( "cg_drawSpectatorMessages", 0 );
842  players = level.players;
843  for ( index = 0; index < players.size; index++ )
844  {
845  player = players[index];
846 
847  if ( !isdefined( player.pers["team"] ) )
848  {
849  player [[level.spawnIntermission]]( true );
850  player closeInGameMenu();
851  continue;
852  }
853 
854  if ( level.wagerMatch )
855  {
856  if ( level.teamBased )
857  player thread [[level.onTeamWagerOutcomeNotify]]( winner, true, endReasonText );
858  else
859  player thread [[level.onWagerOutcomeNotify]]( winner, endReasonText );
860  }
861  else
862  {
863  if ( level.teamBased )
864  {
865  player thread [[level.onTeamOutcomeNotify]]( winner, true, endReasonText );
866  player ‪globallogic_audio::set_music_on_player( "ROUND_END" );
867  }
868  else
869  {
870  player thread [[level.onOutcomeNotify]]( winner, true, endReasonText );
871  player ‪globallogic_audio::set_music_on_player( "ROUND_END" );
872  }
873  }
874 
875  player setClientUIVisibilityFlag( "hud_visible", 0 );
876  player setClientUIVisibilityFlag( "g_compassShowEnemies", 0 );
877  }
878  }
879 
880  if ( ‪util::wasLastRound() )
881  {
882  ‪roundEndWait( level.roundEndDelay, false );
883  }
884  else
885  {
886  thread ‪globallogic_audio::announceRoundWinner( winner, level.roundEndDelay / 4 );
887  ‪roundEndWait( level.roundEndDelay, true );
888  }
889 }
890 
891 function ‪displayRoundSwitch( winner, endReasonText )
892 {
893  switchType = level.halftimeType;
894  if ( switchType == "halftime" )
895  {
896  if ( isdefined( level.nextRoundIsOvertime ) && level.nextRoundIsOvertime )
897  {
898  switchType = "overtime";
899  }
900  else
901  {
902  if ( level.roundLimit )
903  {
904  if ( (game["roundsplayed"] * 2) == level.roundLimit )
905  switchType = "halftime";
906  else
907  switchType = "intermission";
908  }
909  else if ( level.scoreLimit )
910  {
911  if ( game["roundsplayed"] == (level.scoreLimit - 1) )
912  switchType = "halftime";
913  else
914  switchType = "intermission";
915  }
916  else
917  {
918  switchType = "intermission";
919  }
920  }
921  }
922 
923  leaderdialog = ‪globallogic_audio::getRoundSwitchDialog( switchType );
924 
925  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
926 
927  players = level.players;
928  for ( index = 0; index < players.size; index++ )
929  {
930  player = players[index];
931 
932  if ( !isdefined( player.pers["team"] ) )
933  {
934  player [[level.spawnIntermission]]( true );
935  player closeInGameMenu();
936  continue;
937  }
938 
939  player ‪globallogic_audio::leaderDialogOnPlayer( leaderdialog );
940  player ‪globallogic_audio::set_music_on_player( "ROUND_SWITCH" );
941 
942  if ( level.wagerMatch )
943  player thread [[level.onTeamWagerOutcomeNotify]]( switchType, true, level.halftimeSubCaption );
944  else
945  player thread [[level.onTeamOutcomeNotify]]( switchType, false, level.halftimeSubCaption );
946  player setClientUIVisibilityFlag( "hud_visible", 0 );
947  }
948 
949  ‪roundEndWait( level.halftimeRoundEndDelay, false );
950 }
951 
952 function ‪displayGameEnd( winner, endReasonText )
953 {
954  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
955  setmatchflag( "cg_drawSpectatorMessages", 0 );
956 
957  if ( winner == "tie" )
958  {
959  ‪demo::gameResultBookmark( "game_result", level.teamIndex[ "neutral" ], level.teamIndex[ "neutral" ] );
960  }
961  else
962  {
963  ‪demo::gameResultBookmark( "game_result", level.teamIndex[ winner ], level.teamIndex[ "neutral" ] );
964  }
965 
966  // catching gametype, since DM forceEnd sends winner as player entity, instead of string
967  players = level.players;
968  for ( index = 0; index < players.size; index++ )
969  {
970  player = players[index];
971 
972  if ( !isdefined( player.pers["team"] ) )
973  {
974  player [[level.spawnIntermission]]( true );
975  player closeInGameMenu();
976  continue;
977  }
978 
979  if ( level.wagerMatch )
980  {
981  if ( level.teamBased )
982  player thread [[level.onTeamWagerOutcomeNotify]]( winner, false, endReasonText );
983  else
984  player thread [[level.onWagerOutcomeNotify]]( winner, endReasonText );
985  }
986  else
987  {
988  if ( level.teamBased )
989  {
990  player thread [[level.onTeamOutcomeNotify]]( winner, false, endReasonText );
991  }
992  else
993  {
994  player thread [[level.onOutcomeNotify]]( winner, false, endReasonText );
995 
996  if ( isdefined( winner ) && player == winner )
997  player ‪globallogic_audio::set_music_on_player( "VICTORY" );
998  else if ( !level.splitScreen )
1000  }
1001  }
1002 
1003  player setClientUIVisibilityFlag( "hud_visible", 0 );
1004  player setClientUIVisibilityFlag( "g_compassShowEnemies", 0 );
1005  }
1006 
1007  if ( level.teamBased )
1008  {
1009  thread ‪globallogic_audio::announceGameWinner( winner, level.postRoundTime / 2 );
1010 
1011  players = level.players;
1012  for ( index = 0; index < players.size; index++ )
1013  {
1014  player = players[index];
1015  team = player.pers["team"];
1016 
1017  if ( level.splitscreen )
1018  {
1019  if ( winner == "tie" )
1020  {
1022  }
1023  else if ( winner == team )
1024  {
1025  player ‪globallogic_audio::set_music_on_player( "VICTORY" );
1026  }
1027  else
1028  {
1030  }
1031  }
1032  else
1033  {
1034  if ( winner == "tie" )
1035  {
1037  }
1038  else if ( winner == team )
1039  {
1040  player ‪globallogic_audio::set_music_on_player( "VICTORY" );
1041  }
1042  else
1043  {
1045  }
1046  }
1047  }
1048  }
1049 
1050  bbPrint( "global_session_epilogs", "reason %s", endReasonText );
1051 
1052  // tagTMR<NOTE>: all round data aggregates that cannot be summed from other tables post-runtime
1053  // Removed a blackbox print for "mpmatchfacts" from here
1054 
1055  ‪roundEndWait( level.postRoundTime, true );
1056 }
1057 
1059 {
1061  return game["strings"]["round_limit_reached"];
1062  else if ( ‪util::hitScoreLimit() )
1063  return game["strings"]["score_limit_reached"];
1064 
1065  if ( level.forcedEnd )
1066  {
1067  if ( level.hostForcedEnd )
1068  return &"MP_HOST_ENDED_GAME";
1069  else
1070  return &"MP_ENDED_GAME";
1071  }
1072  return game["strings"]["time_limit_reached"];
1073 }
1074 
1076 {
1077  players = level.players;
1078  for ( index = 0; index < players.size; index++ )
1079  {
1080  player = players[index];
1081  player notify ( "reset_outcome" );
1082  }
1083 }
1084 
1085 function ‪startNextRound( winner, endReasonText )
1086 {
1087  if ( !‪util::isOneRound() )
1088  {
1089  ‪displayRoundEnd( winner, endReasonText );
1090 
1092 
1093  if ( !‪util::wasLastRound() )
1094  {
1095  if ( ‪checkRoundSwitch() )
1096  {
1097  ‪displayRoundSwitch( winner, endReasonText );
1098  }
1099 
1100  if ( isdefined( level.nextRoundIsOvertime ) && level.nextRoundIsOvertime )
1101  {
1102  if ( !isdefined( game["overtime_round"] ) )
1103  {
1104  game["overtime_round"] = 1;
1105  }
1106  else
1107  {
1108  game["overtime_round"]++;
1109  }
1110  }
1111 
1112  SetMatchTalkFlag( "DeadChatWithDead", level.voip.deadChatWithDead );
1113  SetMatchTalkFlag( "DeadChatWithTeam", level.voip.deadChatWithTeam );
1114  SetMatchTalkFlag( "DeadHearTeamLiving", level.voip.deadHearTeamLiving );
1115  SetMatchTalkFlag( "DeadHearAllLiving", level.voip.deadHearAllLiving );
1116  SetMatchTalkFlag( "EveryoneHearsEveryone", level.voip.everyoneHearsEveryone );
1117  SetMatchTalkFlag( "DeadHearKiller", level.voip.deadHearKiller );
1118  SetMatchTalkFlag( "KillersHearVictim", level.voip.killersHearVictim );
1119 
1120  game["state"] = "playing";
1121  level.allowbattlechatter["bc"] = GetGametypeSetting( "allowBattleChatter" );
1122  map_restart( true );
1123  return true;
1124  }
1125  }
1126  return false;
1127 }
1128 
1130 {
1131  if ( !level.timeLimit || level.forcedEnd )
1132  {
1133  gameLength = ‪globallogic_utils::getTimePassed() / 1000;
1134  // cap it at 20 minutes to avoid exploiting
1135  gameLength = min( gameLength, 1200 );
1136  }
1137  else
1138  {
1139  gameLength = level.timeLimit * 60;
1140  }
1141 
1142  return gameLength;
1143 }
1144 
1146 {
1147  if ( !GameModeIsMode( ‪GAMEMODE_PUBLIC_MATCH ) )
1148  return;
1149 
1150  teamScoreRatio = 0;
1151  self GameHistoryFinishMatch( ‪MATCH_QUIT, 0, 0, 0, 0, teamScoreRatio );
1152 
1153  if ( isdefined( self.pers["matchesPlayedStatsTracked"] ) )
1154  {
1155  gameMode = ‪util::GetCurrentGameMode();
1156  self ‪IncrementMatchCompletionStat( gameMode, "played", "quit" );
1157 
1158  if ( isdefined( self.pers["matchesHostedStatsTracked"] ) )
1159  {
1160  self ‪IncrementMatchCompletionStat( gameMode, "hosted", "quit" );
1161  self.pers["matchesHostedStatsTracked"] = undefined;
1162  }
1163 
1164  self.pers["matchesPlayedStatsTracked"] = undefined;
1165  }
1166 
1167  UploadStats( self );
1168 
1169  // wait until the player recieves the new stats
1170  wait(1);
1171 }
1172 
1174 {
1175  players = level.players;
1176  for ( index = 0; index < players.size; index++ )
1177  {
1179  }
1180 }
1181 
1182 function ‪endGame( winner, endReasonText )
1183 {
1184  // return if already ending via host quit or victory
1185  if ( game["state"] == "postgame" || level.gameEnded )
1186  return;
1187 
1188  if ( isdefined( level.onEndGame ) )
1189  [[level.onEndGame]]( winner );
1190 
1191  //This wait was added possibly for wager match issues, but we think is no longer necessary.
1192  //It was creating issues with multiple players calling this fuction when checking game score. In modes like HQ,
1193  //The game score is given to every player on the team that captured the HQ, so when the points are dished out it loops through
1194  //all players on that team and checks if the score limit has been reached. But since this wait occured before the game["state"]
1195  //could be set to "postgame" the check score thread would send the next player that reached the score limit into this function,
1196  //when the following code should only be hit once. If this wait turns out to be needed, we need to try pulling the game["state"] = "postgame";
1197  //up above the wait.
1198  //WAIT_SERVER_FRAME;
1199 
1200  //if ( !level.wagerMatch )
1201  // setMatchFlag( "enable_popups", 0 );
1202  if ( !isdefined( level.disableOutroVisionSet ) || level.disableOutroVisionSet == false )
1203  {
1204  if ( SessionModeIsZombiesGame() && level.forcedEnd )
1205  {
1206  visionSetNaked( "zombie_last_stand", 2.0 );
1207  }
1208  else
1209  {
1210  visionSetNaked( "mpOutro", 2.0 );
1211  }
1212  }
1213 
1214  setmatchflag( "cg_drawSpectatorMessages", 0 );
1215  setmatchflag( "game_ended", 1 );
1216 
1217  game["state"] = "postgame";
1218  level.gameEndTime = getTime();
1219  level.gameEnded = true;
1220  SetDvar( "g_gameEnded", 1 );
1221  level.inGracePeriod = false;
1222  level notify ( "game_ended" );
1223  level.allowbattlechatter["bc"] = false;
1225 
1226  if ( !isdefined( game["overtime_round"] ) || ‪util::wasLastRound() ) // Want to treat all overtime rounds as a single round
1227  {
1228  game["roundsplayed"]++;
1229  game["roundwinner"][game["roundsplayed"]] = winner;
1230 
1231  //Added "if" check for FFA - Leif
1232  if( level.teambased )
1233  {
1234  game["roundswon"][winner]++;
1235  }
1236  }
1237 
1238  if ( isdefined( winner ) && isdefined( level.teams[winner] ) )
1239  {
1240  level.finalKillCam_winner = winner;
1241  }
1242  else
1243  {
1244  level.finalKillCam_winner = "none";
1245  }
1246 
1247  setGameEndTime( 0 ); // stop/hide the timers
1248 
1250 
1251  ‪updateRankedMatch( winner );
1252 
1253  // freeze players
1254  players = level.players;
1255 
1256  newTime = getTime();
1257  gameLength = ‪getGameLength();
1258 
1259  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
1260 
1261  bbGameOver = 0;
1263  {
1264  bbGameOver = 1;
1265 
1266  if ( level.teambased )
1267  {
1268  if ( winner == "tie" )
1269  {
1270  recordGameResult( "draw" );
1271  }
1272  else
1273  {
1274  recordGameResult( winner );
1275  }
1276  }
1277  else
1278  {
1279  if ( !isdefined( winner ) )
1280  {
1281  recordGameResult( "draw" );
1282  }
1283  else
1284  {
1285  recordGameResult( winner.team );
1286  }
1287  }
1288  }
1289 
1290  for ( index = 0; index < players.size; index++ )
1291  {
1292  player = players[index];
1294  player thread roundEndDoF( 4.0 );
1295 
1297 
1298  // Update weapon usage stats
1299  player ‪weapons::updateWeaponTimings( newTime );
1300 
1301  player ‪bbPlayerMatchEnd( gameLength, endReasonText, bbGameOver );
1302 
1303  if( ( level.rankedMatch || level.wagerMatch || level.leagueMatch ) && !player IsSplitscreen() )
1304  {
1305  if ( isdefined( player.setPromotion ) )
1306  player setDStat( "AfterActionReportStats", "lobbyPopup", "promotion" );
1307  else
1308  player setDStat( "AfterActionReportStats", "lobbyPopup", "summary" );
1309  }
1310  }
1311 
1312  music::setmusicstate( "SILENT" );
1313 
1316  if ( ‪startNextRound( winner, endReasonText ) )
1317  {
1318  return;
1319  }
1320 
1322  // After this the match is really ending //
1324 
1325  if ( !‪util::isOneRound() )
1326  {
1327  if ( isdefined( level.onRoundEndGame ) )
1328  winner = [[level.onRoundEndGame]]( winner );
1329 
1330  endReasonText = ‪getEndReasonText();
1331  }
1332 
1333  skillUpdate( winner, level.teamBased );
1334  recordLeagueWinner( winner );
1335 
1336  if ( isdefined( winner ) && ( !isdefined( level.skipGameEnd ) || !level.skipGameEnd ) )
1337  ‪displayGameEnd( winner, endReasonText );
1338 
1339  if ( ‪util::isOneRound() )
1340  {
1342  }
1343 
1344  level.intermission = true;
1345 
1346  //_gamerep::gameRepAnalyzeAndReport();
1347 
1348 // _wager::finalizeWagerGame();
1349 
1350  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
1351 
1352  stopdemorecording();
1353 
1354  //regain players array since some might've disconnected during the wait above
1355  players = level.players;
1356  for ( index = 0; index < players.size; index++ )
1357  {
1358  player = players[index];
1359 
1360  recordPlayerStats( player, "presentAtEnd", 1 );
1361 
1362  player closeInGameMenu();
1363  player notify ( "reset_outcome" );
1364  player thread [[level.spawnIntermission]]();
1365  player setClientUIVisibilityFlag( "hud_visible", 1 );
1366  player setClientUIVisibilityFlag( "weapon_hud_visible", 1 );
1367  }
1368  //Eckert - Fading out sound
1369  level notify ( "sfade");
1370 
1371 
1372  if ( !isdefined( level.skipGameEnd ) || !level.skipGameEnd )
1373  wait 5.0;
1374 
1375  exitLevel( false );
1376 
1377 }
1378 
1379 function ‪bbPlayerMatchEnd( gameLength, endReasonString, gameOver ) // self == player
1380 {
1381  playerRank = ‪getPlacementForPlayer( self );
1382 
1383  totalTimePlayed = 0;
1384  if ( isdefined( self.timePlayed ) && isdefined( self.timePlayed["total"] ) )
1385  {
1386  totalTimePlayed = self.timePlayed["total"];
1387  if ( totalTimePlayed > gameLength )
1388  {
1389  totalTimePlayed = gameLength;
1390  }
1391  }
1392 
1393  xuid = self GetXUID();
1394 
1395  // Removed a blackbox print for "mpplayermatchfacts" from here
1396 }
1397 
1398 function ‪roundEndWait( defaultDelay, matchBonus )
1399 {
1400  notifiesDone = false;
1401  while ( !notifiesDone )
1402  {
1403  players = level.players;
1404  notifiesDone = true;
1405  for ( index = 0; index < players.size; index++ )
1406  {
1407  if ( !isdefined( players[index].doingNotify ) || !players[index].doingNotify )
1408  continue;
1409 
1410  notifiesDone = false;
1411  }
1412  wait ( 0.5 );
1413  }
1414 
1415  if ( !matchBonus )
1416  {
1417  wait ( defaultDelay );
1418  level notify ( "round_end_done" );
1419  return;
1420  }
1421 
1422  wait ( defaultDelay / 2 );
1423  level notify ( "give_match_bonus" );
1424  wait ( defaultDelay / 2 );
1425 
1426  notifiesDone = false;
1427  while ( !notifiesDone )
1428  {
1429  players = level.players;
1430  notifiesDone = true;
1431  for ( index = 0; index < players.size; index++ )
1432  {
1433  if ( !isdefined( players[index].doingNotify ) || !players[index].doingNotify )
1434  continue;
1435 
1436  notifiesDone = false;
1437  }
1438  wait ( 0.5 );
1439  }
1440 
1441  level notify ( "round_end_done" );
1442 }
1443 
1444 
1445 function ‪roundEndDOF( time )
1446 {
1447  self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
1448 }
1449 
1450 
1452 {
1453  if ( isdefined( level.timeLimitOverride ) && level.timeLimitOverride )
1454  return;
1455 
1456  if ( game["state"] != "playing" )
1457  {
1458  setGameEndTime( 0 );
1459  return;
1460  }
1461 
1462  if ( level.timeLimit <= 0 )
1463  {
1464  setGameEndTime( 0 );
1465  return;
1466  }
1467 
1468  if ( level.inPrematchPeriod )
1469  {
1470  setGameEndTime( 0 );
1471  return;
1472  }
1473 
1474  if ( level.timerStopped )
1475  {
1476  setGameEndTime( 0 );
1477  return;
1478  }
1479 
1480  if ( !isdefined( level.startTime ) )
1481  return;
1482 
1484 
1485  // want this accurate to the millisecond
1486  setGameEndTime( getTime() + int(timeLeft) );
1487 
1488  if ( timeLeft > 0 )
1489  return;
1490 
1491  [[level.onTimeLimit]]();
1492 }
1493 
1495 {
1496  foreach ( team in level.teams )
1497  {
1498  if ( game["teamScores"][team] >= level.scoreLimit )
1499  return false;
1500  }
1501 
1502  return true;
1503 }
1504 
1506 {
1507  if ( game["state"] != "playing" )
1508  return false;
1509 
1510  if ( level.scoreLimit <= 0 )
1511  return false;
1512 
1513  if ( level.teamBased )
1514  {
1516  return false;
1517  }
1518  else
1519  {
1520  if ( !isPlayer( self ) )
1521  return false;
1522 
1523  if ( self.score < level.scoreLimit )
1524  return false;
1525  }
1526 
1527  [[level.onScoreLimit]]();
1528 }
1529 
1530 
1532 {
1533  level endon ( "game_ended" );
1534 
1535  while ( game["state"] == "playing" )
1536  {
1537  roundlimit = ‪math::clamp( GetGametypeSetting( "roundLimit" ), level.roundLimitMin, level.roundLimitMax );
1538  if ( roundlimit != level.roundlimit )
1539  {
1540  level.roundlimit = roundlimit;
1541  level notify ( "update_roundlimit" );
1542  }
1543 
1544  timeLimit = [[level.getTimeLimit]]();
1545  if ( timeLimit != level.timeLimit )
1546  {
1547  level.timeLimit = timeLimit;
1548  SetDvar( "ui_timelimit", level.timeLimit );
1549  level notify ( "update_timelimit" );
1550  }
1551  thread ‪checkTimeLimit();
1552 
1553  scoreLimit = ‪math::clamp( GetGametypeSetting( "scoreLimit" ), level.scoreLimitMin, level.scoreLimitMax );
1554  if ( scoreLimit != level.scoreLimit )
1555  {
1556  level.scoreLimit = scoreLimit;
1557  SetDvar( "ui_scorelimit", level.scoreLimit );
1558  level notify ( "update_scorelimit" );
1559  }
1560  thread ‪checkScoreLimit();
1561 
1562  // make sure we check time limit right when game ends
1563  if ( isdefined( level.startTime ) )
1564  {
1566  {
1567  wait .1;
1568  continue;
1569  }
1570  }
1571  wait 1;
1572  }
1573 }
1574 
1575 
1577 {
1578  offset = 0;
1579  numPlayers = level.placement["all"].size;
1580  found = false;
1581  for ( i = 0; i < numPlayers; i++ )
1582  {
1583  if ( level.placement["all"][i] == self )
1584  found = true;
1585 
1586  if ( found )
1587  level.placement["all"][i] = level.placement["all"][ i + 1 ];
1588  }
1589  if ( !found )
1590  return;
1591 
1592  level.placement["all"][ numPlayers - 1 ] = undefined;
1593  assert( level.placement["all"].size == numPlayers - 1 );
1594 
1596 
1597  if ( level.teamBased )
1598  return;
1599 
1600  numPlayers = level.placement["all"].size;
1601  for ( i = 0; i < numPlayers; i++ )
1602  {
1603  player = level.placement["all"][i];
1604  player notify( "update_outcome" );
1605  }
1606 
1607 }
1608 
1610 {
1611 
1612  if ( !level.players.size )
1613  return;
1614 
1615  level.placement["all"] = [];
1616  foreach ( player in level.players )
1617  {
1618  if ( !level.teambased || isdefined( level.teams[ player.team ] ) )
1619  level.placement["all"][level.placement["all"].size] = player;
1620  }
1621 
1622  placementAll = level.placement["all"];
1623 
1624  for ( i = 1; i < placementAll.size; i++ )
1625  {
1626  player = placementAll[i];
1627  playerScore = player.score;
1628  for ( j = i - 1; j >= 0 && (playerScore > placementAll[j].score || (playerScore == placementAll[j].score && player.deaths < placementAll[j].deaths)); j-- )
1629  placementAll[j + 1] = placementAll[j];
1630  placementAll[j + 1] = player;
1631  }
1632 
1633  level.placement["all"] = placementAll;
1634 
1636 
1637 }
1638 
1639 
1641 {
1642  foreach( team in level.teams )
1643  {
1644  placement[team] = [];
1645  }
1646  placement["spectator"] = [];
1647 
1648  if ( !level.teamBased )
1649  return;
1650 
1651  placementAll = level.placement["all"];
1652  placementAllSize = placementAll.size;
1653 
1654  for ( i = 0; i < placementAllSize; i++ )
1655  {
1656  player = placementAll[i];
1657  if (isdefined(player))
1658  {
1659  team = player.pers["team"];
1660 
1661  placement[team][ placement[team].size ] = player;
1662  }
1663  }
1664 
1665  foreach( team in level.teams )
1666  {
1667  level.placement[team] = placement[team];
1668  }
1669 }
1670 
1671 function ‪getPlacementForPlayer( player )
1672 {
1674 
1675  playerRank = -1;
1676  placement = level.placement["all"];
1677  for ( placementIndex = 0; placementIndex < placement.size; placementIndex++ )
1678  {
1679  if ( level.placement["all"][placementIndex] == player )
1680  {
1681  playerRank = (placementIndex + 1);
1682  break;
1683  }
1684  }
1685 
1686  return playerRank;
1687 }
1688 
1689 function ‪sortDeadPlayers( team )
1690 {
1691  // only need to sort if we are running queued respawn
1692  if ( !level.playerQueuedRespawn )
1693  return;
1694 
1695  // sort by death time
1696  for ( i = 1; i < level.deadPlayers[team].size; i++ )
1697  {
1698  player = level.deadPlayers[team][i];
1699  for ( j = i - 1; j >= 0 && player.deathTime < level.deadPlayers[team][j].deathTime; j-- )
1700  level.deadPlayers[team][j + 1] = level.deadPlayers[team][j];
1701  level.deadPlayers[team][j + 1] = player;
1702  }
1703 
1704  for ( i = 0; i < level.deadPlayers[team].size; i++ )
1705  {
1706  if ( level.deadPlayers[team][i].spawnQueueIndex != i )
1707  {
1708  level.spawnQueueModified[team] = true;
1709  }
1710  level.deadPlayers[team][i].spawnQueueIndex = i;
1711  }
1712 }
1713 
1715 {
1716  count = 0;
1717  foreach( team in level.teams )
1718  {
1719  count += level.aliveCount[team];
1720  }
1721  return count;
1722 }
1723 
1725 {
1726  count = 0;
1727  foreach( team in level.teams )
1728  {
1729  count += level.playerLives[team];
1730  }
1731  return count;
1732 }
1733 
1734 function ‪initTeamVariables( team )
1735 {
1736 
1737  if ( !isdefined( level.aliveCount ) )
1738  level.aliveCount = [];
1739 
1740  level.aliveCount[team] = 0;
1741  level.lastAliveCount[team] = 0;
1742 
1743  level.everExisted[team] = false;
1744  level.waveDelay[team] = 0;
1745  level.lastWave[team] = 0;
1746  level.wavePlayerSpawnIndex[team] = 0;
1747 
1748  ‪resetTeamVariables( team );
1749 }
1750 
1751 function ‪resetTeamVariables( team )
1752 {
1753  level.playerCount[team] = 0;
1754  level.botsCount[team] = 0;
1755  level.lastAliveCount[team] = level.aliveCount[team];
1756  level.aliveCount[team] = 0;
1757  level.playerLives[team] = 0;
1758  level.alivePlayers[team] = [];
1759  level.deadPlayers[team] = [];
1760  level.squads[team] = [];
1761  level.spawnQueueModified[team] = false;
1762 }
1763 
1765 {
1766  // run only once per frame, at the end of the frame.
1767  level notify("updating_team_status");
1768  level endon("updating_team_status");
1769  level endon ( "game_ended" );
1770  waittillframeend;
1771 
1772  wait 0; // Required for Callback_PlayerDisconnect to complete before updateTeamStatus can execute
1773 
1774  if ( game["state"] == "postgame" )
1775  return;
1776 
1777  resetTimeout();
1778 
1779  foreach( team in level.teams )
1780  {
1781  ‪resetTeamVariables( team );
1782  }
1783 
1784  level.activePlayers = [];
1785 
1786  players = level.players;
1787  for ( i = 0; i < players.size; i++ )
1788  {
1789  player = players[i];
1790 
1791  if ( !isdefined( player ) && level.splitscreen )
1792  continue;
1793 
1794  team = player.team;
1795 
1796  if ( team != "spectator" )
1797  {
1798  level.playerCount[team]++;
1799 
1800  if( isdefined( player.pers["isBot"] ) )
1801  level.botsCount[team]++;
1802 
1803  if ( player.sessionstate == "playing" )
1804  {
1805  level.aliveCount[team]++;
1806  level.playerLives[team]++;
1807  player.spawnQueueIndex = -1;
1808 
1809  if ( isAlive( player ) )
1810  {
1811  level.alivePlayers[team][level.alivePlayers[team].size] = player;
1812  level.activeplayers[ level.activeplayers.size ] = player;
1813  }
1814  else
1815  {
1816  level.deadPlayers[team][level.deadPlayers[team].size] = player;
1817  }
1818  }
1819  else
1820  {
1821  level.deadPlayers[team][level.deadPlayers[team].size] = player;
1822  if ( player ‪globallogic_spawn::maySpawn() )
1823  level.playerLives[team]++;
1824  }
1825  }
1826  }
1827 
1828  totalAlive = ‪totalAliveCount();
1829 
1830  if ( totalAlive > level.maxPlayerCount )
1831  level.maxPlayerCount = totalAlive;
1832 
1833  foreach( team in level.teams )
1834  {
1835  if ( level.aliveCount[team] )
1836  level.everExisted[team] = true;
1837 
1838  ‪sortDeadPlayers( team );
1839  }
1840 
1841  level ‪updateGameEvents();
1842 }
1843 
1845 {
1846  assert( isdefined( team ) );
1847 
1848  if ( level.scoreLimit <= 0 )
1849  return;
1850 
1851  if ( !level.teamBased )
1852  return;
1853 
1854  // Give the data a minute to converge/settle
1855  if ( ‪globallogic_utils::getTimePassed() < ( 60 * 1000 ) )
1856  return;
1857 
1859 
1860  if ( timeLeft < 1 )
1861  {
1862  level notify( "match_ending_soon", "score" );
1863  }
1864 }
1865 
1867 {
1868  assert( IsPlayer( self ) );
1869 
1870  if ( level.scoreLimit <= 0 )
1871  return;
1872 
1873  if ( level.teamBased )
1874  return;
1875 
1876  // Give the data a minute to converge/settle
1877  if ( ‪globallogic_utils::getTimePassed() < ( 60 * 1000 ) )
1878  return;
1879 
1881 
1882  if ( timeLeft < 1 )
1883  {
1884  level notify( "match_ending_soon", "score" );
1885  }
1886 }
1887 
1888 function ‪startGame()
1889 {
1891  level.timerStopped = false;
1892  // RF, disabled this, as it is not required anymore.
1893  //thread spawnlogic::spawnPerFrameUpdate();
1894 
1895  SetMatchTalkFlag( "DeadChatWithDead", level.voip.deadChatWithDead );
1896  SetMatchTalkFlag( "DeadChatWithTeam", level.voip.deadChatWithTeam );
1897  SetMatchTalkFlag( "DeadHearTeamLiving", level.voip.deadHearTeamLiving );
1898  SetMatchTalkFlag( "DeadHearAllLiving", level.voip.deadHearAllLiving );
1899  SetMatchTalkFlag( "EveryoneHearsEveryone", level.voip.everyoneHearsEveryone );
1900  SetMatchTalkFlag( "DeadHearKiller", level.voip.deadHearKiller );
1901  SetMatchTalkFlag( "KillersHearVictim", level.voip.killersHearVictim );
1902 
1904  level notify("prematch_over");
1905 
1906  thread ‪gracePeriod();
1907  thread ‪watchMatchEndingSoon();
1908 
1910 
1911 // thread _gametype_variants::onRoundBegin();
1912  recordMatchBegin();
1913 }
1914 
1915 
1917 {
1918  /*
1919  if ( level.teamBased )
1920  while( !level.everExisted[ "axis" ] || !level.everExisted[ "allies" ] )
1921  WAIT_SERVER_FRAME;
1922  else
1923  while ( level.maxPlayerCount < 2 )
1924  WAIT_SERVER_FRAME;
1925  */
1926 }
1927 
1929 {
1930  setMatchFlag( "hud_hardcore", level.hardcoreMode );
1931 
1932  level endon( "game_ended" );
1933 
1934  if ( level.prematchPeriod > 0 )
1935  {
1936  thread ‪matchStartTimer();
1937 
1939 
1940  wait ( level.prematchPeriod );
1941  }
1942  else
1943  {
1945 
1947  }
1948 
1949  level.inPrematchPeriod = false;
1950 
1951  for ( index = 0; index < level.players.size; index++ )
1952  {
1953  level.players[index] ‪util::freeze_player_controls( false );
1954  level.players[index] enableWeapons();
1955  }
1956 
1957 // _wager::prematchPeriod();
1958 
1959  if ( game["state"] != "playing" )
1960  return;
1961 }
1962 
1963 function ‪gracePeriod()
1964 {
1965  level endon("game_ended");
1966 
1967  if ( isdefined( level.gracePeriodFunc ) )
1968  {
1969  [[ level.gracePeriodFunc ]]();
1970  }
1971  else
1972  {
1973  wait ( level.gracePeriod );
1974  }
1975 
1976  level notify ( "grace_period_ending" );
1978 
1979  level.inGracePeriod = false;
1980 
1981  if ( game["state"] != "playing" )
1982  return;
1983 
1984  if ( level.numLives )
1985  {
1986  // Players on a team but without a weapon show as dead since they can not get in this round
1987  players = level.players;
1988 
1989  for ( i = 0; i < players.size; i++ )
1990  {
1991  player = players[i];
1992 
1993  if ( !player.hasSpawned && player.sessionteam != "spectator" && !isAlive( player ) )
1994  player.statusicon = "hud_status_dead";
1995  }
1996  }
1997 
1998  level thread ‪updateTeamStatus();
1999 }
2000 
2002 {
2003  SetDvar( "xblive_matchEndingSoon", 0 );
2004  level waittill( "match_ending_soon", reason );
2005  SetDvar( "xblive_matchEndingSoon", 1 );
2006 }
2007 
2009 {
2010 }
2011 
2013 {
2014  foreach ( team in level.teams )
2015  {
2016  if ( level.waveDelay[team] )
2017  return true;
2018  }
2019 
2020  return false;
2021 }
2022 
2024 {
2025  level.prematchPeriod = 0;
2026  level.intermission = false;
2027 
2028  setmatchflag( "cg_drawSpectatorMessages", 1 );
2029  setmatchflag( "game_ended", 0 );
2030 
2031  if ( !isdefined( game["gamestarted"] ) )
2032  {
2033  // defaults if not defined in level script
2034  if ( !isdefined( game["allies"] ) )
2035  game["allies"] = "seals";
2036  if ( !isdefined( game["axis"] ) )
2037  game["axis"] = "pmc";
2038  if ( !isdefined( game["attackers"] ) )
2039  game["attackers"] = "allies";
2040  if ( !isdefined( game["defenders"] ) )
2041  game["defenders"] = "axis";
2042 
2043  // if this hits the teams are not setup right
2044  assert( game["attackers"] != game["defenders"] );
2045 
2046  // TODO MTEAM - need to update this valid team
2047  foreach( team in level.teams )
2048  {
2049  if ( !isdefined( game[team] ) )
2050  game[team] = "pmc";
2051  }
2052 
2053  if ( !isdefined( game["state"] ) )
2054  game["state"] = "playing";
2055 
2056  //makeDvarServerInfo( "cg_thirdPersonAngle", 354 );
2057 
2058  SetDvar( "cg_thirdPersonAngle", 354 );
2059 
2060  game["strings"]["press_to_spawn"] = &"PLATFORM_PRESS_TO_SPAWN";
2061  if ( level.teamBased )
2062  {
2063  game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_TEAMS";
2064  game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
2065  }
2066  else
2067  {
2068  game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_PLAYERS";
2069  game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
2070  }
2071  game["strings"]["match_starting_in"] = &"MP_MATCH_STARTING_IN";
2072  game["strings"]["spawn_next_round"] = &"MP_SPAWN_NEXT_ROUND";
2073  game["strings"]["waiting_to_spawn"] = &"MP_WAITING_TO_SPAWN";
2074  game["strings"]["waiting_to_spawn_ss"] = &"MP_WAITING_TO_SPAWN_SS";
2075  //game["strings"]["waiting_to_safespawn"] = &"MP_WAITING_TO_SAFESPAWN";
2076  game["strings"]["you_will_spawn"] = &"MP_YOU_WILL_RESPAWN";
2077  game["strings"]["match_starting"] = &"MP_MATCH_STARTING";
2078  game["strings"]["change_class"] = &"MP_CHANGE_CLASS_NEXT_SPAWN";
2079  game["strings"]["last_stand"] = &"MPUI_LAST_STAND";
2080 
2081  game["strings"]["cowards_way"] = &"PLATFORM_COWARDS_WAY_OUT";
2082 
2083  game["strings"]["tie"] = &"MP_MATCH_TIE";
2084  game["strings"]["round_draw"] = &"MP_ROUND_DRAW";
2085 
2086  game["strings"]["enemies_eliminated"] = &"MP_ENEMIES_ELIMINATED";
2087  game["strings"]["score_limit_reached"] = &"MP_SCORE_LIMIT_REACHED";
2088  game["strings"]["round_limit_reached"] = &"MP_ROUND_LIMIT_REACHED";
2089  game["strings"]["time_limit_reached"] = &"MP_TIME_LIMIT_REACHED";
2090  game["strings"]["players_forfeited"] = &"MP_PLAYERS_FORFEITED";
2091 
2093 
2094  [[level.onPrecacheGameType]]();
2095 
2096  game["gamestarted"] = true;
2097 
2098  game["totalKills"] = 0;
2099 
2100  foreach( team in level.teams )
2101  {
2102  game["teamScores"][team] = 0;
2103  game["totalKillsTeam"][team] = 0;
2104  }
2105 
2106  if ( !level.splitscreen )
2107  level.prematchPeriod = GetGametypeSetting( "prematchperiod" );
2108 
2109  if ( GetDvarint( "xblive_clanmatch" ) != 0 )
2110  {
2111  // TODO MTEAM is this code used anymore?
2112  foreach( team in level.teams )
2113  {
2114  game["icons"][team] = "composite_emblem_team_axis";
2115  }
2116 
2117  game["icons"]["allies"] = "composite_emblem_team_allies";
2118  game["icons"]["axis"] = "composite_emblem_team_axis";
2119  }
2120  }
2121 
2122  if(!isdefined(game["timepassed"]))
2123  game["timepassed"] = 0;
2124 
2125  if(!isdefined(game["roundsplayed"]))
2126  game["roundsplayed"] = 0;
2127  SetRoundsPlayed( game["roundsplayed"] );
2128 
2129  if(!isdefined(game["roundwinner"] ))
2130  game["roundwinner"] = [];
2131 
2132  if(!isdefined(game["roundswon"] ))
2133  game["roundswon"] = [];
2134 
2135  if(!isdefined(game["roundswon"]["tie"] ))
2136  game["roundswon"]["tie"] = 0;
2137 
2138  foreach ( team in level.teams )
2139  {
2140  if(!isdefined(game["roundswon"][team] ))
2141  game["roundswon"][team] = 0;
2142 
2143  level.teamSpawnPoints[team] = [];
2144  level.spawn_point_team_class_names[team] = [];
2145  }
2146 
2147  level.skipVote = false;
2148  level.gameEnded = false;
2149  SetDvar( "g_gameEnded", 0 );
2150 
2151  level.objIDStart = 0;
2152  level.forcedEnd = false;
2153  level.hostForcedEnd = false;
2154 
2155  level.hardcoreMode = GetGametypeSetting( "hardcoreMode" );
2156  if ( level.hardcoreMode )
2157  {
2158 
2159 
2160  //set up friendly fire delay for hardcore
2161  if( !isdefined(level.friendlyFireDelayTime) )
2162  level.friendlyFireDelayTime = 0;
2163  }
2164 
2165  if ( GetDvarString( "scr_max_rank" ) == "" )
2166  SetDvar( "scr_max_rank", "0" );
2167  level.rankCap = GetDvarint( "scr_max_rank" );
2168 
2169  if ( GetDvarString( "scr_min_prestige" ) == "" )
2170  {
2171  SetDvar( "scr_min_prestige", "0" );
2172  }
2173  level.minPrestige = GetDvarint( "scr_min_prestige" );
2174 
2175  // this gets set to false when someone takes damage or a gametype-specific event happens.
2176  level.useStartSpawns = true;
2177 
2178  level.cumulativeRoundScores = GetGametypeSetting( "cumulativeRoundScores" );
2179 
2180  level.allowHitMarkers = GetGametypeSetting( "allowhitmarkers" );
2181  level.playerQueuedRespawn = GetGametypeSetting( "playerQueuedRespawn" );
2182  level.playerForceRespawn = GetGametypeSetting( "playerForceRespawn" );
2183 
2184  level.perksEnabled = GetGametypeSetting( "perksEnabled" );
2185  level.disableAttachments = GetGametypeSetting( "disableAttachments" );
2186  level.disableTacInsert = GetGametypeSetting( "disableTacInsert" );
2187  level.disableCAC = GetGametypeSetting( "disableCAC" );
2188  level.disableWeaponDrop = GetGametypeSetting( "disableweapondrop" );
2189  level.onlyHeadShots = GetGametypeSetting( "onlyHeadshots" );
2190 
2191  // set to 0 to disable
2192  level.minimumAllowedTeamKills = GetGametypeSetting( "teamKillPunishCount" ) - 1; // punishment starts at the next one
2193  level.teamKillReducedPenalty = GetGametypeSetting( "teamKillReducedPenalty" );
2194  level.teamKillPointLoss = GetGametypeSetting( "teamKillPointLoss" );
2195  level.teamKillSpawnDelay = GetGametypeSetting( "teamKillSpawnDelay" );
2196 
2197  level.deathPointLoss = GetGametypeSetting( "deathPointLoss" );
2198  level.leaderBonus = GetGametypeSetting( "leaderBonus" );
2199  level.forceRadar = GetGametypeSetting( "forceRadar" );
2200  level.playerSprintTime = GetGametypeSetting( "playerSprintTime" );
2201  level.bulletDamageScalar = GetGametypeSetting( "bulletDamageScalar" );
2202 
2203  level.playerMaxHealth = GetGametypeSetting( "playerMaxHealth" );
2204  level.playerHealthRegenTime = GetGametypeSetting( "playerHealthRegenTime" );
2205 
2206  level.playerRespawnDelay = GetGametypeSetting( "playerRespawnDelay" );
2207  level.playerObjectiveHeldRespawnDelay = GetGametypeSetting( "playerObjectiveHeldRespawnDelay" );
2208  level.waveRespawnDelay = GetGametypeSetting( "waveRespawnDelay" );
2209 
2210  level.spectateType = GetGametypeSetting( "spectateType" );
2211 
2212  level.voip = SpawnStruct();
2213  level.voip.deadChatWithDead = GetGametypeSetting( "voipDeadChatWithDead" );
2214  level.voip.deadChatWithTeam = GetGametypeSetting( "voipDeadChatWithTeam" );
2215  level.voip.deadHearAllLiving = GetGametypeSetting( "voipDeadHearAllLiving" );
2216  level.voip.deadHearTeamLiving = GetGametypeSetting( "voipDeadHearTeamLiving" );
2217  level.voip.everyoneHearsEveryone = GetGametypeSetting( "voipEveryoneHearsEveryone" );
2218  level.voip.deadHearKiller = GetGametypeSetting( "voipDeadHearKiller" );
2219  level.voip.killersHearVictim = GetGametypeSetting( "voipKillersHearVictim" );
2220 
2221  ‪callback::callback( #"on_start_gametype" );
2222 
2223  level.prematchPeriod = 0;
2224 
2225  level.persistentDataInfo = [];
2226  level.maxRecentStats = 10;
2227  level.maxHitLocations = 19;
2228  level.globalShotsFired = 0;
2229 
2230 // thread _class::init();
2231 // thread _menus::init();
2232 // thread _teams::init();
2233 // thread _killcam::init();
2234 // thread _deathicons::init();
2235 // thread _objpoints::init();
2236 // thread _battlechatter_mp::init();
2237 // FIX ME thread _killstreaks::init();
2238  //thread _wager::init();
2239 // thread _gametype_variants::init();
2240  //thread _bot::init();
2241  //thread _decoy::init();
2242 
2243 // if ( level.teamBased )
2244 // thread _friendicons::init();
2245 
2246  thread ‪hud_message::init();
2247  //thread _multi_extracam::init();
2248 
2249  foreach( team in level.teams )
2250  {
2251  ‪initTeamVariables( team );
2252  }
2253 
2254  level.maxPlayerCount = 0;
2255  level.activePlayers = [];
2256 
2257  level.allowAnnouncer = GetGametypeSetting( "allowAnnouncer" );
2258 
2259  if ( !isdefined( level.timeLimit ) )
2260  ‪util::registerTimeLimit( 1, 1440 );
2261 
2262  if ( !isdefined( level.scoreLimit ) )
2263  ‪util::registerScoreLimit( 1, 500 );
2264 
2265  if ( !isdefined( level.roundLimit ) )
2266  ‪util::registerRoundLimit( 0, 10 );
2267 
2268  if ( !isdefined( level.roundWinLimit ) )
2270 
2271  // The order the following functions are registered in are the order they will get called
2272 // globallogic_utils::registerPostRoundEvent( _killcam::postRoundFinalKillcam );
2273 // globallogic_utils::registerPostRoundEvent( _wager::postRoundSideBet );
2274 
2275  //makeDvarServerInfo( "ui_scorelimit" );
2276  //makeDvarServerInfo( "ui_timelimit" );
2277  //makeDvarServerInfo( "ui_allow_classchange", GetDvarString( "ui_allow_classchange" ) );
2278 
2279  waveDelay = level.waveRespawnDelay;
2280  if ( waveDelay )
2281  {
2282  foreach ( team in level.teams )
2283  {
2284  level.waveDelay[team] = waveDelay;
2285  level.lastWave[team] = 0;
2286  }
2287 
2288  level thread [[level.waveSpawnTimer]]();
2289  }
2290 
2291  level.inPrematchPeriod = true;
2292 
2293  if ( level.prematchPeriod > 2.0 )
2294  level.prematchPeriod = level.prematchPeriod + (randomFloat( 4 ) - 2); // live host obfuscation
2295 
2296  if ( level.numLives || ‪anyTeamHasWaveDelay() || level.playerQueuedRespawn )
2297  level.gracePeriod = 15;
2298  else
2299  level.gracePeriod = 5;
2300 
2301  level.inGracePeriod = true;
2302 
2303  level.roundEndDelay = 5;
2304  level.halftimeRoundEndDelay = 3;
2305 
2307 
2308  level.killstreaksenabled = 1;
2309 
2310  if ( GetDvarString( "scr_game_rankenabled" ) == "" )
2311  SetDvar( "scr_game_rankenabled", true );
2312  level.rankEnabled = GetDvarint( "scr_game_rankenabled" );
2313 
2314  if ( GetDvarString( "scr_game_medalsenabled" ) == "" )
2315  SetDvar( "scr_game_medalsenabled", true );
2316  level.medalsEnabled = GetDvarint( "scr_game_medalsenabled" );
2317 
2318  if( level.hardcoreMode && level.rankedMatch && GetDvarString( "scr_game_friendlyFireDelay" ) == "" )
2319  SetDvar( "scr_game_friendlyFireDelay", true );
2320  level.friendlyFireDelay = GetDvarint( "scr_game_friendlyFireDelay" );
2321 
2322  // level gametype and features globals should be defaulted before this, and level.onstartgametype should reset them if desired
2323  [[level.onStartGameType]]();
2324 
2325  // disable killstreaks for custom game modes
2326  if( GetDvarInt( "custom_killstreak_mode" ) == 1 )
2327  {
2328  level.killstreaksenabled = 0;
2329  }
2330 
2331  //level thread _killcam::doFinalKillcam();
2332 
2333  thread ‪startGame();
2334  level thread ‪updateGameTypeDvars();
2335  level thread simple_hostmigration::UpdateHostMigrationData();
2336 
2337 }
2338 
2339 
2340 function ‪registerFriendlyFireDelay( dvarString, defaultValue, minValue, maxValue )
2341 {
2342  dvarString = ("scr_" + dvarString + "_friendlyFireDelayTime");
2343  if ( GetDvarString( dvarString ) == "" )
2344  SetDvar( dvarString, defaultValue );
2345 
2346  if ( getDvarInt( dvarString ) > maxValue )
2347  SetDvar( dvarString, maxValue );
2348  else if ( getDvarInt( dvarString ) < minValue )
2349  SetDvar( dvarString, minValue );
2350 
2351  level.friendlyFireDelayTime = getDvarInt( dvarString );
2352 }
2353 
2355 {
2356  if ( !isdefined( level.roundSwitch ) || !level.roundSwitch )
2357  return false;
2358  if ( !isdefined( level.onRoundSwitch ) )
2359  return false;
2360 
2361  assert( game["roundsplayed"] > 0 );
2362 
2363  if ( game["roundsplayed"] % level.roundswitch == 0 )
2364  {
2365  [[level.onRoundSwitch]]();
2366  return true;
2367  }
2368 
2369  return false;
2370 }
2371 
2372 
2374 {
2375  self waittill( "host_sucks_end_game" );
2376  //if ( level.console )
2377  // endparty();
2378  level.skipVote = true;
2379 
2380  if ( !level.gameEnded )
2381  level thread ‪globallogic::forceEnd(true);
2382 }
2383 
2384 
2385 function ‪getKillStreaks( player )
2386 {
2387  for ( killstreakNum = 0; killstreakNum < level.maxKillstreaks; killstreakNum++ )
2388  {
2389  killstreak[ killstreakNum ] = "killstreak_null";
2390  }
2391 
2392  if ( isPlayer( player ) && !level.oldschool && ( level.disableCAC != 1 ) &&
2393  ( !isdefined( player.pers["isBot"] ) && isdefined(player.killstreak) ) )
2394  {
2395  currentKillstreak = 0;
2396  for ( killstreakNum = 0; killstreakNum < level.maxKillstreaks; killstreakNum++ )
2397  {
2398  if ( isdefined( player.killstreak[ killstreakNum ] ) )
2399  {
2400  killstreak[ currentKillstreak ] = player.killstreak[ killstreakNum ];
2401  currentKillstreak++;
2402  }
2403  }
2404  }
2405 
2406  return killstreak;
2407 }
2408 
2409 function ‪updateRankedMatch(winner)
2410 {
2411  if ( level.rankedMatch )
2412  {
2413  if ( ‪hostIdledOut() )
2414  {
2415  level.hostForcedEnd = true;
2416 
2417  endLobby();
2418  }
2419  }
2420 }
‪endGame
‪function endGame(winner, endReasonText)
Definition: _globallogic.gsc:1950
‪default_onDeadEvent
‪function default_onDeadEvent(team)
Definition: _globallogic_defaults.gsc:83
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪SetupCallbacks
‪function SetupCallbacks()
Definition: _globallogic.gsc:256
‪updateAllTeamScores
‪function updateAllTeamScores()
Definition: _globallogic_score.gsc:849
‪recordActivePlayersEndGameMatchRecordStats
‪function recordActivePlayersEndGameMatchRecordStats()
Definition: _globallogic_player.gsc:2601
‪anyTeamHasWaveDelay
‪function anyTeamHasWaveDelay()
Definition: _globallogic.gsc:3535
‪set_music_on_player
‪function set_music_on_player(state, wait_time=0, save_state=false, return_state=false)
Definition: _globallogic_audio.gsc:1053
‪isOneRound
‪function isOneRound()
Definition: util_shared.gsc:3497
‪checkScoreLimit
‪function checkScoreLimit()
Definition: _globallogic.gsc:2533
‪teamWagerOutcomeNotify
‪function teamWagerOutcomeNotify(winner, isRoundEnd, endReasonText)
Definition: _hud_message.gsc:612
‪blank
‪function blank(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
Definition: _globallogic.gsc:333
‪sortDeadPlayers
‪function sortDeadPlayers(team)
Definition: _globallogic.gsc:2837
‪waitForPlayers
‪function waitForPlayers()
Definition: _globallogic.gsc:3322
‪prematchPeriod
‪function prematchPeriod()
Definition: _globallogic.gsc:3434
‪updatePlacement
‪function updatePlacement()
Definition: _globallogic.gsc:2692
‪registerRoundWinLimit
‪function registerRoundWinLimit(minValue, maxValue)
Definition: _util.gsc:630
‪totalAliveCount
‪function totalAliveCount()
Definition: _globallogic.gsc:2862
‪gameHistoryPlayerQuit
‪function gameHistoryPlayerQuit()
Definition: _globallogic.gsc:1423
‪compareTeamByTeamScore
‪function compareTeamByTeamScore(teamA, teamB, previous_winner_score)
Definition: _globallogic.gsc:597
‪updateGameEvents
‪function updateGameEvents()
Definition: _globallogic.gsc:929
‪hitScoreLimit
‪function hitScoreLimit()
Definition: util_shared.gsc:3650
‪default_onTimeLimit
‪function default_onTimeLimit()
Definition: _globallogic_defaults.gsc:206
‪executePostRoundEvents
‪function executePostRoundEvents()
Definition: _globallogic_utils.gsc:122
‪killserverPc
‪function killserverPc()
Definition: _globallogic.gsc:690
‪doDeadEventUpdates
‪function doDeadEventUpdates()
Definition: _globallogic.gsc:850
‪forceEnd
‪function forceEnd(hostsucks)
Definition: _globallogic.gsc:643
‪matchStartTimerSkip
‪function matchStartTimerSkip()
Definition: _globallogic.gsc:1070
‪updateTeamPlacement
‪function updateTeamPlacement()
Definition: _globallogic.gsc:2737
‪gameResultBookmark
‪function gameResultBookmark(type, winningTeamIndex, losingTeamIndex)
Definition: demo_shared.gsc:74
‪precache_mp_leaderboards
‪function precache_mp_leaderboards()
Definition: _globallogic.gsc:526
‪getTimeRemaining
‪function getTimeRemaining()
Definition: _globallogic_utils.gsc:109
‪default_onRoundEndGame
‪function default_onRoundEndGame(winner)
Definition: _globallogic_defaults.gsc:143
‪gracePeriod
‪function gracePeriod()
Definition: _globallogic.gsc:3471
‪getBaseWeaponParam
‪function getBaseWeaponParam(weapon)
Definition: _weapon_utils.gsc:7
‪spawnPlayer
‪function spawnPlayer()
Definition: _globallogic_spawn.gsc:227
‪setPoint
‪function setPoint(point, relativePoint, xOffset, yOffset, moveTime)
Definition: hud_util_shared.gsc:53
‪isOnlyOneLeftAliveOnTeam
‪function isOnlyOneLeftAliveOnTeam(team)
Definition: _globallogic.gsc:896
‪updateWeaponTimings
‪function updateWeaponTimings(newTime)
Definition: _weapons.gsc:133
‪GAMEMODE_PUBLIC_MATCH
‪#define GAMEMODE_PUBLIC_MATCH
Definition: shared.gsh:10
‪maySpawn
‪function maySpawn()
Definition: _globallogic_spawn.gsc:93
‪figureOutAttacker
‪function figureOutAttacker(eAttacker)
Definition: _globallogic_player.gsc:633
‪announceRoundWinner
‪function announceRoundWinner(winner, delay)
Definition: _globallogic_audio.gsc:311
‪teamOutcomeNotify
‪function teamOutcomeNotify(winner, endType, endReasonText)
Definition: _hud_message.gsc:80
‪registerFriendlyFireDelay
‪function registerFriendlyFireDelay(dvarString, defaultValue, minValue, maxValue)
Definition: _globallogic.gsc:3917
‪recordZMEndGameComScoreEventForPlayer
‪function recordZMEndGameComScoreEventForPlayer(player, result)
Definition: _globallogic_player.gsc:468
‪destroyElem
‪function destroyElem()
Definition: hud_util_shared.gsc:755
‪freezePlayerForRoundEnd
‪function freezePlayerForRoundEnd()
Definition: _globallogic_player.gsc:81
‪wagerOutcomeNotify
‪function wagerOutcomeNotify(winner, endReasonText)
Definition: _hud_message.gsc:448
‪updateRankedMatch
‪function updateRankedMatch(winner)
Definition: _globallogic.gsc:3988
‪freeze_player_controls
‪function freeze_player_controls(b_frozen=true)
Definition: util_shared.gsc:2474
‪default_onScoreLimit
‪function default_onScoreLimit()
Definition: _globallogic_defaults.gsc:234
‪someoneOnEachTeam
‪function someoneOnEachTeam()
Definition: _globallogic.gsc:495
‪waveSpawnTimer
‪function waveSpawnTimer()
Definition: _globallogic.gsc:1091
‪displayGameEnd
‪function displayGameEnd(winner, endReasonText)
Definition: _globallogic.gsc:1580
‪default_onTeamScore
‪function default_onTeamScore(event, team)
Definition: _globallogic_score.gsc:995
‪registerScoreLimit
‪function registerScoreLimit(minValue, maxValue)
Definition: _util.gsc:638
‪roundEndWait
‪function roundEndWait(defaultDelay, matchBonus)
Definition: _globallogic.gsc:2421
‪compareTeamByGameStat
‪function compareTeamByGameStat(gameStat, teamA, teamB, previous_winner_score)
Definition: _globallogic.gsc:557
‪notifyTeamWaveSpawn
‪function notifyTeamWaveSpawn(team, time)
Definition: _globallogic.gsc:1081
‪registerDialogGroup
‪function registerDialogGroup(group, skipIfCurrentlyPlayingGroup)
Definition: _globallogic_audio.gsc:217
‪wasLastRound
‪function wasLastRound()
Definition: util_shared.gsc:3521
‪checkTimeLimit
‪function checkTimeLimit()
Definition: _globallogic.gsc:2474
‪setMatchScoreHUDElemForTeam
‪function setMatchScoreHUDElemForTeam(team)
Definition: ctf.gsc:348
‪getEstimatedTimeUntilScoreLimit
‪function getEstimatedTimeUntilScoreLimit(team)
Definition: _globallogic_utils.gsc:353
‪checkForAnyTeamForfeit
‪function checkForAnyTeamForfeit()
Definition: _globallogic.gsc:519
‪totalPlayerLives
‪function totalPlayerLives()
Definition: _globallogic.gsc:2872
‪getEndReasonText
‪function getEndReasonText()
Definition: _globallogic.gsc:1704
‪IncrementMatchCompletionStat
‪function IncrementMatchCompletionStat(gameMode, playedOrHosted, stat)
Definition: _globallogic.gsc:1119
‪Callback_StartGameType
‪function Callback_StartGameType()
Definition: _globallogic.gsc:3546
‪displayRoundSwitch
‪function displayRoundSwitch(winner, endReasonText)
Definition: _globallogic.gsc:1514
‪listenForGameEnd
‪function listenForGameEnd()
Definition: _globallogic.gsc:3950
‪SetMatchCompletionStat
‪function SetMatchCompletionStat(gameMode, playedOrHosted, stat)
Definition: _globallogic.gsc:1124
‪registerDvars
‪function registerDvars()
Definition: _globallogic.gsc:295
‪updateTeamStatus
‪function updateTeamStatus()
Definition: _globallogic.gsc:2920
‪GetCurrentGameMode
‪function GetCurrentGameMode()
Definition: util_shared.gsc:3750
‪_setPlayerScore
‪function _setPlayerScore(player, score)
Definition: _globallogic_score.gsc:519
‪_getPlayerScore
‪function _getPlayerScore(player)
Definition: _globallogic_score.gsc:538
‪init
‪function init()
Definition: _globallogic.gsc:141
‪getTimePassed
‪function getTimePassed()
Definition: _globallogic_utils.gsc:274
‪allDeadTeamCount
‪function allDeadTeamCount()
Definition: _globallogic.gsc:564
‪totalPlayerCount
‪function totalPlayerCount()
Definition: util_shared.gsc:3482
‪gameTimer
‪function gameTimer()
Definition: _globallogic_utils.gsc:196
‪determineTeamWinnerByTeamScore
‪function determineTeamWinnerByTeamScore()
Definition: _globallogic.gsc:624
‪bbPlayerMatchEnd
‪function bbPlayerMatchEnd(gameLength, endReasonString, gameOver)
Definition: _globallogic.gsc:2417
‪updateGameTypeDvars
‪function updateGameTypeDvars()
Definition: _globallogic.gsc:2606
‪allTeamsUnderScoreLimit
‪function allTeamsUnderScoreLimit()
Definition: _globallogic.gsc:1494
‪determineTeamWinnerByGameStat
‪function determineTeamWinnerByGameStat(gameStat)
Definition: _globallogic.gsc:578
‪hostIdledOut
‪function hostIdledOut()
Definition: _globallogic.gsc:1108
‪default_onSpawnIntermission
‪function default_onSpawnIntermission(endGame)
Definition: _globallogic_defaults.gsc:310
‪assertTeamVariables
‪function assertTeamVariables()
Definition: _globallogic.gsc:3517
‪watchMatchEndingSoon
‪function watchMatchEndingSoon()
Definition: _globallogic.gsc:3510
‪logTeamWinString
‪function logTeamWinString(wintype, winner)
Definition: _globallogic_utils.gsc:498
‪givePlayerScore
‪function givePlayerScore(event, player, victim, descValue, weapon)
Definition: _globallogic_score.gsc:431
‪default_onOneLeftEvent
‪function default_onOneLeftEvent(team)
Definition: _globallogic_defaults.gsc:175
‪areAllTeamsDead
‪function areAllTeamsDead()
Definition: _globallogic.gsc:809
‪announceGameWinner
‪function announceGameWinner(winner, delay)
Definition: _globallogic_audio.gsc:337
‪musicController
‪function musicController()
Definition: _globallogic_audio.gsc:679
‪getPlacementForPlayer
‪function getPlacementForPlayer(player)
Definition: _globallogic.gsc:2765
‪checkPlayerScoreLimitSoon
‪function checkPlayerScoreLimitSoon()
Definition: _globallogic.gsc:3124
‪flushDialog
‪function flushDialog()
Definition: _globallogic_audio.gsc:456
‪doSpawnQueueUpdates
‪function doSpawnQueueUpdates()
Definition: _globallogic.gsc:793
‪isTeamAllDead
‪function isTeamAllDead(team)
Definition: _globallogic.gsc:804
‪createServerFontString
‪function createServerFontString(font, fontScale, team)
Definition: hud_util_shared.gsc:353
‪outcomeNotify
‪function outcomeNotify(winner, isRoundEnd, endReasonText)
Definition: _hud_message.gsc:386
‪getHostPlayer
‪function getHostPlayer()
Definition: util_shared.gsc:2904
‪registerRoundLimit
‪function registerRoundLimit(minValue, maxValue)
Definition: _util.gsc:622
‪getHighestScoringPlayer
‪function getHighestScoringPlayer()
Definition: _globallogic_score.gsc:279
‪doOneLeftEventUpdates
‪function doOneLeftEventUpdates()
Definition: _globallogic.gsc:902
‪freeGameplayHudElems
‪function freeGameplayHudElems()
Definition: _globallogic_ui.gsc:51
‪default_spawnMessage
‪function default_spawnMessage()
Definition: _globallogic_spawn.gsc:818
‪hitRoundLimit
‪function hitRoundLimit()
Definition: util_shared.gsc:3547
‪giveTeamScore
‪function giveTeamScore(event, team, player, victim)
Definition: _globallogic_score.gsc:727
‪resetOutcomeForAllPlayers
‪function resetOutcomeForAllPlayers()
Definition: _globallogic.gsc:1728
‪recordZMEndGameComScoreEvent
‪function recordZMEndGameComScoreEvent(winner)
Definition: _globallogic.gsc:1173
‪getGameLength
‪function getGameLength()
Definition: _globallogic.gsc:1129
‪_setTeamScore
‪function _setTeamScore(team, teamScore)
Definition: _globallogic_score.gsc:795
‪default_onForfeit
‪function default_onForfeit(team)
Definition: _globallogic_defaults.gsc:30
‪spawnSpectator
‪function spawnSpectator(origin, angles)
Definition: _globallogic_spawn.gsc:532
‪default_getTimeLimit
‪function default_getTimeLimit()
Definition: _globallogic_defaults.gsc:332
‪MATCH_QUIT
‪#define MATCH_QUIT
Definition: _globallogic.gsc:44
‪checkTeamScoreLimitSoon
‪function checkTeamScoreLimitSoon(team)
Definition: _globallogic.gsc:3102
‪figureOutFriendlyFire
‪function figureOutFriendlyFire(victim)
Definition: _globallogic_player.gsc:672
‪startGame
‪function startGame()
Definition: _globallogic.gsc:3235
‪getKillStreaks
‪function getKillStreaks(player)
Definition: _globallogic.gsc:3962
‪initTeamVariables
‪function initTeamVariables(team)
Definition: _globallogic.gsc:2882
‪resetTeamVariables
‪function resetTeamVariables(team)
Definition: _globallogic.gsc:2906
‪removeDisconnectedPlayerFromPlacement
‪function removeDisconnectedPlayerFromPlacement()
Definition: _globallogic.gsc:2659
‪displayRoundEnd
‪function displayRoundEnd(winner, endReasonText)
Definition: _globallogic.gsc:1455
‪clamp
‪function clamp(val, val_min, val_max)
Definition: math_shared.csc:16
‪spawnIntermission
‪function spawnIntermission(useDefaultCallback, endGame)
Definition: _globallogic_spawn.gsc:703
‪hitRoundWinLimit
‪function hitRoundWinLimit()
Definition: util_shared.gsc:3609
‪spawnClient
‪function spawnClient(timeAlreadyPassed)
Definition: _globallogic_spawn.gsc:832
‪default_onAliveCountChange
‪function default_onAliveCountChange(team)
Definition: _globallogic_defaults.gsc:139
‪_getTeamScore
‪function _getTeamScore(team)
Definition: _globallogic_score.gsc:857
‪default_isKillBoosting
‪function default_isKillBoosting()
Definition: _globallogic_score.gsc:1470
‪getRoundSwitchDialog
‪function getRoundSwitchDialog(switchType)
Definition: _globallogic_audio.gsc:903
‪registerTimeLimit
‪function registerTimeLimit(minValue, maxValue)
Definition: _util.gsc:655
‪default_onPlayerScore
‪function default_onPlayerScore(event, player, victim)
Definition: _globallogic_score.gsc:504
‪default_onSpawnSpectator
‪function default_onSpawnSpectator(origin, angles)
Definition: _globallogic_defaults.gsc:295
‪matchStartTimer
‪function matchStartTimer()
Definition: _globallogic.gsc:1015
‪checkIfTeamForfeits
‪function checkIfTeamForfeits(team)
Definition: _globallogic.gsc:748
‪checkRoundSwitch
‪function checkRoundSwitch()
Definition: _globallogic.gsc:3931
‪leaderDialogOnPlayer
‪function leaderDialogOnPlayer(dialog, group)
Definition: _globallogic_audio.gsc:548
‪spawnPlayerPrediction
‪function spawnPlayerPrediction()
Definition: _globallogic_spawn.gsc:162
‪roundEndDOF
‪function roundEndDOF(time)
Definition: _globallogic.gsc:2468
‪startNextRound
‪function startNextRound(winner, endReasonText)
Definition: _globallogic.gsc:1748
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265