‪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\shared\bb_shared;
2 #using scripts\codescripts\struct;
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\challenges_shared;
6 #using scripts\shared\damagefeedback_shared;
7 #using scripts\shared\demo_shared;
8 #using scripts\shared\gameobjects_shared;
9 #using scripts\shared\hostmigration_shared;
10 #using scripts\shared\hud_shared;//DO NOT REMOVE - needed for system registration
11 #using scripts\shared\hud_message_shared;
12 #using scripts\shared\hud_util_shared;
13 #using scripts\shared\math_shared;
14 #using scripts\shared\music_shared;
15 #using scripts\shared\objpoints_shared;
16 #using scripts\shared\persistence_shared;
17 #using scripts\shared\rank_shared;
18 #using scripts\shared\util_shared;
19 #using scripts\shared\simple_hostmigration;
20 #using scripts\shared\system_shared;
21 #using scripts\shared\tweakables_shared;
22 #using scripts\shared\visionset_mgr_shared;
23 #using scripts\shared\lui_shared;
24 #using scripts\shared\weapons\_hive_gun;
25 #using scripts\shared\weapons\_weapon_utils;
26 #using scripts\shared\weapons\_weapons;
27 #using scripts\mp\gametypes\_dogtags;
28 
29 #using scripts\shared\bots\_bot;
30 
31 #using scripts\mp\gametypes\_battlechatter;//DO NOT REMOVE - needed for system registration
32 #using scripts\mp\gametypes\_clientids;//DO NOT REMOVE - needed for system registration
33 #using scripts\mp\gametypes\_deathicons;//DO NOT REMOVE - needed for system registration
34 #using scripts\mp\gametypes\_dev;
35 #using scripts\mp\gametypes\_friendicons;
36 #using scripts\mp\gametypes\_globallogic_audio;
37 #using scripts\mp\gametypes\_globallogic_defaults;
38 #using scripts\mp\gametypes\_globallogic_player;
39 #using scripts\mp\gametypes\_globallogic_score;
40 #using scripts\mp\gametypes\_globallogic_spawn;
41 #using scripts\mp\gametypes\_globallogic_ui;
42 #using scripts\mp\gametypes\_globallogic_utils;
43 #using scripts\mp\gametypes\_healthoverlay;//DO NOT REMOVE - needed for system registration
44 #using scripts\mp\gametypes\_hostmigration;
45 #using scripts\mp\gametypes\_hud_message;
46 #using scripts\mp\gametypes\_killcam;//DO NOT REMOVE - needed for system registration
47 #using scripts\mp\gametypes\_loadout;
48 #using scripts\mp\gametypes\_menus;//DO NOT REMOVE - needed for system registration
49 #using scripts\mp\gametypes\_scoreboard;//DO NOT REMOVE - needed for system registration
50 #using scripts\mp\gametypes\_serversettings;//DO NOT REMOVE - needed for system registration
51 #using scripts\mp\gametypes\_shellshock;
52 #using scripts\mp\gametypes\_spawning;//DO NOT REMOVE - needed for system registration
53 #using scripts\mp\gametypes\_spawnlogic;//DO NOT REMOVE - needed for system registration
54 #using scripts\mp\gametypes\_spectating;//DO NOT REMOVE - needed for system registration
55 #using scripts\mp\gametypes\_weapon_utils;
56 #using scripts\mp\gametypes\_weapons;//DO NOT REMOVE - needed for system registration
57 
58 #using scripts\mp\_arena;
59 #using scripts\mp\_behavior_tracker;
60 #using scripts\mp\_challenges;
61 #using scripts\mp\_gameadvertisement;
62 #using scripts\mp\_gamerep;
63 #using scripts\mp\_rat;
64 #using scripts\mp\_teamops;
65 #using scripts\mp\_util;
66 #using scripts\mp\bots\_bot;//DO NOT REMOVE - needed for system registration
67 #using scripts\mp\killstreaks\_dogs;
68 #using scripts\mp\killstreaks\_killstreaks;//DO NOT REMOVE - needed for system registration
69 #using scripts\mp\teams\_teams;//DO NOT REMOVE - needed for system registration
70 
71 #insert scripts\mp\gametypes\_globallogic.gsh;
72 
73 #insert scripts\shared\shared.gsh;
74 #insert scripts\shared\version.gsh;
75 
76 // must match the stats.ddl quitTypes_e enum
77 #define MATCH_KICKED 2
78 #define MATCH_QUIT 3
79 #define MATCH_FINISHED 4
80 
81 #define TAUNT_TYPE_FIRST_PLACE 0
82 
83 #define GESTURE_TYPE_GOOD_GAME 0
84 #define GESTURE_TYPE_THREATEN 1
85 #define GESTURE_TYPE_BOAST 2
86 #define GESTURE_TYPE_MAX 7
87 
88 #define OTHER_LOOTXP_UPLOADSTAT_WAITTIME 1.0
89 #define WAIT_TIME_BEFORE_AWARDING_LOOT_XP 3.0
90 
91 #namespace globallogic;
92 
93 #precache( "model", "tag_origin" );
94 
95 #precache( "statusicon", "hud_status_dead" );
96 #precache( "statusicon", "hud_status_connecting" );
97 
98 #precache( "material", "white" );
99 #precache( "material", "black" );
100 
101 #precache( "string", "PLATFORM_PRESS_TO_SPAWN" );
102 #precache( "string", "MP_WAITING_FOR_TEAMS" );
103 #precache( "string", "MP_OPPONENT_FORFEITING_IN" );
104 #precache( "string", "MP_WAITING_FOR_PLAYERS" );
105 #precache( "string", "MP_OPPONENT_FORFEITING_IN" );
106 #precache( "string", "MP_MATCH_STARTING_IN" );
107 #precache( "string", "MP_SPAWN_NEXT_ROUND" );
108 #precache( "string", "MP_WAITING_TO_SPAWN" );
109 #precache( "string", "MP_WAITING_TO_SPAWN_SS" );
110 #precache( "string", "MP_YOU_WILL_RESPAWN" );
111 #precache( "string", "MP_MATCH_STARTING" );
112 #precache( "string", "MP_CHANGE_CLASS_NEXT_SPAWN" );
113 #precache( "string", "MPUI_LAST_STAND" );
114 #precache( "string", "PLATFORM_COWARDS_WAY_OUT" );
115 #precache( "string", "MP_MATCH_TIE" );
116 #precache( "string", "MP_ROUND_DRAW" );
117 #precache( "string", "MP_ENEMIES_ELIMINATED" );
118 #precache( "string", "MP_SCORE_LIMIT_REACHED" );
119 #precache( "string", "MP_ROUND_LIMIT_REACHED" );
120 #precache( "string", "MP_TIME_LIMIT_REACHED" );
121 #precache( "string", "MP_PLAYERS_FORFEITED" );
122 #precache( "string", "MP_OTHER_TEAMS_FORFEITED" );
123 
124 #precache( "eventstring", "prematch_waiting_for_players" );
125 #precache( "eventstring", "create_prematch_timer" );
126 #precache( "eventstring", "prematch_timer_ended" );
127 #precache( "eventstring", "force_scoreboard" );
128 
129 #precache( "menu", "T7Hud_MP" );
130 
131 ‪REGISTER_SYSTEM( "globallogic", &‪__init__, "visionset_mgr" )
132 
133 function ‪__init__()
134 {
135  ‪DEFAULT( level.vsmgr_prio_visionset_mpintro, ‪MPINTRO_VISIONSET_PRIORITY );
137  level.host_migration_activate_visionset_func = &‪mpintro_visionset_activate_func;
138  level.host_migration_deactivate_visionset_func = &‪mpintro_visionset_deactivate_func;
139 }
140 
141 function ‪init()
142 {
143  level.splitscreen = isSplitScreen();
144  level.xenon = (GetDvarString( "xenonGame") == "true");
145  level.ps3 = (GetDvarString( "ps3Game") == "true");
146  level.wiiu = (GetDvarString( "wiiuGame") == "true");
147  level.orbis = (GetDvarString( "orbisGame") == "true");
148  level.durango = (GetDvarString( "durangoGame") == "true");
149 
150  level.onlineGame = SessionModeIsOnlineGame();
151  level.systemLink = SessionModeIsSystemlink();
152  level.console = (level.xenon || level.ps3 || level.wiiu || level.orbis || level.durango);
153 
154  level.rankedMatch = ( GameModeIsUsingXP() );
155  level.leagueMatch = false;
156  level.customMatch = ( GameModeIsMode( ‪GAMEMODE_PRIVATE_MATCH ) );
157  level.arenaMatch = GameModeIsArena();
158 
159  level.mpCustomMatch = level.customMatch;
160 
161  level.contractsEnabled = !GetGametypeSetting( "disableContracts" );
162 
163  level.contractsEnabled = false;
164 
165  level.disableVehicleBurnDamage = true;
166 
167  level.script = toLower( GetDvarString( "mapname" ) );
168  level.gametype = toLower( GetDvarString( "g_gametype" ) );
169 
170  level.teamBased = false;
171  level.teamCount = GetGametypeSetting( "teamCount" );
172  level.multiTeam = ( level.teamCount > 2 );
173 
174  // used to loop through all valid playing teams ( not spectator )
175  // can also be used to check if a team is valid ( isdefined( level.teams[team] ) )
176  // NOTE: added in the same order they are defined in code
177  level.teams = [];
178  level.teamIndex = [];
179 
180  teamCount = level.teamCount;
181 
182  if ( level.teamCount == 1 )
183  {
184  teamCount = 18;
185  level.teams[ "free" ] = "free";
186  }
187 
188  level.teams[ "allies" ] = "allies";
189  level.teams[ "axis" ] = "axis";
190 
191  level.teamIndex[ "neutral" ] = 0; // Neutral team set to 0 so that it can be used by objectives
192  level.teamIndex[ "allies" ] = 1;
193  level.teamIndex[ "axis" ] = 2;
194 
195  for( teamIndex = 3; teamIndex <= teamCount; teamIndex++ )
196  {
197  level.teams[ "team" + teamIndex ] = "team" + teamIndex;
198  level.teamIndex[ "team" + teamIndex ] = teamIndex;
199  }
200 
201  level.overrideTeamScore = false;
202  level.overridePlayerScore = false;
203  level.displayHalftimeText = false;
204  level.displayRoundEndText = true;
205 
206  level.clampScoreLimit = true;
207  level.endGameOnScoreLimit = true;
208  level.endGameOnTimeLimit = true;
209  level.scoreRoundWinBased = false;
210  level.resetPlayerScoreEveryRound = false;
211  level.doEndgameScoreboard = true;
212 
213  level.gameForfeited= false;
214  level.forceAutoAssign = false;
215 
216  level.halftimeType = "halftime";
217  level.halftimeSubCaption = &"MP_SWITCHING_SIDES_CAPS";
218 
219  level.lastStatusTime = 0;
220  level.wasWinning = [];
221 
222  level.lastSlowProcessFrame = 0;
223 
224  level.placement = [];
225  foreach( team in level.teams )
226  {
227  level.placement[team] = [];
228  }
229  level.placement["all"] = [];
230 
231  level.postRoundTime = 7.0;//Kevin Sherwood changed to 9 to have enough time for music stingers
232 
233  level.inOvertime = false;
234 
235  level.defaultOffenseRadius = 560;
236  level.defaultOffenseRadiusSQ = level.defaultOffenseRadius * level.defaultOffenseRadius;
237 
238  level.dropTeam = GetDvarint( "sv_maxclients" );
239 
240  level.inFinalKillcam = false;
241 
243 
246 
247  level.oldschool = GetGametypeSetting( "oldschoolMode" );
248 
250 
251  if ( !isdefined( game["tiebreaker"] ) )
252  game["tiebreaker"] = false;
253 
255  thread ‪gamerep::init();
256  thread ‪teamops::init();
257 
258  level.disableChallenges = false;
259 
260  if ( level.leagueMatch || ( GetDvarInt( "scr_disableChallenges" ) > 0 ) )
261  {
262  level.disableChallenges = true;
263  }
264 
265  level.disableStatTracking = ( GetDvarInt( "scr_disableStatTracking" ) > 0 );
266 
268 
269  //handles both actor and player corpse cases
270  ‪clientfield::register( "playercorpse", "firefly_effect", ‪VERSION_SHIP, 2, "int" );
271  ‪clientfield::register( "playercorpse", "annihilate_effect", ‪VERSION_SHIP, 1, "int" );
272  ‪clientfield::register( "playercorpse", "pineapplegun_effect", ‪VERSION_SHIP, 1, "int" );
273  ‪clientfield::register( "actor", "annihilate_effect", ‪VERSION_SHIP, 1, "int" );
274  ‪clientfield::register( "actor", "pineapplegun_effect", ‪VERSION_SHIP, 1, "int" );
275  ‪clientfield::register( "world", "game_ended", ‪VERSION_SHIP, 1, "int" );
276  ‪clientfield::register( "world", "post_game", ‪VERSION_SHIP, 1, "int" );
277  ‪clientfield::register( "world", "displayTop3Players", ‪VERSION_SHIP, 1, "int" );
278  ‪clientfield::register( "world", "triggerScoreboardCamera", ‪VERSION_SHIP, 1, "int" );
279  ‪clientfield::register( "clientuimodel", "hudItems.hideOutcomeUI", ‪VERSION_SHIP, 1, "int" );
280  ‪clientfield::register( "clientuimodel", "hudItems.remoteKillstreakActivated", ‪VERSION_SHIP, 1, "int" );
281  ‪clientfield::register( "world", "playTop0Gesture", ‪VERSION_TU1, 3, "int" );
282  ‪clientfield::register( "world", "playTop1Gesture", ‪VERSION_TU1, 3, "int" );
283  ‪clientfield::register( "world", "playTop2Gesture", ‪VERSION_TU1, 3, "int" );
284  ‪clientfield::register( "clientuimodel", "hudItems.captureCrateState", ‪VERSION_TU5, 2, "int" );
285  ‪clientfield::register( "clientuimodel", "hudItems.captureCrateTotalTime", ‪VERSION_TU5, 13, "int" );
286 
287  level.playersDrivingVehiclesBecomeInvulnerable = false;
288 
289  // for use in shared scripts that do not know which version of figure_out_attacker to use
290  level.figure_out_attacker = &‪globallogic_player::figure_out_attacker;
291  level.figure_out_friendly_fire = &‪globallogic_player::figure_out_friendly_fire;
292  level.get_base_weapon_param = &‪weapon_utils::getBaseWeaponParam; // used to figure out the weapon to as the parameter to GetBaseWeaponItemIndex()
293 }
294 
296 {
297  if ( GetDvarString( "ui_guncycle" ) == "" )
298  SetDvar( "ui_guncycle", 0 );
299 
300  //makeDvarServerInfo( "ui_guncycle" );
301 
302  if ( GetDvarString( "ui_weapon_tiers" ) == "" )
303  SetDvar( "ui_weapon_tiers", 0 );
304  //makeDvarServerInfo( "ui_weapon_tiers" );
305 
306  SetDvar( "ui_text_endreason", "");
307  //makeDvarServerInfo( "ui_text_endreason", "" );
308 
309  setMatchFlag( "bomb_timer", 0 );
310 
311  if ( GetDvarString( "scr_vehicle_damage_scalar" ) == "" )
312  SetDvar( "scr_vehicle_damage_scalar", "1" );
313 
314  level.vehicleDamageScalar = GetDvarfloat( "scr_vehicle_damage_scalar");
315 
316  level.fire_audio_repeat_duration = GetDvarint( "fire_audio_repeat_duration" );
317  level.fire_audio_random_max_duration = GetDvarint( "fire_audio_random_max_duration" );
318 
319  teamName = getcustomteamname( level.teamIndex[ "allies" ] );
320  if( isdefined( teamName ) )
321  SetDvar( "g_customTeamName_Allies", teamName );
322  else
323  SetDvar( "g_customTeamName_Allies", "" );
324 
325  teamName = getcustomteamname( level.teamIndex[ "axis" ] );
326  if( isdefined( teamName ) )
327  SetDvar( "g_customTeamName_Axis", teamName );
328  else
329  SetDvar( "g_customTeamName_Axis", "" );
330 
331 }
332 
333 function ‪blank( arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10 )
334 {
335 }
336 
338 {
339  level.spawnPlayer = &‪globallogic_spawn::spawnPlayer;
340  level.spawnPlayerPrediction = &‪globallogic_spawn::spawnPlayerPrediction;
341  level.spawnClient = &‪globallogic_spawn::spawnClient;
342  level.spawnSpectator = &‪globallogic_spawn::spawnSpectator;
343  level.spawnIntermission = &‪globallogic_spawn::spawnIntermission;
344  level.scoreOnGivePlayerScore = &‪globallogic_score::givePlayerScore;
345  level.onPlayerScore = &‪globallogic_score::default_onPlayerScore;
346  level.onTeamScore = &‪globallogic_score::default_onTeamScore;
347 
348  level.waveSpawnTimer =&‪waveSpawnTimer;
349  level.spawnMessage = &‪globallogic_spawn::default_spawnMessage;
350 
351  level.onSpawnPlayer =&‪blank;
352  level.onSpawnPlayer = &‪spawning::onSpawnPlayer;
353  level.onSpawnSpectator = &‪globallogic_defaults::default_onSpawnSpectator;
354  level.onSpawnIntermission = &‪globallogic_defaults::default_onSpawnIntermission;
355  level.onRespawnDelay =&‪blank;
356 
359  level.onScoreLimit = &‪globallogic_defaults::default_onScoreLimit;
360  level.onRoundScoreLimit = &‪globallogic_defaults::default_onRoundScoreLimit;
361  level.onAliveCountChange = &‪globallogic_defaults::default_onAliveCountChange;
362  level.onDeadEvent = undefined;
363  level.onOneLeftEvent = &‪globallogic_defaults::default_onOneLeftEvent;
364  level.giveTeamScore = &‪globallogic_score::giveTeamScore;
365  level.onLastTeamAliveEvent = &‪globallogic_defaults::default_onLastTeamAliveEvent;
366 
367  level.getTimePassed = &‪globallogic_utils::getTimePassed;
368  level.getTimeLimit = &‪globallogic_defaults::default_getTimeLimit;
369  level.getTeamKillPenalty = &‪globallogic_defaults::default_getTeamKillPenalty;
370  level.getTeamKillScore = &‪globallogic_defaults::default_getTeamKillScore;
371 
372  level.isKillBoosting = &‪globallogic_score::default_isKillBoosting;
373 
374  level._setTeamScore = &‪globallogic_score::_setTeamScore;
375  level._setPlayerScore = &‪globallogic_score::_setPlayerScore;
376 
377  level._getTeamScore = &‪globallogic_score::_getTeamScore;
378  level._getPlayerScore = &‪globallogic_score::_getPlayerScore;
379 
380  level.resetPlayerScorestreaks = &‪globallogic_score::resetPlayerScoreChainAndMomentum;
381 
382  level.onPrecacheGametype =&‪blank;
383  level.onStartGameType =&‪blank;
384  level.onPlayerConnect =&‪blank;
385  level.onPlayerDisconnect =&‪blank;
386  level.onPlayerDamage =&‪blank;
387  level.onPlayerKilled =&‪blank;
388  level.onPlayerKilledExtraUnthreadedCBs = [];
389 
390  level.onTeamOutcomeNotify = &‪hud_message::teamOutcomeNotify;
391  level.onOutcomeNotify = &‪hud_message::outcomeNotify;
392  level.setMatchScoreHUDElemForTeam = &‪hud_message::setMatchScoreHUDElemForTeam;
393  level.onEndGame =&‪blank;
394  level.onRoundEndGame = &‪globallogic_defaults::default_onRoundEndGame;
395  level.determineWinner = &‪globallogic_defaults::default_determineWinner;
396  level.onMedalAwarded =&‪blank;
397  level.dogManagerOnGetDogs = &‪dogs::dog_manager_get_dogs;
398 
400 
402 }
403 
405 {
406 
407  hardcoreMode = GetGametypeSetting( "hardcoreMode" );
408  if( !isdefined( hardcoreMode ) )
409  {
410  hardcoreMode = false;
411  }
412 
413  arenaMode = IsArenaMode();
414 
416 
417  postfix = ""; // normal
418 
419  if( hardcoreMode ) // hardcore
420  {
421  postfix = "_HC";
422  }
423  else if( arenaMode ) // arena
424  {
425  postfix = "_ARENA";
426  }
427 
428  friendLeaderboardA = "LB_MP_FRIEND_A" + postfix;
429  friendLeaderboardB = " LB_MP_FRIEND_B" + postfix;
430 
431  precacheLeaderboards( friendLeaderboardA + friendLeaderboardB );
432 }
433 
434 //Note not all game modes have anticheat so these may not always be found
436 {
437 
438  hardcoreMode = GetGametypeSetting( "hardcoreMode" );
439  if( !isdefined( hardcoreMode ) )
440  {
441  hardcoreMode = false;
442  }
443 
444  arenaMode = IsArenaMode();
445 
447 
448  postfix = ""; // normal
449 
450  if( hardcoreMode ) // hardcore
451  {
452  postfix = "_HC";
453  }
454  else if( arenaMode ) // arena
455  {
456  postfix = "_ARENA";
457  }
458 
459  anticheatLeaderboard = "LB_MP_ANTICHEAT_" + level.gametype + postfix;
460 
461  if( level.gametype != "fr" )
462  {
463  anticheatLeaderboard = anticheatLeaderboard + " LB_MP_ANTICHEAT_GLOBAL";
464  }
465 
466  precacheLeaderboards( anticheatLeaderboard );
467 }
468 
470 {
471  mapname = GetDvarString( "mapname" );
472 
473  hardcoreMode = GetGametypeSetting( "hardcoreMode" );
474  if( !isdefined( hardcoreMode ) )
475  {
476  hardcoreMode = false;
477  }
478 
479  arenaMode = IsArenaMode();
480  freerunMode = ( level.gametype == "fr" );
481 
483 
484  postfix = ""; // normal
485 
486  if( freerunMode ) // freerun
487  {
488  // strip the MP_ from the map name
489  frLeaderboard = " LB_MP_GM_FR_" + getsubstr( mapname, 3, mapname.size );
490 
491  precacheLeaderboards( frLeaderboard );
492  return;
493  }
494  else if( hardcoreMode ) // hardcore
495  {
496  postfix = "_HC";
497  }
498  else if( arenaMode ) // arena
499  {
500  postfix = "_ARENA";
501  }
502 
503  careerLeaderboard = " LB_MP_GB_SCORE" + postfix;
504  prestigeLB = " LB_MP_GB_XPPRESTIGE";
505  gamemodeLeaderboard = "LB_MP_GM_" + level.gametype + postfix;
506 
507  arenaLeaderboard = "";
508  if( GameModeIsMode( ‪GAMEMODE_LEAGUE_MATCH ) )
509  {
510  arenaSlot = ArenaGetSlot();
511  arenaLeaderboard = " LB_MP_ARENA_MASTERS_0" + arenaSlot;
512  }
513 
514  precacheLeaderboards( gamemodeLeaderboard + careerLeaderboard + prestigeLB + arenaLeaderboard );
515 }
516 
518 {
519  customLeaderboards = "LB_MP_CG_" + level.gametype;
520 
521  precacheLeaderboards( "LB_MP_CG_GENERAL " + customLeaderboards );
522 
523  return;
524 }
525 
527 {
529  {
530  return;
531  }
532 
533  if( level.rankedMatch || level.gametype == "fr" )
534  {
538  }
539  else
540  {
542  }
543 }
544 
545 function ‪setvisiblescoreboardcolumns( col1, col2, col3, col4, col5 )
546 {
547  if ( !level.rankedMatch )
548  {
549  setscoreboardcolumns( col1, col2, col3, col4, col5, "sbtimeplayed", "shotshit", "shotsmissed", "victory" );
550  }
551  else
552  {
553  setscoreboardcolumns( col1, col2, col3, col4, col5 );
554  }
555 }
556 
557 function ‪compareTeamByGameStat( gameStat, teamA, teamB, previous_winner_score )
558 {
559  winner = undefined;
560 
561  if ( teamA == "tie" )
562  {
563  winner = "tie";
564 
565  if ( previous_winner_score < game[gameStat][teamB] )
566  winner = teamB;
567  }
568  else if ( game[gameStat][teamA] == game[gameStat][teamB] )
569  winner = "tie";
570  else if ( game[gameStat][teamB] > game[gameStat][teamA] )
571  winner = teamB;
572  else
573  winner = teamA;
574 
575  return winner;
576 }
577 
579 {
580  teamKeys = GetArrayKeys(level.teams);
581  winner = teamKeys[0];
582  previous_winner_score = game[gameStat][winner];
583 
584  for ( teamIndex = 1; teamIndex < teamKeys.size; teamIndex++ )
585  {
586  winner = ‪compareTeamByGameStat( gameStat, winner, teamKeys[teamIndex], previous_winner_score);
587 
588  if ( winner != "tie" )
589  {
590  previous_winner_score = game[gameStat][winner];
591  }
592  }
593 
594  return winner;
595 }
596 
597 function ‪compareTeamByTeamScore( teamA, teamB, previous_winner_score )
598 {
599  winner = undefined;
600  teamBScore = [[level._getTeamScore]]( teamB );
601 
602  if ( teamA == "tie" )
603  {
604  winner = "tie";
605 
606  if ( previous_winner_score < teamBScore )
607  winner = teamB;
608 
609  return winner;
610  }
611 
612  teamAScore = [[level._getTeamScore]]( teamA );
613 
614  if ( teamBScore == teamAScore )
615  winner = "tie";
616  else if ( teamBScore > teamAScore )
617  winner = teamB;
618  else
619  winner = teamA;
620 
621  return winner;
622 }
623 
625 {
626  teamKeys = GetArrayKeys(level.teams);
627  winner = teamKeys[0];
628  previous_winner_score = [[level._getTeamScore]]( winner );
629 
630  for ( teamIndex = 1; teamIndex < teamKeys.size; teamIndex++ )
631  {
632  winner = ‪compareTeamByTeamScore( winner, teamKeys[teamIndex], previous_winner_score);
633 
634  if ( winner != "tie" )
635  {
636  previous_winner_score = [[level._getTeamScore]]( winner );
637  }
638  }
639 
640  return winner;
641 }
642 
643 function ‪forceEnd(hostsucks)
644 {
645  if (!isdefined(hostsucks))
646  hostsucks = false;
647 
648  if ( level.hostForcedEnd || level.forcedEnd )
649  return;
650 
651  winner = undefined;
652 
653  if ( level.teamBased )
654  {
655  winner = ‪determineTeamWinnerByGameStat("teamScores");
656  ‪globallogic_utils::logTeamWinString( "host ended game", winner );
657  }
658  else
659  {
661  /#
662  if ( isdefined( winner ) )
663  print( "host ended game, win: " + winner.name );
664  else
665  print( "host ended game, tie" );
666  #/
667  }
668 
669  level.forcedEnd = true;
670  level.hostForcedEnd = true;
671 
672  if (hostsucks)
673  {
674  endString = &"MP_HOST_SUCKS";
675  }
676  else
677  {
678  if ( level.splitscreen )
679  endString = &"MP_ENDED_GAME";
680  else
681  endString = &"MP_HOST_ENDED_GAME";
682  }
683 
684  setMatchFlag( "disableIngameMenu", 1 );
685  //makeDvarServerInfo( "ui_text_endreason", endString );
686  SetDvar( "ui_text_endreason", endString );
687  thread ‪endGame( winner, endString );
688 }
689 
690 function ‪killserverPc()
691 {
692  if ( level.hostForcedEnd || level.forcedEnd )
693  return;
694 
695  winner = undefined;
696 
697  if ( level.teamBased )
698  {
699  winner = ‪determineTeamWinnerByGameStat("teamScores");
700  ‪globallogic_utils::logTeamWinString( "host ended game", winner );
701  }
702  else
703  {
705  /#
706  if ( isdefined( winner ) )
707  print( "host ended game, win: " + winner.name );
708  else
709  print( "host ended game, tie" );
710  #/
711  }
712 
713  level.forcedEnd = true;
714  level.hostForcedEnd = true;
715 
716  level.killserver = true;
717 
718  endString = &"MP_HOST_ENDED_GAME";
719 
720 
721 /#
722  PrintLn("kill server; ending game\n");
723 #/
724 
725  thread ‪endGame( winner, endString );
726 }
727 
729 {
730  valid_count = 0;
731 
732  foreach ( team in level.teams )
733  {
734  if ( level.playerCount[team] != 0 )
735  {
736  valid_count++;
737  }
738  }
739 
740  if ( valid_count < 2 )
741  {
742  return false;
743  }
744 
745  return true;
746 }
747 
748 function ‪checkIfTeamForfeits( team )
749 {
750  if ( !game["everExisted"][team] )
751  return false;
752 
753  if ( level.playerCount[team] < 1 && ‪util::totalPlayerCount() > 0 )
754  {
755  return true;
756  }
757 
758  return false;
759 }
760 
762 {
763  forfeit_count = 0;
764  valid_team = undefined;
765 
766  foreach( team in level.teams )
767  {
768  if ( ‪checkIfTeamForfeits( team ) )
769  {
770  forfeit_count++;
771 
772  if ( !level.multiTeam )
773  {
774  thread [[level.onForfeit]]( team );
775  return true;
776  }
777  }
778  else
779  {
780  valid_team = team;
781  }
782  }
783 
784  if ( level.multiTeam && ( forfeit_count == ( level.teams.size - 1 ) ) )
785  {
786  thread [[level.onForfeit]]( valid_team );
787  return true;
788  }
789 
790  return false;
791 }
792 
794 {
795  foreach( team in level.teams )
796  {
797  if ( level.spawnQueueModified[team] )
798  {
799  [[level.onAliveCountChange]]( team );
800  }
801  }
802 }
803 
804 function ‪isTeamAllDead( team )
805 {
806  return (level.everExisted[team] && !level.aliveCount[team] && !level.playerLives[team] );
807 }
808 
810 {
811  foreach( team in level.teams )
812  {
813  // if team was alive and now they are not
814  if ( !‪isTeamAllDead( team ) )
815  {
816  return false;
817  }
818  }
819 
820  return true;
821 }
822 
824 {
825  count = 0;
826  everExistedCount = 0;
827  aliveTeam = undefined;
828  foreach( team in level.teams )
829  {
830  // if team was alive and now they are not
831  if ( level.everExisted[team] )
832  {
833  if ( !‪isTeamAllDead( team ) )
834  {
835  aliveTeam = team;
836  count++;
837  }
838  everExistedCount++;
839  }
840  }
841 
842  if ( ( everExistedCount > 1 ) && ( count == 1 ) )
843  {
844  return aliveTeam;
845  }
846 
847  return undefined;
848 }
849 
851 {
852  if ( level.teamBased )
853  {
854  // if all teams were alive and now they are all dead in the same instance
855  if ( ‪areAllTeamsDead( ) )
856  {
857  [[level.onDeadEvent]]( "all" );
858  return true;
859  }
860 
861  if ( !isdefined( level.onDeadEvent ) )
862  {
863  lastTeamAlive = ‪getLastTeamAlive();
864  if ( isdefined( lastTeamAlive ) )
865  {
866  [[level.onLastTeamAliveEvent]]( lastTeamAlive );
867  return true;
868  }
869  }
870  else
871  {
872  foreach( team in level.teams )
873  {
874  // if team was alive and now they are not
875  if ( ‪isTeamAllDead( team ) )
876  {
877  [[level.onDeadEvent]]( team );
878  return true;
879  }
880  }
881  }
882  }
883  else
884  {
885  // everyone is dead
886  if ( (‪totalAliveCount() == 0) && (‪totalPlayerLives() == 0) && level.maxPlayerCount > 1 )
887  {
888  [[level.onDeadEvent]]( "all" );
889  return true;;
890  }
891  }
892 
893  return false;
894 }
895 
897 {
898  return (level.lastAliveCount[team] > 1 && level.aliveCount[team] == 1 && level.playerLives[team] == 1 );
899 }
900 
901 
903 {
904  if ( level.teamBased )
905  {
906  foreach( team in level.teams )
907  {
908  // one "team" left
909  if ( ‪isOnlyOneLeftAliveOnTeam( team ) )
910  {
911  [[level.onOneLeftEvent]]( team );
912  return true;;
913  }
914  }
915  }
916  else
917  {
918  // last man standing
919  if ( (‪totalAliveCount() == 1) && (‪totalPlayerLives() == 1) && level.maxPlayerCount > 1 )
920  {
921  [[level.onOneLeftEvent]]( "all" );
922  return true;;
923  }
924  }
925 
926  return false;
927 }
928 
930 {
931  if ( ( level.rankedMatch || level.wagerMatch || level.leagueMatch ) && !level.inGracePeriod )
932  {
933  if ( level.teamBased )
934  {
935  if (!level.gameForfeited )
936  {
937  if( game["state"] == "playing" && ‪checkForForfeit() )
938  {
939  return;
940  }
941  }
942  else // level.gameForfeited==true
943  {
944  if ( ‪atLeastTwoTeams() )
945  {
946  level.gameForfeited = false;
947  level notify( "abort forfeit" );
948  }
949  }
950  }
951  else
952  {
953  if (!level.gameForfeited)
954  {
955  if ( ‪util::totalPlayerCount() == 1 && level.maxPlayerCount > 1 )
956  {
957  thread [[level.onForfeit]]();
958  return;
959  }
960  }
961  else // level.gameForfeited==true
962  {
963  if ( ‪util::totalPlayerCount() > 1 )
964  {
965  level.gameForfeited = false;
966  level notify( "abort forfeit" );
967  }
968  }
969  }
970  }
971 
972  if ( !level.playerQueuedRespawn && !level.numLives && !level.inOverTime )
973  return;
974 
975  if ( level.inGracePeriod )
976  return;
977 
978  if ( level.playerQueuedRespawn )
979  {
981  }
982 
983  if ( ‪doDeadEventUpdates() )
984  return;
985 
986  if ( ‪doOneLeftEventUpdates() )
987  return;
988 }
989 
991 {
992  level endon( ‪MPINTRO_VISIONSET_RAMP_NOTIFY );
993 
994  while ( true )
995  {
996  for ( player_index = 0; player_index < level.players.size; player_index++ )
997  {
998  self ‪visionset_mgr::set_state_active( level.players[player_index], 1 );
999  }
1000 
1002  }
1003 }
1004 
1006 {
1008 }
1009 
1011 {
1012  level notify( ‪MPINTRO_VISIONSET_RAMP_NOTIFY );
1013 }
1014 
1016 {
1018  level thread ‪sndSetMatchSnapshot( 1 );
1020 
1021  countTime = int( level.prematchPeriod );
1022 
1023  if ( countTime >= 2 )
1024  {
1025  while ( countTime > 0 && !level.gameEnded )
1026  {
1027  LUINotifyEvent( &"create_prematch_timer", 1, GetTime() + ( countTime * 1000 ) );
1028 
1029  if ( countTime == 2 )
1030  {
1032  }
1033 
1034  if( countTime == 3 )
1035  {
1036  level thread ‪sndSetMatchSnapshot( 0 );
1037  foreach ( player in level.players )
1038  {
1039  if ( player.hasSpawned || player.pers["team"] == "spectator" )
1040  {
1041  player ‪globallogic_audio::set_music_on_player( "spawnPreRise" );
1042  }
1043  }
1044  }
1045 
1046  countTime--;
1047 
1048  foreach ( player in level.players )
1049  {
1050  player PlayLocalSound( "uin_start_count_down" );
1051  }
1052 
1053  wait ( 1.0 );
1054  }
1055 
1056  LUINotifyEvent( &"prematch_timer_ended", 0 );
1057  }
1058  else
1059  {
1061  }
1062 }
1063 
1065 {
1066  level waittill( "game_ended" );
1067  level ‪clientfield::set("gameplay_started", 0);
1068 }
1069 
1071 {
1072  visionSetNaked( GetDvarString( "mapname" ), 0 );
1073 }
1074 
1075 function ‪sndSetMatchSnapshot( num )
1076 {
1077  wait(.05);
1078  level ‪clientfield::set( "sndMatchSnapshot", num );
1079 }
1080 
1081 function ‪notifyTeamWaveSpawn( team, time )
1082 {
1083  if ( time - level.lastWave[team] > (level.waveDelay[team] * 1000) )
1084  {
1085  level notify ( "wave_respawn_" + team );
1086  level.lastWave[team] = time;
1087  level.wavePlayerSpawnIndex[team] = 0;
1088  }
1089 }
1090 
1092 {
1093  level endon( "game_ended" );
1094 
1095  while ( game["state"] == "playing" )
1096  {
1097  time = getTime();
1098 
1099  foreach( team in level.teams )
1100  {
1101  ‪notifyTeamWaveSpawn( team, time );
1102  }
1104  }
1105 }
1106 
1107 
1109 {
1110  hostPlayer = ‪util::getHostPlayer();
1111 
1112  // host never spawned
1113  if ( isdefined( hostPlayer ) && !hostPlayer.hasSpawned && !isdefined( hostPlayer.selectedClass ) )
1114  return true;
1115 
1116  return false;
1117 }
1118 
1119 function ‪IncrementMatchCompletionStat( gameMode, playedOrHosted, stat )
1120 {
1121  self AddDStat( "gameHistory", gameMode, "modeHistory", playedOrHosted, stat, 1 );
1122 }
1123 
1124 function ‪SetMatchCompletionStat( gameMode, playedOrHosted, stat )
1125 {
1126  self SetDStat( "gameHistory", gameMode, "modeHistory", playedOrHosted, stat, 1 );
1127 }
1128 
1130 {
1131  playerTeam = self.pers["team"];
1132 
1133  score = getTeamScore( playerTeam );
1134 
1135  otherTeamScore = 0;
1136 
1137  foreach ( team in level.teams )
1138  {
1139  if ( team == playerTeam )
1140  continue;
1141 
1142  otherTeamScore += getTeamScore( team );
1143  }
1144 
1145  if ( level.teams.size > 1 )
1146  {
1147  otherTeamScore = otherTeamScore / ( level.teams.size - 1 );
1148  }
1149 
1150  if ( otherTeamScore != 0 )
1151  return ( float( score ) / float( otherTeamScore ) );
1152 
1153  // should we just return the flat score here or some other indication of win?
1154  return score;
1155 }
1156 
1158 {
1159  highestScore = -999999999;
1160  for ( index = 0; index < level.players.size; index++ )
1161  {
1162  player = level.players[index];
1163 
1164  if ( player.score > highestScore )
1165  highestScore = player.score;
1166  }
1167 
1168  return highestScore;
1169 }
1170 
1171 function ‪getNextHighestScore( score )
1172 {
1173  highestScore = -999999999;
1174  for ( index = 0; index < level.players.size; index++ )
1175  {
1176  player = level.players[index];
1177 
1178  if ( player.score >= score )
1179  continue;
1180 
1181  if ( player.score > highestScore )
1182  highestScore = player.score;
1183  }
1184 
1185  return highestScore;
1186 }
1187 
1189 {
1190  // Record information for determining play styles
1191  avgKillDistance = 0;
1192  percentTimeMoving = 0;
1193  avgSpeedOfPlayerWhenMoving = 0;
1194  totalKillDistances = float( self.pers["kill_distances"] );
1195  numKillDistanceEntries = float( self.pers["num_kill_distance_entries"] );
1196  timePlayedMoving = float( self.pers["time_played_moving"] );
1197  timePlayedAlive = float( self.pers["time_played_alive"] );
1198  totalSpeedsWhenMoving = float( self.pers["total_speeds_when_moving"] );
1199  numSpeedsWhenMovingEntries = float( self.pers["num_speeds_when_moving_entries"] );
1200  totalDistanceTravelled = float( self.pers["total_distance_travelled"] );
1201  movementUpdateCount = float(self.pers["movement_Update_Count"]);
1202  if ( numKillDistanceEntries > 0 )
1203  avgKillDistance = totalKillDistances / numKillDistanceEntries;
1204 
1205  movementUpdateDenom = int(movementUpdateCount/5);
1206  if ( movementUpdateDenom > 0 )
1207  percentTimeMoving = ( numSpeedsWhenMovingEntries / movementUpdateDenom ) * 100.0;
1208 
1209  if ( numSpeedsWhenMovingEntries > 0 )
1210  avgSpeedOfPlayerWhenMoving = totalSpeedsWhenMoving / numSpeedsWhenMovingEntries;
1211 
1212  recordPlayerStats( self, "totalKillDistances", totalKillDistances );
1213  recordPlayerStats( self, "numKillDistanceEntries", numKillDistanceEntries );
1214  recordPlayerStats( self, "timePlayedMoving", timePlayedMoving );
1215  recordPlayerStats( self, "timePlayedAlive", timePlayedAlive );
1216  recordPlayerStats( self, "totalSpeedsWhenMoving", totalSpeedsWhenMoving );
1217  recordPlayerStats( self, "numSpeedsWhenMovingEntries", numSpeedsWhenMovingEntries );
1218  recordPlayerStats( self, "averageKillDistance", avgKillDistance );
1219  recordPlayerStats( self, "percentageOfTimeMoving", percentTimeMoving );
1220  recordPlayerStats( self, "averageSpeedDuringMatch", avgSpeedOfPlayerWhenMoving );
1221  recordPlayerStats( self, "totalDistanceTravelled", totalDistanceTravelled );
1222 }
1223 
1225 {
1226  for ( index = 0; index < level.players.size; index++ )
1227  {
1228  player = level.players[index];
1229 
1230  if ( player ‪util::is_bot() )
1231  {
1232  continue;
1233  }
1234 
1235  if ( player.name == ‪name )
1236  {
1237  return player;
1238  }
1239  }
1240 }
1241 
1243 {
1244  //Send After Action Report information to the client
1245  for ( index = 0; index < level.players.size; index++ )
1246  {
1247  player = level.players[index];
1248 
1249  if ( player ‪util::is_bot() )
1250  {
1251  continue;
1252  }
1253 
1254  //Find the Nemesis for each player
1255  nemesis = player.pers["nemesis_name"];
1256 
1257  if( !isdefined( player.pers["killed_players"][nemesis] ) )
1258  player.pers["killed_players"][nemesis] = 0;
1259  if( !isdefined( player.pers["killed_by"][nemesis] ) )
1260  player.pers["killed_by"][nemesis] = 0;
1261 
1262  //Get the kill to death spread of the player
1263  spread = player.kills - player.deaths;
1264 
1265  if( player.pers["cur_kill_streak"] > player.pers["best_kill_streak"] )
1266  player.pers["best_kill_streak"] = player.pers["cur_kill_streak"];
1267 
1268  if ( ( level.rankedMatch || level.leagueMatch ) )
1269  player ‪persistence::set_after_action_report_stat( "privateMatch", 0 );
1270  else
1271  player ‪persistence::set_after_action_report_stat( "privateMatch", 1 );
1272 
1273  player setNemesisXuid( player.pers["nemesis_xuid"] );
1274  player ‪persistence::set_after_action_report_stat( "nemesisName", nemesis );
1275  player ‪persistence::set_after_action_report_stat( "nemesisRank", player.pers["nemesis_rank"] );
1276  player ‪persistence::set_after_action_report_stat( "nemesisRankIcon", player.pers["nemesis_rankIcon"] );
1277  player ‪persistence::set_after_action_report_stat( "nemesisKills", player.pers["killed_players"][nemesis] );
1278  player ‪persistence::set_after_action_report_stat( "nemesisKilledBy", player.pers["killed_by"][nemesis] );
1279  nemesisPlayerEnt = ‪getPlayerByName( nemesis );
1280 
1281  if ( isDefined( nemesisPlayerEnt ) )
1282  {
1283  player ‪persistence::set_after_action_report_stat( "nemesisHeroIndex", nemesisPlayerEnt GetCharacterBodyType() );
1284  }
1285 
1286  player ‪persistence::set_after_action_report_stat( "bestKillstreak", player.pers["best_kill_streak"] );
1287  player ‪persistence::set_after_action_report_stat( "kills", player.kills );
1288  player ‪persistence::set_after_action_report_stat( "deaths", player.deaths );
1289  player ‪persistence::set_after_action_report_stat( "headshots", player.headshots );
1290  player ‪persistence::set_after_action_report_stat( "score", player.score );
1291 
1292  player ‪persistence::set_after_action_report_stat( "xpEarned", int( player.pers["summary"]["xp"] ) );
1293  player ‪persistence::set_after_action_report_stat( "cpEarned", int( player.pers["summary"]["codpoints"] ) );
1294  player ‪persistence::set_after_action_report_stat( "miscBonus", int( player.pers["summary"]["challenge"] + player.pers["summary"]["misc"] ) );
1295  player ‪persistence::set_after_action_report_stat( "matchBonus", int( player.pers["summary"]["match"] ) );
1296  player ‪persistence::set_after_action_report_stat( "demoFileID", getDemoFileID() );
1297  player ‪persistence::set_after_action_report_stat( "leagueTeamID", player getLeagueTeamID() );
1298 
1300 
1301  alliesScore = globallogic_score::_getteamscore( "allies" );
1302  if( isdefined( alliesScore ) )
1303  {
1304  player ‪persistence::set_after_action_report_stat( "alliesScore", alliesScore );
1305  }
1306 
1307  axisScore = globallogic_score::_getteamscore( "axis" );
1308  if( isdefined( axisScore ) )
1309  {
1310  player ‪persistence::set_after_action_report_stat( "axisScore", axisScore );
1311  }
1312 
1313  player ‪persistence::set_after_action_report_stat( "gameTypeRef", level.gametype );
1314  player ‪persistence::set_after_action_report_stat( "mapname", GetDvarString( "ui_mapname" ) );
1315  }
1316 }
1317 
1319 {
1320  for ( index = 0; index < level.players.size; index++ )
1321  {
1322  player = level.players[index];
1323 
1325 
1326  if ( player ‪util::is_bot() )
1327  {
1328  continue;
1329  }
1330 
1332 
1333  //Find the Nemesis for each player
1334  nemesis = player.pers["nemesis_name"];
1335 
1336  if( !isdefined( player.pers["killed_players"][nemesis] ) )
1337  player.pers["killed_players"][nemesis] = 0;
1338  if( !isdefined( player.pers["killed_by"][nemesis] ) )
1339  player.pers["killed_by"][nemesis] = 0;
1340 
1341  //Get the kill to death spread of the player
1342  spread = player.kills - player.deaths;
1343 
1344  if( player.pers["cur_kill_streak"] > player.pers["best_kill_streak"] )
1345  player.pers["best_kill_streak"] = player.pers["cur_kill_streak"];
1346 
1347  if ( level.onlineGame )
1348  {
1349  teamScoreRatio = player ‪getTeamScoreRatio();
1350  scoreboardPosition = ‪getPlacementForPlayer( player );
1351  if ( scoreboardPosition < 0 )
1352  scoreboardPosition = level.players.size;
1353 
1354  player GameHistoryFinishMatch( ‪MATCH_FINISHED, player.kills, player.deaths, player.score, scoreboardPosition, teamScoreRatio );
1355 
1356  placement = level.placement["all"];
1357  for ( otherPlayerIndex = 0; otherPlayerIndex < placement.size; otherPlayerIndex++ )
1358  {
1359  if ( level.placement["all"][otherPlayerIndex] == player )
1360  {
1361  recordPlayerStats( player, "position", otherPlayerIndex );
1362  }
1363  }
1364 
1365  if ( isdefined( player.pers["matchesPlayedStatsTracked"] ) )
1366  {
1367  gameMode = ‪util::GetCurrentGameMode();
1368  player ‪IncrementMatchCompletionStat( gameMode, "played", "completed" );
1369 
1370  if ( isdefined( player.pers["matchesHostedStatsTracked"] ) )
1371  {
1372  player ‪IncrementMatchCompletionStat( gameMode, "hosted", "completed" );
1373  player.pers["matchesHostedStatsTracked"] = undefined;
1374  }
1375 
1376  player.pers["matchesPlayedStatsTracked"] = undefined;
1377  }
1378 
1379  recordPlayerStats( player, "highestKillStreak", player.pers["best_kill_streak"] );
1380  recordPlayerStats( player, "numUavCalled", player ‪killstreaks::get_killstreak_usage("uav_used") );
1381  recordPlayerStats( player, "numDogsCalleD", player ‪killstreaks::get_killstreak_usage("dogs_used") );
1382  recordPlayerStats( player, "numDogsKills", player.pers["dog_kills"] );
1383 
1385 
1386  recordPlayerMatchEnd( player );
1387  RecordPlayerStats(player, "presentAtEnd", 1 );
1388  }
1389  }
1390 
1391  finalizeMatchRecord();
1392 }
1393 
1395 {
1396  teamScoreRatio = self ‪getTeamScoreRatio();
1397  scoreboardPosition = ‪getPlacementForPlayer( self );
1398  if ( scoreboardPosition < 0 )
1399  scoreboardPosition = level.players.size;
1400 /#
1401  assert( isdefined( self.kills ) );
1402  assert( isdefined( self.deaths ) );
1403  assert( isdefined( self.score ) );
1404  assert( isdefined( scoreboardPosition ) );
1405  assert( isdefined( teamScoreRatio ) );
1406 #/
1407  self GameHistoryFinishMatch( ‪MATCH_KICKED, self.kills, self.deaths, self.score, scoreboardPosition, teamScoreRatio );
1408 
1409  if ( isdefined( self.pers["matchesPlayedStatsTracked"] ) )
1410  {
1411  gameMode = ‪util::GetCurrentGameMode();
1412  self ‪IncrementMatchCompletionStat( gameMode, "played", "kicked" );
1413 
1414  self.pers["matchesPlayedStatsTracked"] = undefined;
1415  }
1416 
1417  UploadStats( self );
1418 
1419  // wait until the player recieves the new stats
1420  wait(1);
1421 }
1422 
1424 {
1425  teamScoreRatio = self ‪getTeamScoreRatio();
1426  scoreboardPosition = ‪getPlacementForPlayer( self );
1427  if ( scoreboardPosition < 0 )
1428  scoreboardPosition = level.players.size;
1429 
1430  self GameHistoryFinishMatch( ‪MATCH_QUIT, self.kills, self.deaths, self.score, scoreboardPosition, teamScoreRatio );
1431 
1432  if ( isdefined( self.pers["matchesPlayedStatsTracked"] ) )
1433  {
1434  gameMode = ‪util::GetCurrentGameMode();
1435  self ‪IncrementMatchCompletionStat( gameMode, "played", "quit" );
1436 
1437  if ( isdefined( self.pers["matchesHostedStatsTracked"] ) )
1438  {
1439  self ‪IncrementMatchCompletionStat( gameMode, "hosted", "quit" );
1440  self.pers["matchesHostedStatsTracked"] = undefined;
1441  }
1442 
1443  self.pers["matchesPlayedStatsTracked"] = undefined;
1444  }
1445 
1446  UploadStats( self );
1447 
1448  if ( !self IsHost() )
1449  {
1450  // wait until the player recieves the new stats
1451  wait(1);
1452  }
1453 }
1454 
1455 function ‪displayRoundEnd( winner, endReasonText )
1456 {
1457  if ( level.displayRoundEndText )
1458  {
1459  if ( level.teamBased )
1460  {
1461  if ( winner == "tie" )
1462  {
1463  ‪demo::gameResultBookmark( "round_result", level.teamIndex[ "neutral" ], level.teamIndex[ "neutral" ] );
1464  }
1465  else
1466  {
1467  ‪demo::gameResultBookmark( "round_result", level.teamIndex[ winner ], level.teamIndex[ "neutral" ] );
1468  }
1469  }
1470 
1471  setmatchflag( "cg_drawSpectatorMessages", 0 );
1472  players = level.players;
1473  for ( index = 0; index < players.size; index++ )
1474  {
1475  player = players[index];
1476 
1477  if( !‪util::wasLastRound() )
1478  {
1479  player notify( "round_ended" );
1480  }
1481  if ( !isdefined( player.pers["team"] ) )
1482  {
1483  player [[level.spawnIntermission]]( true );
1484  continue;
1485  }
1486 
1487  if ( level.teamBased )
1488  {
1489  player thread [[level.onTeamOutcomeNotify]]( winner, "roundend", endReasonText );
1490  player ‪globallogic_audio::set_music_on_player( "roundEnd" );
1491  }
1492  else
1493  {
1494  player thread [[level.onOutcomeNotify]]( winner, true, endReasonText );
1495  player ‪globallogic_audio::set_music_on_player( "roundEnd" );
1496  }
1497 
1498  player setClientUIVisibilityFlag( "hud_visible", 0 );
1499  player setClientUIVisibilityFlag( "g_compassShowEnemies", 0 );
1500  }
1501  }
1502 
1503  if ( ‪util::wasLastRound() )
1504  {
1505  ‪roundEndWait( level.roundEndDelay, false );
1506  }
1507  else
1508  {
1509  thread ‪globallogic_audio::announce_round_winner( winner, level.roundEndDelay / 4 );
1510  ‪roundEndWait( level.roundEndDelay, true );
1511  }
1512 }
1513 
1514 function ‪displayRoundSwitch( winner, endReasonText )
1515 {
1516  switchType = level.halftimeType;
1517  level thread ‪globallogic_audio::set_music_global( "roundSwitch" );
1518  if ( switchType == "halftime" )
1519  {
1520  if ( isdefined( level.nextRoundIsOvertime ) && level.nextRoundIsOvertime )
1521  {
1522  switchType = "overtime";
1523  }
1524  else
1525  {
1526  if ( level.roundLimit )
1527  {
1528  if ( (game["roundsplayed"] * 2) == level.roundLimit )
1529  switchType = "halftime";
1530  else
1531  switchType = "intermission";
1532  }
1533  else if ( level.scoreLimit )
1534  {
1535  if ( isdefined( level.roundswitch ) && level.roundSwitch == 1 )
1536  {
1537  switchtype = "intermission";
1538  }
1539  else if ( game["roundsplayed"] == (level.scoreLimit - 1) )
1540  {
1541  switchType = "halftime";
1542  }
1543  else
1544  {
1545  switchType = "intermission";
1546  }
1547  }
1548  else
1549  {
1550  switchType = "intermission";
1551  }
1552  }
1553 
1554  }
1555 
1556  leaderdialog = ‪globallogic_audio::get_round_switch_dialog( switchType );
1557 
1558  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
1559 
1560  players = level.players;
1561  for ( index = 0; index < players.size; index++ )
1562  {
1563  player = players[index];
1564 
1565  if ( !isdefined( player.pers["team"] ) )
1566  {
1567  player [[level.spawnIntermission]]( true );
1568  continue;
1569  }
1570 
1571  player ‪globallogic_audio::leader_dialog_on_player( leaderdialog );
1572 
1573  player thread [[level.onTeamOutcomeNotify]]( winner, switchType, level.halftimeSubCaption );
1574  player setClientUIVisibilityFlag( "hud_visible", 0 );
1575  }
1576 
1577  ‪roundEndWait( level.halftimeRoundEndDelay, false );
1578 }
1579 
1580 function ‪displayGameEnd( winner, endReasonText )
1581 {
1582  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
1583  setmatchflag( "cg_drawSpectatorMessages", 0 );
1584 
1585  level thread ‪sndSetMatchSnapshot( 2 );
1586 
1587  ‪util::setClientSysState("levelNotify", "streamFKsl" );
1588 
1589  if ( level.teambased )
1590  {
1591  if ( winner == "tie" )
1592  {
1593  ‪demo::gameResultBookmark( "game_result", level.teamIndex[ "neutral" ], level.teamIndex[ "neutral" ] );
1594  }
1595  else
1596  {
1597  ‪demo::gameResultBookmark( "game_result", level.teamIndex[ winner ], level.teamIndex[ "neutral" ] );
1598  }
1599  }
1600  // catching gametype, since DM forceEnd sends winner as player entity, instead of string
1601  players = level.players;
1602  for ( index = 0; index < players.size; index++ )
1603  {
1604  player = players[index];
1605 
1606  if ( !isdefined( player.pers["team"] ) )
1607  {
1608  player [[level.spawnIntermission]]( true );
1609  continue;
1610  }
1611 
1612  if ( level.teamBased )
1613  {
1614  player thread [[level.onTeamOutcomeNotify]]( winner, "gameend", endReasonText );
1615  }
1616  else
1617  {
1618  if ( !‪IS_TRUE( level.freerun ) )
1619  {
1620  player thread [[level.onOutcomeNotify]]( winner, false, endReasonText );
1621  }
1622 
1623  if( ‪IS_TRUE( level.freerun ) )
1624  {
1625  player ‪globallogic_audio::set_music_on_player( "mp_freerun_gameover" );
1626  }
1627  else if ( isdefined( winner ) && player == winner )
1628  {
1629  player ‪globallogic_audio::set_music_on_player( "matchWin" );
1630  }
1631  else if ( !level.splitScreen )
1632  {
1633  player ‪globallogic_audio::set_music_on_player( "matchLose" );
1634  }
1635  }
1636 
1637  player setClientUIVisibilityFlag( "hud_visible", 0 );
1638  player setClientUIVisibilityFlag( "g_compassShowEnemies", 0 );
1639  }
1640 
1642 
1643  if ( level.teamBased )
1644  {
1645  players = level.players;
1646  for ( index = 0; index < players.size; index++ )
1647  {
1648  player = players[index];
1649  team = player.pers["team"];
1650 
1651  if ( level.splitscreen )
1652  {
1653  if( ‪IS_TRUE( level.freerun ) )
1654  {
1655  player ‪globallogic_audio::set_music_on_player( "mp_freerun_gameover" );
1656  }
1657  else if ( winner == "tie" )
1658  {
1659  player ‪globallogic_audio::set_music_on_player( "matchDraw" );
1660  }
1661  else if ( winner == team )
1662  {
1663  player ‪globallogic_audio::set_music_on_player( "matchWin" );
1664  }
1665  else
1666  {
1667  player ‪globallogic_audio::set_music_on_player( "matchLose" );
1668  }
1669  }
1670  else
1671  {
1672  if( ‪IS_TRUE( level.freerun ) )
1673  {
1674  player ‪globallogic_audio::set_music_on_player( "mp_freerun_gameover" );
1675  }
1676  else if ( winner == "tie" )
1677  {
1678  player ‪globallogic_audio::set_music_on_player( "matchDraw" );
1679  }
1680  else if ( winner == team )
1681  {
1682  player ‪globallogic_audio::set_music_on_player( "matchWin" );
1683  }
1684  else
1685  {
1686  player ‪globallogic_audio::set_music_on_player( "matchLose" );
1687  }
1688  }
1689  }
1690  }
1691 
1692  ‪roundEndWait( level.postRoundTime, true );
1693 }
1694 
1696 {
1697  players = level.players;
1698  for ( index = 0; index < players.size; index++ )
1699  {
1701  }
1702 }
1703 
1705 {
1706  if ( isdefined( level.endReasonText ) )
1707  {
1708  return level.endReasonText;
1709  }
1710 
1712  return game["strings"]["round_limit_reached"];
1713  else if ( ‪util::hitScoreLimit() )
1714  return game["strings"]["score_limit_reached"];
1715  else if ( ‪util::hitRoundScoreLimit() )
1716  return game["strings"]["round_score_limit_reached"];
1717 
1718  if ( level.forcedEnd )
1719  {
1720  if ( level.hostForcedEnd )
1721  return &"MP_HOST_ENDED_GAME";
1722  else
1723  return &"MP_ENDED_GAME";
1724  }
1725  return game["strings"]["time_limit_reached"];
1726 }
1727 
1729 {
1730  players = level.players;
1731  for ( index = 0; index < players.size; index++ )
1732  {
1733  player = players[index];
1734  player notify ( "reset_outcome" );
1735  }
1736 }
1737 
1739 {
1740  players = level.players;
1741  for ( index = 0; index < players.size; index++ )
1742  {
1743  player = players[index];
1744  player ‪clientfield::set_player_uimodel( "hudItems.hideOutcomeUI", 1 );
1745  }
1746 }
1747 
1748 function ‪startNextRound( winner, endReasonText )
1749 {
1750  if ( !‪util::isOneRound() )
1751  {
1752  ‪displayRoundEnd( winner, endReasonText );
1753 
1755 
1756  if ( !‪util::wasLastRound() )
1757  {
1758  if ( ‪checkRoundSwitch() )
1759  {
1760  if ( level.scoreRoundWinBased )
1761  {
1762  foreach( team in level.teams )
1763  {
1764  [[level._setTeamScore]]( team, game["roundswon"][team] );
1765  }
1766  }
1767 
1768  ‪displayRoundSwitch( winner, endReasonText );
1769  }
1770 
1771  if ( isdefined( level.nextRoundIsOvertime ) && level.nextRoundIsOvertime )
1772  {
1773  if ( !isdefined( game["overtime_round"] ) )
1774  {
1775  game["overtime_round"] = 1;
1776  }
1777  else
1778  {
1779  game["overtime_round"]++;
1780  }
1781  }
1782 
1783  SetMatchTalkFlag( "DeadChatWithDead", level.voip.deadChatWithDead );
1784  SetMatchTalkFlag( "DeadChatWithTeam", level.voip.deadChatWithTeam );
1785  SetMatchTalkFlag( "DeadHearTeamLiving", level.voip.deadHearTeamLiving );
1786  SetMatchTalkFlag( "DeadHearAllLiving", level.voip.deadHearAllLiving );
1787  SetMatchTalkFlag( "EveryoneHearsEveryone", level.voip.everyoneHearsEveryone );
1788  SetMatchTalkFlag( "DeadHearKiller", level.voip.deadHearKiller );
1789  SetMatchTalkFlag( "KillersHearVictim", level.voip.killersHearVictim );
1790 
1791  game["state"] = "playing";
1792  map_restart( true );
1794  return true;
1795  }
1796  }
1797  return false;
1798 }
1799 
1800 
1802 {
1803  if( level.rankedMatch )
1804  {
1805  placement = level.placement["all"];
1806  topThreePlayers = min( 3, placement.size );
1807 
1808  for ( index = 0; index < topThreePlayers; index++ )
1809  {
1810  if ( level.placement["all"][index].score )
1811  {
1812  if ( !index )
1813  {
1814  level.placement["all"][index] AddPlayerStatWithGameType( "TOPPLAYER", 1 );
1815  level.placement["all"][index] notify( "topplayer" );
1816  }
1817  else
1818  level.placement["all"][index] notify( "nottopplayer" );
1819 
1820  level.placement["all"][index] AddPlayerStatWithGameType( "TOP3", 1 );
1821  level.placement["all"][index] AddPlayerStat( "TOP3ANY", 1 );
1822  if ( level.hardcoreMode )
1823  {
1824  level.placement["all"][index] AddPlayerStat( "TOP3ANY_HC", 1 );
1825  }
1826  if ( level.multiTeam )
1827  {
1828  level.placement["all"][index] AddPlayerStat( "TOP3ANY_MULTITEAM", 1 );
1829  }
1830  level.placement["all"][index] notify( "top3" );
1831  }
1832  }
1833 
1834  for ( index = 3 ; index < placement.size ; index++ )
1835  {
1836  level.placement["all"][index] notify( "nottop3" );
1837  level.placement["all"][index] notify( "nottopplayer" );
1838  }
1839 
1840  if ( level.teambased )
1841  {
1842  foreach ( team in level.teams )
1843  {
1844  ‪setTopTeamStats(team);
1845  }
1846  }
1847  }
1848 }
1849 
1850 function ‪setTopTeamStats(team)
1851 {
1852  placementTeam = level.placement[team];
1853  topThreeTeamPlayers = min( 3, placementTeam.size );
1854  // should have at least 5 players on the team
1855  if ( placementTeam.size < 5 )
1856  return;
1857 
1858  for ( index = 0; index < topThreeTeamPlayers; index++ )
1859  {
1860  if ( placementTeam[index].score )
1861  {
1862  placementTeam[index] AddPlayerStat( "TOP3TEAM", 1 );
1863  placementTeam[index] AddPlayerStat( "TOP3ANY", 1 );
1864  if ( level.hardcoreMode )
1865  {
1866  placementTeam[index] AddPlayerStat( "TOP3ANY_HC", 1 );
1867  }
1868  if ( level.multiTeam )
1869  {
1870  placementTeam[index] AddPlayerStat( "TOP3ANY_MULTITEAM", 1 );
1871  }
1872  placementTeam[index] AddPlayerStatWithGameType( "TOP3TEAM", 1 );
1873  }
1874  }
1875 }
1876 
1877 function ‪figureOutWinningTeam( winner )
1878 {
1879  if ( !isdefined( winner ) )
1880  return "tie";
1881 
1882  if ( IsEntity( winner ) )
1883  return ( isdefined( winner.team ) ? winner.team : "none" );
1884 
1885  return winner;
1886 }
1887 
1889 {
1890  if ( !level.timeLimit || level.forcedEnd )
1891  {
1892  gameLength = ‪globallogic_utils::getTimePassed() / 1000;
1893  // cap it at 20 minutes to avoid exploiting
1894  gameLength = min( gameLength, 1200 );
1895  }
1896  else
1897  {
1898  gameLength = level.timeLimit * 60;
1899  }
1900 
1901  return gameLength;
1902 }
1903 
1904 function ‪awardLootXP( ) // self == player
1905 {
1906 
1907 }
1908 
1909 function ‪WaitAndUploadStats( player, waitTime )
1910 {
1911  wait waitTime;
1912 
1913  if ( isPlayer( player ) )
1914  {
1915  UploadStats( player );
1916  }
1917 }
1918 
1920 {
1921  if ( !isdefined( level.awardOtherLootXPfunctions ) )
1922  level.awardOtherLootXPfunctions = [];
1923 
1924  ‪ARRAY_ADD( level.awardOtherLootXPfunctions, func );
1925 }
1926 
1928 {
1929  player = self;
1930 
1931  if ( !isdefined( level.awardOtherLootXPfunctions ) )
1932  return 0;
1933 
1934  if ( !isPlayer( player ) )
1935  return 0;
1936 
1937  lootXP = 0;
1938 
1939  foreach( func in level.awardOtherLootXPfunctions )
1940  {
1941  if ( !isdefined( func ) )
1942  continue;
1943 
1944  lootXP += player [[ func ]]();
1945  }
1946 
1947  return lootXP;
1948 }
1949 
1950 function ‪endGame( winner, endReasonText )
1951 {
1952  // return if already ending via host quit or victory
1953  if ( game["state"] == "postgame" || level.gameEnded )
1954  return;
1955 
1956  if ( isdefined( level.onEndGame ) )
1957  [[level.onEndGame]]( winner );
1958 
1959  if ( !isdefined( level.disableOutroVisionSet ) || level.disableOutroVisionSet == false )
1960  {
1961  visionSetNaked( "mpOutro", 2.0 );
1962  }
1963 
1964  setmatchflag( "cg_drawSpectatorMessages", 0 );
1965  setmatchflag( "game_ended", 1 );
1966 
1967  game["state"] = "postgame";
1968  level.gameEndTime = getTime();
1969  level.gameEnded = true;
1970  SetDvar( "g_gameEnded", 1 );
1971  level.inGracePeriod = false;
1972  level notify ( "game_ended" );
1973  level ‪clientfield::set( "game_ended", 1 );
1975 
1976  foreach( team in level.teams )
1977  {
1978  game["lastroundscore"][team] = getTeamScore( team );
1979  }
1980 
1981  if( ‪util::isRoundBased() )
1982  {
1983  matchRecordRoundEnd();
1984  }
1985 
1986  winning_team = ‪figureOutWinningTeam( winner );
1987 
1988  if ( isdefined( game["overtime_round"] ) && isdefined( game["overtimeroundswon"][winning_team] ) )
1989  {
1990  game["overtimeroundswon"][winning_team]++;
1991  }
1992 
1993  if ( !isdefined( game["overtime_round"] ) || ‪util::wasLastRound() ) // Want to treat all overtime rounds as a single round
1994  {
1995  game["roundsplayed"]++;
1996  game["roundwinner"][game["roundsplayed"]] = winner;
1997 
1998  if ( isdefined( game["roundswon"][winning_team] ) )
1999  game["roundswon"][winning_team]++;
2000  }
2001 
2002  if ( isdefined( winner ) && isdefined( level.teams[ winning_team ] ) )
2003  {
2004  level.finalKillCam_winner = winner;
2005  }
2006  else
2007  {
2008  level.finalKillCam_winner = "none";
2009  }
2010 
2011  level.finalKillCam_winnerPicked = true; // consider "none" as picked too
2012 
2013  setGameEndTime( 0 ); // stop/hide the timers
2014 
2016 
2017  ‪updateRankedMatch( winner );
2018 
2019  // freeze players
2020  players = level.players;
2021 
2022  newTime = getTime();
2023  roundLength = ‪getRoundLength();
2024 
2025  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
2026 
2027  bbGameOver = 0;
2029  {
2030  bbGameOver = 1;
2031  }
2032 
2033  surveyId = 0;
2034  if( RandomFloat(1) <= GetDvarFloat("survey_chance") )
2035  surveyId = RandomIntRange(1, GetDvarInt( "survey_count" ) + 1 );
2036 
2037  for ( index = 0; index < players.size; index++ )
2038  {
2039  player = players[index];
2041  player thread roundEndDoF( 4.0 );
2042 
2044 
2045  player.pers["lastroundscore"] = player.pointstowin;
2046 
2047  // Update weapon usage stats
2048  player ‪weapons::update_timings( newTime );
2049 
2050  if ( bbGameOver )
2052 
2053  player ‪bbPlayerMatchEnd( roundLength, endReasonText, bbGameOver );
2054 
2055  player.pers["totalTimePlayed"] += player.timePlayed["total"];
2056 
2057  if ( bbGameOver )
2058  {
2059  if ( level.leagueMatch )
2060  {
2061  player setAARStat( "lobbyPopup", "leaguesummary" );
2062  }
2063  else
2064  {
2065  player setAARStat( "lobbyPopup", "summary" );
2066  }
2067  }
2068 
2069  player setAARStat( "surveyId", surveyId );
2070  player setAARStat( "hardcore", level.hardcoreMode );
2071  }
2072 
2073 // music::setmusicstate( "silent" );
2074 
2075 // temporarily disabling round end sound call to prevent the final killcam from not having sound
2076  if ( !level.inFinalKillcam )
2077  {
2078 // util::clientNotify( "snd_end_rnd" );
2079  }
2080 
2082  thread ‪challenges::roundEnd( winner );
2083 
2084  // update now
2085  game_winner = winner;
2086  if ( !‪util::isOneRound() )
2087  {
2088  game_winner = [[level.determineWinner]]( winner );
2089  }
2090  ‪update_top_scorers(game_winner);
2091 
2092  if ( ‪startNextRound( winner, endReasonText ) )
2093  {
2094  return;
2095  }
2096 
2098  // After this the match is really ending //
2100 
2101  if ( !‪util::isOneRound() )
2102  {
2103  if ( isdefined( level.onRoundEndGame ) )
2104  winner = [[level.onRoundEndGame]]( winner );
2105 
2106  endReasonText = ‪getEndReasonText();
2107  }
2108 
2110 
2111  // this needs to happen after updateWinLossStats to award winner multipliers correctly
2112  if( level.rankedmatch || level.arenaMatch )
2113  {
2115  }
2116 
2117  if( level.arenaMatch )
2118  {
2119  ‪arena::match_end( winner );
2120  }
2121 
2122  ‪result = "";
2123 
2124  if ( level.teambased )
2125  {
2126  if ( winner == "tie" )
2127  {
2128  ‪result = "draw";
2129  }
2130  else
2131  {
2132  ‪result = winner;
2133  }
2134  }
2135  else
2136  {
2137  if ( !isDefined( winner ) )
2138  {
2139  ‪result = "draw";
2140  }
2141  else
2142  {
2143  ‪result = winner.team;
2144  }
2145  }
2146 
2147  recordGameResult( ‪result );
2148 
2149  // we want the end time for each player the moment the match is done, not post-final-killcam-presentation
2150  players = level.players;
2151  for ( index = 0; index < players.size; index++ )
2152  {
2153  player = players[index];
2155  }
2156 
2157  skillUpdate( winner, level.teamBased );
2158  recordLeagueWinner( winner );
2159 
2161  thread ‪challenges::gameEnd( winner );
2162 
2164 
2166 
2167  level.finalGameEnd = true;
2168 
2169  if ( !isdefined( level.skipGameEnd ) || !level.skipGameEnd )
2170  ‪displayGameEnd( winner, endReasonText );
2171 
2172  level.finalGameEnd = undefined;
2173 
2174  if ( ‪util::isOneRound() )
2175  {
2177  }
2178 
2179  level.intermission = true;
2180 
2182 
2183  ‪util::setClientSysState("levelNotify", "fkcs" );
2184 
2185  // update again
2186 // update_top_scorers(winner);
2187 
2189  {
2190  thread ‪sendAfterActionReport();
2191  }
2192 
2193  stopdemorecording();
2194 
2195  SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
2196 
2197  //regain players array since some might've disconnected during the wait above
2198  players = level.players;
2199  for ( index = 0; index < players.size; index++ )
2200  {
2201  player = players[index];
2202 
2203  player notify ( "reset_outcome" );
2204  player thread [[level.spawnIntermission]]( false, level.useXCamsForEndGame );
2205  player setClientUIVisibilityFlag( "hud_visible", 1 );
2206  }
2207 
2208  level ‪clientfield::set( "post_game", 1 );
2209 
2211 
2212  if ( isdefined ( level.endGameFunction ) )
2213  {
2214  level thread [[level.endGameFunction]]();
2215  }
2216  //Eckert - Fading out sound
2217  level notify ( "sfade");
2218  /#print( "game ended" );#/
2219 
2220  if ( !isdefined( level.skipGameEnd ) || !level.skipGameEnd )
2221  wait 5.0;
2222 
2223  if( isDefined( level.end_game_video ) )
2224  {
2225  level thread ‪lui::play_movie( level.end_game_video.name, "fullscreen", true );
2226  wait( level.end_game_video.duration + 4.5 );
2227  }
2228 
2229  ‪exit_level();
2230 }
2231 
2232 function ‪awardLootXPToPlayers( ‪delay, players )
2233 {
2234  wait ‪delay;
2235 
2236  foreach( player in players )
2237  {
2238  if ( !isdefined( player ) )
2239  continue;
2240 
2241  player ‪awardLootXP();
2242  }
2243 }
2244 
2245 function ‪exit_level()
2246 {
2247  if ( level.exitLevel )
2248  return;
2249 
2250  level.exitLevel = true;
2251  exitLevel( false );
2252 }
2253 
2254 function ‪update_top_scorers(winner)
2255 {
2256  topscorers = [];
2257 
2258  winning_team = ‪figureOutWinningTeam( winner );
2259 
2260  if ( level.teambased && isdefined(winner) && isdefined( level.placement[winning_team] ) )
2261  {
2262  topscorers = level.placement[winning_team];
2263  }
2264  else
2265  {
2266  topscorers = level.placement["all"];
2267  }
2268 
2269  if ( topscorers.size )
2270  {
2271  level.doTopScorers = true;
2272  }
2273  else
2274  {
2275  level.doTopScorers = false;
2276  }
2277 
2278  ClearTopScorers();
2279 
2280  for ( i = 0; i < 3 && i < topscorers.size; i++ )
2281  {
2282  player = topscorers[i];
2283 
2284  player thread ‪checkForGestures( i );
2285 
2286  showcase_weapon = player ‪weapons::showcaseweapon_get();
2287  tauntIndex = player GetPlayerSelectedTaunt( ‪TAUNT_TYPE_FIRST_PLACE );
2288  gesture0Index = player GetPlayerSelectedGesture( ‪GESTURE_TYPE_GOOD_GAME );
2289  gesture1Index = player GetPlayerSelectedGesture( ‪GESTURE_TYPE_THREATEN );
2290  gesture2Index = player GetPlayerSelectedGesture( ‪GESTURE_TYPE_BOAST );
2291  // if they dont have a weapon then they never spawned in
2292  if ( !isDefined( showcase_weapon ) )
2293  {
2294  SetTopScorer( i, player, tauntIndex, gesture0Index, gesture1Index, gesture2Index, GetWeapon("ar_standard") );
2295  continue;
2296  }
2297 
2298  SetTopScorer( i, player, tauntIndex, gesture0Index, gesture1Index, gesture2Index, showcase_weapon["weapon"], showcase_weapon["options"], showcase_weapon["acvi"] );
2299  }
2300 }
2301 
2302 // self = player
2303 function ‪checkForGestures( topPlayerIndex )
2304 {
2305  self endon( "disconnect" );
2306 
2307  fieldName = "playTop" + topPlayerIndex + "Gesture";
2308 
2309  // Initialize the field
2310  level ‪clientfield::set( fieldName, ‪GESTURE_TYPE_MAX );
2312 
2313  while(true)
2314  {
2315  if ( self actionSlotOneButtonPressed() )
2316  {
2317  // Up - Good Game
2319  }
2320  else if ( self actionSlotThreeButtonPressed() )
2321  {
2322  // Left - Threaten
2324  }
2325  else if ( self actionSlotFourButtonPressed() )
2326  {
2327  // Right - Boast
2329  }
2330 /*
2331  else if ( self actionSlotTwoButtonPressed() )
2332  {
2333  Down - Unused
2334  self setGestureClientField( topPlayerIndex, 3 );
2335  }
2336 */
2338  }
2339 }
2340 
2341 function ‪setGestureClientField( fieldName, gestureType )
2342 {
2343  self notify ( "setGestureClientField" );
2344  self endon ( "setGestureClientField" );
2345 
2346  level ‪clientfield::set( fieldName, gestureType );
2347 
2349 
2350  // Reset the field
2351  level ‪clientfield::set( fieldName, ‪GESTURE_TYPE_MAX );
2352 }
2353 
2355 {
2356  // This should be done only if the end game flow prefab is in the map.
2357  level notify ( "endgame_sequence" );
2358 
2359  preloadingEnabled = GetDvarInt( "sv_mapSwitchPreloadFrontend", 0 );
2360  if ( level.doTopScorers && isDefined( ‪struct::get( "endgame_top_players_struct", "targetname" ) ) )
2361  {
2362  //setMatchFlag( "full_screen", 1 );
2363  setMatchFlag( "enable_popups", 1 ); // replace full_screen when new exes come in
2364 
2365  // get rid of the corpses so they dont show up in the top scorers screen
2366  ClearPlayerCorpses();
2367 
2368  level thread ‪sndSetMatchSnapshot( 3 );
2369  level thread ‪globallogic_audio::set_music_global("endmatch");
2370  level ‪clientfield::set( "displayTop3Players", 1 );
2371 
2372  if( preloadingEnabled )
2373  SwitchMap_Preload( "core_frontend" );
2374 
2375  wait 15.0;
2376  level ‪clientfield::set( "triggerScoreboardCamera", 1 );
2377  wait 5.0;
2378  //setMatchFlag( "full_screen", 0 );
2379  setMatchFlag( "enable_popups", 0 ); // replace full_screen when new exes come in
2380  }
2381  else if ( level.doEndgameScoreboard )
2382  {
2383  if( preloadingEnabled )
2384  SwitchMap_Preload( "core_frontend" );
2385  LUINotifyEvent( &"force_scoreboard", 0 );
2386  }
2387 }
2388 
2389 function ‪getTotalTimePlayed( maxLength ) // self == player
2390 {
2391  totalTimePlayed = 0;
2392  if ( isdefined( self.pers["totalTimePlayed"] ) )
2393  {
2394  totalTimePlayed = self.pers["totalTimePlayed"];
2395  if ( totalTimePlayed > maxLength )
2396  {
2397  totalTimePlayed = maxLength;
2398  }
2399  }
2400  return totalTimePlayed;
2401 }
2402 
2403 function ‪getRoundTimePlayed( roundLength ) // self == player
2404 {
2405  totalTimePlayed = 0;
2406  if ( isdefined( self.timePlayed ) && isdefined( self.timePlayed["total"] ) )
2407  {
2408  totalTimePlayed = self.timePlayed["total"];
2409  if ( totalTimePlayed > roundLength )
2410  {
2411  totalTimePlayed = roundLength;
2412  }
2413  }
2414  return totalTimePlayed;
2415 }
2416 
2417 function ‪bbPlayerMatchEnd( gameLength, endReasonString, gameOver ) // self == player
2418 {
2419 }
2420 
2421 function ‪roundEndWait( defaultDelay, matchBonus )
2422 {
2423  notifiesDone = false;
2424  while ( !notifiesDone )
2425  {
2426  players = level.players;
2427  notifiesDone = true;
2428  for ( index = 0; index < players.size; index++ )
2429  {
2430  if ( !isdefined( players[index].doingNotify ) || !players[index].doingNotify )
2431  continue;
2432 
2433  notifiesDone = false;
2434  }
2435  wait ( 0.5 );
2436  }
2437 
2438  if ( !matchBonus )
2439  {
2440  wait ( defaultDelay );
2441  level notify ( "round_end_done" );
2442  return;
2443  }
2444 
2445  wait ( defaultDelay / 2 );
2446  level notify ( "give_match_bonus" );
2447  wait ( defaultDelay / 2 );
2448 
2449  notifiesDone = false;
2450  while ( !notifiesDone )
2451  {
2452  players = level.players;
2453  notifiesDone = true;
2454  for ( index = 0; index < players.size; index++ )
2455  {
2456  if ( !isdefined( players[index].doingNotify ) || !players[index].doingNotify )
2457  continue;
2458 
2459  notifiesDone = false;
2460  }
2461  wait ( 0.5 );
2462  }
2463 
2464  level notify ( "round_end_done" );
2465 }
2466 
2467 
2468 function ‪roundEndDOF( time )
2469 {
2470  self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
2471 }
2472 
2473 
2475 {
2476  if ( isdefined( level.timeLimitOverride ) && level.timeLimitOverride )
2477  return;
2478 
2479  if ( game["state"] != "playing" )
2480  {
2481  setGameEndTime( 0 );
2482  return;
2483  }
2484 
2485  if ( level.timeLimit <= 0 )
2486  {
2487  setGameEndTime( 0 );
2488  return;
2489  }
2490 
2491  if ( level.inPrematchPeriod )
2492  {
2493  setGameEndTime( 0 );
2494  return;
2495  }
2496 
2497  if( ‪IS_TRUE( level.timerPaused ) )
2498  {
2499  timeRemaining = ‪globallogic_utils::getTimeRemaining();
2500  if ( timeRemaining > 30000 )
2501  {
2502  // round down to the nearest number so it doesn't jump back and forth
2503  setGameEndTime( -int(timeRemaining - 999) );
2504  }
2505  else
2506  {
2507  // we show tenths of a second under 30
2508  setGameEndTime( -int(timeRemaining - 99) );
2509  }
2510  return;
2511  }
2512 
2513  if ( level.timerStopped )
2514  {
2515  setGameEndTime( 0 );
2516  return;
2517  }
2518 
2519  if ( !isdefined( level.startTime ) )
2520  return;
2521 
2523 
2524  // want this accurate to the millisecond
2525  setGameEndTime( getTime() + int(timeLeft) );
2526 
2527  if ( timeLeft > 0 )
2528  return;
2529 
2530  [[level.onTimeLimit]]();
2531 }
2532 
2534 {
2535  if ( game["state"] != "playing" )
2536  return false;
2537 
2538  if ( level.scoreLimit <= 0 )
2539  return false;
2540 
2541  if ( level.teamBased )
2542  {
2544  return false;
2545  }
2546  else
2547  {
2548  if ( !isPlayer( self ) )
2549  return false;
2550 
2551  if ( self.pointstowin < level.scoreLimit )
2552  return false;
2553  }
2554 
2555  [[level.onScoreLimit]]();
2556 }
2557 
2559 {
2560  if ( game["state"] != "playing" )
2561  return false;
2562 
2563  if ( level.roundScoreLimit <= 0 )
2564  return false;
2565 
2566  if ( level.teamBased )
2567  {
2568  if( !game["teamSuddenDeath"][team] )
2569  return false;
2570  }
2571  else
2572  {
2573  return false;
2574  }
2575 
2576  [[level.onScoreLimit]]();
2577 }
2578 
2580 {
2581  if ( game["state"] != "playing" )
2582  return false;
2583 
2584  if ( level.roundScoreLimit <= 0 )
2585  return false;
2586 
2587  if ( level.teamBased )
2588  {
2590  return false;
2591  }
2592  else
2593  {
2594  if ( !isPlayer( self ) )
2595  return false;
2596 
2597  roundScoreLimit = ‪util::get_current_round_score_limit();
2598 
2599  if ( self.pointstowin < roundScoreLimit )
2600  return false;
2601  }
2602 
2603  [[level.onRoundScoreLimit]]();
2604 }
2605 
2607 {
2608  level endon ( "game_ended" );
2609 
2610  while ( game["state"] == "playing" )
2611  {
2612  roundlimit = ‪math::clamp( GetGametypeSetting( "roundLimit" ), level.roundLimitMin, level.roundLimitMax );
2613  if ( roundlimit != level.roundlimit )
2614  {
2615  level.roundlimit = roundlimit;
2616  level notify ( "update_roundlimit" );
2617  }
2618 
2619  timeLimit = [[level.getTimeLimit]]();
2620  if ( timeLimit != level.timeLimit )
2621  {
2622  level.timeLimit = timeLimit;
2623  SetDvar( "ui_timelimit", level.timeLimit );
2624  level notify ( "update_timelimit" );
2625  }
2626  thread ‪checkTimeLimit();
2627 
2628  scoreLimit = ‪math::clamp( GetGametypeSetting( "scoreLimit" ), level.scoreLimitMin, level.scoreLimitMax );
2629  if ( scoreLimit != level.scoreLimit )
2630  {
2631  level.scoreLimit = scoreLimit;
2632  SetDvar( "ui_scorelimit", level.scoreLimit );
2633  level notify ( "update_scorelimit" );
2634  }
2635  thread ‪checkScoreLimit();
2636 
2637  roundScoreLimit = ‪math::clamp( GetGametypeSetting( "roundScoreLimit" ), level.roundScoreLimitMin, level.roundScoreLimitMax );
2638  if ( roundScoreLimit != level.roundScoreLimit )
2639  {
2640  level.roundScoreLimit = roundScoreLimit;
2641  level notify ( "update_roundScoreLimit" );
2642  }
2643  thread ‪checkRoundScoreLimit();
2644 
2645  // make sure we check time limit right when game ends
2646  if ( isdefined( level.startTime ) )
2647  {
2649  {
2650  wait .1;
2651  continue;
2652  }
2653  }
2654  wait 1;
2655  }
2656 }
2657 
2658 
2660 {
2661  offset = 0;
2662  numPlayers = level.placement["all"].size;
2663  found = false;
2664  for ( i = 0; i < numPlayers; i++ )
2665  {
2666  if ( level.placement["all"][i] == self )
2667  found = true;
2668 
2669  if ( found )
2670  level.placement["all"][i] = level.placement["all"][ i + 1 ];
2671  }
2672  if ( !found )
2673  return;
2674 
2675  level.placement["all"][ numPlayers - 1 ] = undefined;
2676  assert( level.placement["all"].size == numPlayers - 1 );
2677 
2679 
2680  if ( level.teamBased )
2681  return;
2682 
2683  numPlayers = level.placement["all"].size;
2684  for ( i = 0; i < numPlayers; i++ )
2685  {
2686  player = level.placement["all"][i];
2687  player notify( "update_outcome" );
2688  }
2689 
2690 }
2691 
2693 {
2694 
2695  if ( !level.players.size )
2696  return;
2697 
2698  level.placement["all"] = [];
2699  foreach ( player in level.players )
2700  {
2701  if ( !level.teambased || isdefined( level.teams[ player.team ] ) )
2702  level.placement["all"][level.placement["all"].size] = player;
2703  }
2704 
2705  placementAll = level.placement["all"];
2706 
2707  if ( level.teamBased )
2708  {
2709  for ( i = 1; i < placementAll.size; i++ )
2710  {
2711  player = placementAll[i];
2712  playerScore = player.score;
2713  for ( j = i - 1; j >= 0 && (playerScore > placementAll[j].score || (playerScore == placementAll[j].score && player.deaths < placementAll[j].deaths)); j-- )
2714  placementAll[j + 1] = placementAll[j];
2715  placementAll[j + 1] = player;
2716  }
2717  }
2718  else
2719  {
2720  for ( i = 1; i < placementAll.size; i++ )
2721  {
2722  player = placementAll[i];
2723  playerScore = player.pointstowin;
2724  for ( j = i - 1; j >= 0 && (playerScore > placementAll[j].pointstowin || (playerScore == placementAll[j].pointstowin && player.deaths < placementAll[j].deaths) || (playerScore == placementAll[j].pointstowin && player.deaths == placementAll[j].deaths && player.lastKillTime > placementAll[j].lastKillTime)); j-- )
2725  placementAll[j + 1] = placementAll[j];
2726  placementAll[j + 1] = player;
2727  }
2728  }
2729 
2730  level.placement["all"] = placementAll;
2731 
2733 
2734 }
2735 
2736 
2738 {
2739  foreach( team in level.teams )
2740  {
2741  placement[team] = [];
2742  }
2743  placement["spectator"] = [];
2744 
2745  if ( !level.teamBased )
2746  return;
2747 
2748  placementAll = level.placement["all"];
2749  placementAllSize = placementAll.size;
2750 
2751  for ( i = 0; i < placementAllSize; i++ )
2752  {
2753  player = placementAll[i];
2754  team = player.pers["team"];
2755 
2756  placement[team][ placement[team].size ] = player;
2757  }
2758 
2759  foreach( team in level.teams )
2760  {
2761  level.placement[team] = placement[team];
2762  }
2763 }
2764 
2765 function ‪getPlacementForPlayer( player )
2766 {
2768 
2769  playerRank = -1;
2770  placement = level.placement["all"];
2771  for ( placementIndex = 0; placementIndex < placement.size; placementIndex++ )
2772  {
2773  if ( level.placement["all"][placementIndex] == player )
2774  {
2775  playerRank = (placementIndex + 1);
2776  break;
2777  }
2778  }
2779 
2780  return playerRank;
2781 }
2782 
2783 function ‪isTopScoringPlayer( player )
2784 {
2785  topScoringPlayer = false;
2787 
2788  assert( level.placement["all"].size > 0 );
2789  if ( level.placement["all"].size == 0 )
2790  {
2791  return false;
2792  }
2793 
2794  if ( level.teambased )
2795  {
2796  topScore = level.placement["all"][0].score;
2797  for ( index = 0; index < level.placement["all"].size; index++ )
2798  {
2799  if ( level.placement["all"][index].score == 0 )
2800  {
2801  break;
2802  }
2803  if ( topScore > level.placement["all"][index].score )
2804  {
2805  break;
2806  }
2807  if ( player == level.placement["all"][index] )
2808  {
2809  topScoringPlayer = true;
2810  break;
2811  }
2812  }
2813  }
2814  else
2815  {
2816  topScore = level.placement["all"][0].pointsToWin;
2817  for ( index = 0; index < level.placement["all"].size; index++ )
2818  {
2819  if ( level.placement["all"][index].pointsToWin == 0 )
2820  {
2821  break;
2822  }
2823  if ( topScore > level.placement["all"][index].pointsToWin )
2824  {
2825  break;
2826  }
2827  if ( player == level.placement["all"][index] )
2828  {
2829  topScoringPlayer = true;
2830  break;
2831  }
2832  }
2833  }
2834  return topScoringPlayer;
2835 }
2836 
2837 function ‪sortDeadPlayers( team )
2838 {
2839  // only need to sort if we are running queued respawn
2840  if ( !level.playerQueuedRespawn )
2841  return;
2842 
2843  // sort by death time
2844  for ( i = 1; i < level.deadPlayers[team].size; i++ )
2845  {
2846  player = level.deadPlayers[team][i];
2847  for ( j = i - 1; j >= 0 && player.deathTime < level.deadPlayers[team][j].deathTime; j-- )
2848  level.deadPlayers[team][j + 1] = level.deadPlayers[team][j];
2849  level.deadPlayers[team][j + 1] = player;
2850  }
2851 
2852  for ( i = 0; i < level.deadPlayers[team].size; i++ )
2853  {
2854  if ( level.deadPlayers[team][i].spawnQueueIndex != i )
2855  {
2856  level.spawnQueueModified[team] = true;
2857  }
2858  level.deadPlayers[team][i].spawnQueueIndex = i;
2859  }
2860 }
2861 
2863 {
2864  count = 0;
2865  foreach( team in level.teams )
2866  {
2867  count += level.aliveCount[team];
2868  }
2869  return count;
2870 }
2871 
2873 {
2874  count = 0;
2875  foreach( team in level.teams )
2876  {
2877  count += level.playerLives[team];
2878  }
2879  return count;
2880 }
2881 
2882 function ‪initTeamVariables( team )
2883 {
2884 
2885  if ( !isdefined( level.aliveCount ) )
2886  level.aliveCount = [];
2887 
2888  level.aliveCount[team] = 0;
2889  level.lastAliveCount[team] = 0;
2890 
2891  if ( !isdefined( game["everExisted"] ) )
2892  {
2893  game["everExisted"] = [];
2894  }
2895  if ( !isdefined( game["everExisted"][team] ) )
2896  {
2897  game["everExisted"][team] = false;
2898  }
2899  level.everExisted[team] = false;
2900  level.waveDelay[team] = 0;
2901  level.lastWave[team] = 0;
2902  level.wavePlayerSpawnIndex[team] = 0;
2903 
2904  ‪resetTeamVariables( team );}
2905 
2906 function ‪resetTeamVariables( team )
2907 {
2908  level.playerCount[team] = 0;
2909  level.botsCount[team] = 0;
2910  level.lastAliveCount[team] = level.aliveCount[team];
2911  level.aliveCount[team] = 0;
2912  level.playerLives[team] = 0;
2913  level.alivePlayers[team] = [];
2914  level.spawningPlayers[team] = [];
2915  level.deadPlayers[team] = [];
2916  level.squads[team] = [];
2917  level.spawnQueueModified[team] = false;
2918 }
2919 
2921 {
2922  // run only once per frame, at the end of the frame.
2923  level notify("updating_team_status");
2924  level endon("updating_team_status");
2925  level endon ( "game_ended" );
2926  waittillframeend;
2927 
2928  wait 0; // Required for Callback_PlayerDisconnect to complete before updateTeamStatus can execute
2929 
2930  if ( game["state"] == "postgame" )
2931  return;
2932 
2933  resetTimeout();
2934 
2935  foreach( team in level.teams )
2936  {
2937  ‪resetTeamVariables( team );
2938  }
2939 
2940  if ( !level.teambased )
2941  {
2942  ‪resetTeamVariables( "free" );
2943  }
2944 
2945  level.activePlayers = [];
2946 
2947  players = level.players;
2948  for ( i = 0; i < players.size; i++ )
2949  {
2950  player = players[i];
2951 
2952  if ( !isdefined( player ) && level.splitscreen )
2953  continue;
2954 
2955  if ( level.teambased || player.team == "spectator" )
2956  {
2957  team = player.team;
2958  }
2959  else
2960  {
2961  team = "free";
2962  }
2963 
2964  playerclass = player.curClass;
2965 
2966  if ( team != "spectator" && (isdefined( playerclass ) && playerclass != "") )
2967  {
2968  level.playerCount[team]++;
2969 
2970  if( isdefined( player.pers["isBot"] ) )
2971  level.botsCount[team]++;
2972 
2973  not_quite_dead = false;
2974 
2975  // used by the resurrect gadget to keep players that could self-resurrect from appearing dead
2976  if ( isdefined( player.overridePlayerDeadStatus ) )
2977  {
2978  not_quite_dead = player [[ player.overridePlayerDeadStatus ]]();
2979  }
2980 
2981  if ( player.sessionstate == "playing" )
2982  {
2983  level.aliveCount[team]++;
2984  level.playerLives[team]++;
2985  player.spawnQueueIndex = -1;
2986 
2987  if ( isAlive( player ) )
2988  {
2989  level.alivePlayers[team][level.alivePlayers[team].size] = player;
2990  level.activeplayers[ level.activeplayers.size ] = player;
2991  }
2992  else
2993  {
2994  level.deadPlayers[team][level.deadPlayers[team].size] = player;
2995  }
2996  }
2997  else if ( not_quite_dead )
2998  {
2999  level.aliveCount[team]++;
3000  level.playerLives[team]++;
3001  level.alivePlayers[team][level.alivePlayers[team].size] = player;
3002  }
3003  else
3004  {
3005  level.deadPlayers[team][level.deadPlayers[team].size] = player;
3006  if ( player ‪globallogic_spawn::maySpawn() )
3007  level.playerLives[team]++;
3008  }
3009  }
3010  }
3011 
3012  totalAlive = ‪totalAliveCount();
3013 
3014  if ( totalAlive > level.maxPlayerCount )
3015  level.maxPlayerCount = totalAlive;
3016 
3017  foreach( team in level.teams )
3018  {
3019  if ( level.aliveCount[team] )
3020  {
3021  game["everExisted"][team] = true;
3022  level.everExisted[team] = true;
3023  }
3024 
3025  ‪sortDeadPlayers( team );
3026  }
3027 
3028  level ‪updateGameEvents();
3029 }
3030 
3031 function ‪updateAliveTimes(team)
3032 {
3033  level.aliveTimesAverage[team] = 0;
3034 
3035  if ( game["state"] == "postgame" )
3036  return;
3037 
3038  total_player_count = 0;
3039  average_player_spawn_time = 0;
3040  total_value_count = 0;
3041 
3042  foreach( player in level.alivePlayers[team] )
3043  {
3044  average_time = 0;
3045  count = 0;
3046  foreach( time in player.aliveTimes )
3047  {
3048  if ( time != 0 )
3049  {
3050  average_time += time;
3051  count++;
3052  }
3053  }
3054 
3055  if ( count )
3056  {
3057  total_value_count += count;
3058  average_player_spawn_time += average_time / count;
3059  total_player_count++;
3060  }
3061  }
3062 
3063  foreach( player in level.deadPlayers[team] )
3064  {
3065  average_time = 0;
3066  count = 0;
3067  foreach( time in player.aliveTimes )
3068  {
3069  if ( time != 0 )
3070  {
3071  average_time += time;
3072  count++;
3073  }
3074  }
3075 
3076  if ( count )
3077  {
3078  total_value_count += count;
3079  average_player_spawn_time += average_time / count;
3080  total_player_count++;
3081  }
3082  }
3083 
3084  // if we dont have player or dont have enough data dont bother
3085  if ( total_player_count == 0 || total_value_count < 3 )
3086  {
3087  level.aliveTimesAverage[team] = 0;
3088  return;
3089  }
3090 
3091  level.aliveTimesAverage[team] = average_player_spawn_time / total_player_count;
3092 }
3093 
3095 {
3096  foreach( team in level.teams )
3097  {
3098  ‪updateAliveTimes(team);
3099  }
3100 }
3101 
3103 {
3104  assert( isdefined( team ) );
3105 
3106  if ( level.scoreLimit <= 0 )
3107  return;
3108 
3109  if ( !level.teamBased )
3110  return;
3111 
3112  // Give the data a minute to converge/settle
3113  if ( ‪globallogic_utils::getTimePassed() < ( 60 * 1000 ) )
3114  return;
3115 
3117 
3118  if ( timeLeft < 1 )
3119  {
3120  level notify( "match_ending_soon", "score" );
3121  }
3122 }
3123 
3125 {
3126  assert( IsPlayer( self ) );
3127 
3128  if ( level.scoreLimit <= 0 )
3129  return;
3130 
3131  if ( level.teamBased )
3132  return;
3133 
3134  // Give the data a minute to converge/settle
3135  if ( ‪globallogic_utils::getTimePassed() < ( 60 * 1000 ) )
3136  return;
3137 
3139 
3140  if ( timeLeft < 1 )
3141  {
3142  level notify( "match_ending_soon", "score" );
3143  }
3144 }
3145 
3147 {
3148  level endon ( "game_ended" );
3149 
3150  wait .05;
3151 
3152  clockObject = ‪spawn( "script_origin", (0,0,0) );
3153 
3154  while ( game["state"] == "playing" )
3155  {
3156  if ( !level.timerStopped && level.timeLimit )
3157  {
3158  timeLeft = ‪globallogic_utils::getTimeRemaining() / 1000;
3159  timeLeftInt = int(timeLeft + 0.5); // adding .5 and flooring rounds it.
3160 
3161  if ( timeLeftInt == 601 )
3162  ‪util::clientNotify( "notify_10" );
3163 
3164  if ( timeLeftInt == 301 )
3165  ‪util::clientNotify( "notify_5" );
3166 
3167  if ( timeLeftInt == 60 )
3168  ‪util::clientNotify( "notify_1" );
3169 
3170  if ( timeLeftInt == 12 )
3171  ‪util::clientNotify( "notify_count" );
3172 
3173  if ( timeLeftInt >= 40 && timeLeftInt <= 60 )
3174  level notify ( "match_ending_soon", "time" );
3175 
3176  if ( timeLeftInt >= 30 && timeLeftInt <= 40 )
3177  level notify ( "match_ending_pretty_soon", "time" );
3178 
3179  if( timeLeftInt <= 32 )
3180  level notify ( "match_ending_vox" );
3181 
3182  if ( timeLeftInt <= 10 || (timeLeftInt <= 30 && timeLeftInt % 2 == 0) )
3183  {
3184  level notify ( "match_ending_very_soon", "time" );
3185  // don't play a tick at exactly 0 seconds, that's when something should be happening!
3186  if ( timeLeftInt == 0 )
3187  break;
3188 
3189  clockObject playSound( "mpl_ui_timer_countdown" );
3190  }
3191 
3192  // synchronize to be exactly on the second
3193  if ( timeLeft - floor(timeLeft) >= .05 )
3194  wait timeLeft - floor(timeLeft);
3195  }
3196 
3197  wait ( 1.0 );
3198  }
3199 }
3200 
3202 {
3203  setGameEndTime( getTime() + int(waitTime*1000) );
3204  clockObject = ‪spawn( "script_origin", (0,0,0) );
3205 
3206  if ( waitTime >= 10.0 )
3207  wait ( waitTime - 10.0 );
3208 
3209  for ( ;; )
3210  {
3211  clockObject playSound( "mpl_ui_timer_countdown" );
3212  wait ( 1.0 );
3213  }
3214 }
3216 {
3217  level endon ( "game_ended" );
3218 
3219  while(1)
3220  {
3221  for ( i = 0; i < level.players.size; i++ )
3222  {
3223  player = level.players[i];
3224  if( isAlive( player ) )
3225  {
3226  RecordBreadcrumbDataForPlayer( player, player.lastShotBy );
3227  }
3228  }
3229 
3230  wait( 2.0 ); // make sure #define BREADCRUMBDATA_INTERVAL_SECONDS in code matches this!
3231  }
3232 
3233 }
3234 
3235 function ‪startGame()
3236 {
3238  level.timerStopped = false;
3239  level.playableTimerStopped = false;
3240  // RF, disabled this, as it is not required anymore.
3241  //thread spawnlogic::spawn_per_frame_update();
3242 
3243  SetMatchTalkFlag( "DeadChatWithDead", level.voip.deadChatWithDead );
3244  SetMatchTalkFlag( "DeadChatWithTeam", level.voip.deadChatWithTeam );
3245  SetMatchTalkFlag( "DeadHearTeamLiving", level.voip.deadHearTeamLiving );
3246  SetMatchTalkFlag( "DeadHearAllLiving", level.voip.deadHearAllLiving );
3247  SetMatchTalkFlag( "EveryoneHearsEveryone", level.voip.everyoneHearsEveryone );
3248  SetMatchTalkFlag( "DeadHearKiller", level.voip.deadHearKiller );
3249  SetMatchTalkFlag( "KillersHearVictim", level.voip.killersHearVictim );
3250 
3251  ClearTopScorers();
3252 
3253  if(IsDefined(level.custom_prematch_period))
3254  {
3255  [[level.custom_prematch_period]]();
3256  }
3257  else
3258  {
3260  }
3261 
3262  level notify("prematch_over");
3263  level.prematch_over = true;
3264 
3265  level ‪clientfield::set("gameplay_started", 1);
3266 
3267  thread ‪notifyEndOfGameplay();
3268 
3269  thread ‪timeLimitClock();
3270  thread ‪gracePeriod();
3271  thread ‪watchMatchEndingSoon();
3272 
3275  thread ‪recordBreadcrumbData();
3276 
3277  if( ‪util::isRoundBased() )
3278  {
3279  if( ‪util::getRoundsPlayed() == 0 )
3280  {
3281  // true beginning of a round-based game
3282  recordMatchBegin();
3283  }
3284  matchRecordRoundStart();
3285 
3286  if ( isdefined( game["overtime_round"] ) )
3287  {
3288  matchRecordOvertimeRound();
3289  }
3290  }
3291  else
3292  {
3293  // not round based
3294  recordMatchBegin();
3295  }
3296 }
3297 
3298 function ‪isPrematchRequirementConditionMet(activeTeamCount)
3299 {
3300  if ( level.prematchRequirement == 0 )
3301  return true;
3302 
3303  if ( level.teamBased )
3304  {
3305  if ( activeTeamCount.size <= 1 )
3306  return false;
3307 
3308  foreach( teamCount in activeTeamCount )
3309  {
3310  if ( teamCount != level.prematchRequirement )
3311  return false;
3312  }
3313  }
3314  else
3315  {
3316  if ( activeTeamCount["free"] != level.prematchRequirement )
3317  return false;
3318  }
3319  return true;
3320 }
3321 
3323 {
3324  level endon( "game_ended" );
3325  ‪startTime = getTime();
3326 
3327  playerReady = false;
3328  activePlayerCount = 0;
3329  acceptTestClient = false;
3330 
3331  activeTeamCount = [];
3332  player_ready = [];
3333 
3334  while ( !playerReady || activePlayerCount == 0 || !isprematchRequirementConditionMet(activeTeamCount) )
3335  {
3336  activePlayerCount = 0;
3337 
3338  if ( level.teamBased )
3339  {
3340  foreach( team in level.teams )
3341  {
3342  activeTeamCount[team] = 0;
3343  }
3344  }
3345  else
3346  {
3347  activeTeamCount["free"] = 0;
3348  }
3349 
3350  temp_player_ready = [];
3351 
3352  foreach( player in level.players )
3353  {
3354  // only consider real players
3355  if ( player istestclient() && acceptTestClient == false )
3356  continue;
3357 
3358  if ( player.team != "spectator" )
3359  {
3360  activePlayerCount++;
3361 
3362  player_num = player GetEntityNumber();
3363  if ( isDefined( player_ready[player_num] ) )
3364  {
3365  temp_player_ready[player_num] = player_ready[player_num];
3366  }
3367  else
3368  {
3369  temp_player_ready[player_num] = GetTime();
3370  }
3371 
3372  // streamer gets marked ready well before the player is done "loading"
3373  // we want to wait until the player is done loading but will have a five second failsafe
3374  // this mechanic should probably be a core system as we have several places that we want to know
3375  // when the player is done loading
3376  if ( ((temp_player_ready[player_num] + 5000) < GetTime()) || player isStreamerReady( -1, true ) )
3377  {
3378  if ( level.teamBased )
3379  {
3380  activeTeamCount[player.team]++;
3381  }
3382  else
3383  {
3384  activeTeamCount["free"]++;
3385  }
3386  }
3387  }
3388 
3389  if( player isStreamerReady( -1, true ) )
3390  {
3391  if ( playerReady == false )
3392  {
3393  level notify("first_player_ready", player );
3394  }
3395  playerReady = true;
3396  }
3397  }
3398 
3399  // this causes any players that no longer exist in the list to flush
3400  player_read = temp_player_ready;
3401 
3403  if( getTime() - ‪startTime > ( 20 * 1000 ) )
3404  {
3405  if ( level.rankedmatch == false && level.arenamatch == false )
3406  {
3407  acceptTestClient = true;
3408  }
3409  }
3410 
3411  if( level.rankedMatch && ((getTime() - ‪startTime) > ( 120 * 1000 )) )
3412  {
3413  //EOughton: if we've been sitting here for 2 minutes without anyone making it in, it's time to call it a night
3414  ‪exit_level();
3415 
3416  while(1)
3417  {
3418  // dont do anything just let the level exit
3419  wait(10);
3420  }
3421  }
3422  }
3423 }
3424 
3426 {
3427  if ( level.prematchRequirement != 0 )
3428  {
3429  level waittill ("first_player_ready", player );
3430  LUINotifyEvent( &"prematch_waiting_for_players" );
3431  }
3432 }
3433 
3435 {
3436  setMatchFlag( "hud_hardcore", level.hardcoreMode );
3437 
3438  level endon( "game_ended" );
3439 
3441 
3442  if ( level.prematchPeriod > 0 )
3443  {
3444  thread ‪matchStartTimer();
3446 
3448 
3449  wait ( level.prematchPeriod );
3450  }
3451  else
3452  {
3454 
3456  }
3457 
3458  level.inPrematchPeriod = false;
3459  level thread ‪sndSetMatchSnapshot( 0 );
3460 
3461  for ( index = 0; index < level.players.size; index++ )
3462  {
3463  level.players[index] ‪util::freeze_player_controls( false );
3464  level.players[index] enableWeapons();
3465  }
3466 
3467  if ( game["state"] != "playing" )
3468  return;
3469 }
3470 
3471 function ‪gracePeriod()
3472 {
3473  level endon("game_ended");
3474 
3475  if ( isdefined( level.gracePeriodFunc ) )
3476  {
3477  [[ level.gracePeriodFunc ]]();
3478  }
3479  else
3480  {
3481  wait ( level.gracePeriod );
3482  }
3483 
3484  level notify ( "grace_period_ending" );
3486 
3487  level.inGracePeriod = false;
3488 
3489  if ( game["state"] != "playing" )
3490  return;
3491 
3492  if ( level.numLives )
3493  {
3494  // Players on a team but without a weapon show as dead since they can not get in this round
3495  players = level.players;
3496 
3497  for ( i = 0; i < players.size; i++ )
3498  {
3499  player = players[i];
3500 
3501  if ( !player.hasSpawned && player.sessionteam != "spectator" && !isAlive( player ) )
3502  player.statusicon = "hud_status_dead";
3503  }
3504  }
3505 
3506  level thread ‪updateTeamStatus();
3507  level thread ‪updateAllAliveTimes();
3508 }
3509 
3511 {
3512  SetDvar( "xblive_matchEndingSoon", 0 );
3513  level waittill( "match_ending_soon", reason );
3514  SetDvar( "xblive_matchEndingSoon", 1 );
3515 }
3516 
3518 {
3519  // these are defined in the teamset file
3520  foreach ( team in level.teams )
3521  {
3522  Assert( isdefined( game["strings"][ team + "_win"] ), "game[\"strings\"][\"" + team + "_win\"] does not exist" );
3523  Assert( isdefined( game["strings"][ team + "_win_round"] ), "game[\"strings\"][\"" + team + "_win_round\"] does not exist" );
3524  Assert( isdefined( game["strings"][ team + "_mission_accomplished"] ), "game[\"strings\"][\"" + team + "_mission_accomplished\"] does not exist" );
3525  Assert( isdefined( game["strings"][ team + "_eliminated"] ), "game[\"strings\"][\"" + team + "_eliminated\"] does not exist" );
3526  Assert( isdefined( game["strings"][ team + "_forfeited"] ), "game[\"strings\"][\"" + team + "_forfeited\"] does not exist" );
3527  Assert( isdefined( game["strings"][ team + "_name"] ), "game[\"strings\"][\"" + team + "_name\"] does not exist" );
3528  Assert( isdefined( game["music"]["spawn_" + team] ), "game[\"music\"][\"spawn_" + team + "\"] does not exist" );
3529  Assert( isdefined( game["music"]["victory_" + team] ), "game[\"music\"][\"victory_" + team + "\"] does not exist" );
3530  Assert( isdefined( game["icons"][team] ), "game[\"icons\"][\"" + team + "\"] does not exist" );
3531  Assert( isdefined( game["voice"][team] ), "game[\"voice\"][\"" + team + "\"] does not exist" );
3532  }
3533 }
3534 
3536 {
3537  foreach ( team in level.teams )
3538  {
3539  if ( level.waveDelay[team] )
3540  return true;
3541  }
3542 
3543  return false;
3544 }
3545 
3547 {
3548  level.prematchRequirement = 0;
3549  level.prematchPeriod = 0;
3550  level.intermission = false;
3551 
3552  setmatchflag( "cg_drawSpectatorMessages", 1 );
3553  setmatchflag( "game_ended", 0 );
3554 
3555  if ( !isdefined( game["gamestarted"] ) )
3556  {
3557  // defaults if not defined in level script
3558  if ( !isdefined( game["allies"] ) )
3559  game["allies"] = "seals";
3560  if ( !isdefined( game["axis"] ) )
3561  game["axis"] = "pmc";
3562  if ( !isdefined( game["attackers"] ) )
3563  game["attackers"] = "allies";
3564  if ( !isdefined( game["defenders"] ) )
3565  game["defenders"] = "axis";
3566 
3567  // if this hits the teams are not setup right
3568  assert( game["attackers"] != game["defenders"] );
3569 
3570  // TODO MTEAM - need to update this valid team
3571  foreach( team in level.teams )
3572  {
3573  if ( !isdefined( game[team] ) )
3574  game[team] = "pmc";
3575  }
3576 
3577  if ( !isdefined( game["state"] ) )
3578  game["state"] = "playing";
3579 
3580  //makeDvarServerInfo( "cg_thirdPersonAngle", 354 );
3581 
3582  SetDvar( "cg_thirdPersonAngle", 354 );
3583 
3584  game["strings"]["press_to_spawn"] = &"PLATFORM_PRESS_TO_SPAWN";
3585  if ( level.teamBased )
3586  {
3587  game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_TEAMS";
3588  game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
3589  }
3590  else
3591  {
3592  game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_PLAYERS";
3593  game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
3594  }
3595  game["strings"]["match_starting_in"] = &"MP_MATCH_STARTING_IN";
3596  game["strings"]["spawn_next_round"] = &"MP_SPAWN_NEXT_ROUND";
3597  game["strings"]["waiting_to_spawn"] = &"MP_WAITING_TO_SPAWN";
3598  game["strings"]["waiting_to_spawn_ss"] = &"MP_WAITING_TO_SPAWN_SS";
3599  //game["strings"]["waiting_to_safespawn"] = &"MP_WAITING_TO_SAFESPAWN";
3600  game["strings"]["you_will_spawn"] = &"MP_YOU_WILL_RESPAWN";
3601  game["strings"]["match_starting"] = &"MP_MATCH_STARTING";
3602  game["strings"]["change_class"] = &"MP_CHANGE_CLASS_NEXT_SPAWN";
3603  game["strings"]["last_stand"] = &"MPUI_LAST_STAND";
3604 
3605  game["strings"]["cowards_way"] = &"PLATFORM_COWARDS_WAY_OUT";
3606 
3607  game["strings"]["tie"] = &"MP_MATCH_TIE";
3608  game["strings"]["round_draw"] = &"MP_ROUND_DRAW";
3609 
3610  game["strings"]["enemies_eliminated"] = &"MP_ENEMIES_ELIMINATED";
3611  game["strings"]["score_limit_reached"] = &"MP_SCORE_LIMIT_REACHED";
3612  game["strings"]["round_score_limit_reached"] = &"MP_SCORE_LIMIT_REACHED";
3613  game["strings"]["round_limit_reached"] = &"MP_ROUND_LIMIT_REACHED";
3614  game["strings"]["time_limit_reached"] = &"MP_TIME_LIMIT_REACHED";
3615  game["strings"]["players_forfeited"] = &"MP_PLAYERS_FORFEITED";
3616  game["strings"]["other_teams_forfeited"] = &"MP_OTHER_TEAMS_FORFEITED";
3617 
3619 
3620  [[level.onPrecacheGameType]]();
3621 
3622  game["gamestarted"] = true;
3623 
3624  game["totalKills"] = 0;
3625 
3626  foreach( team in level.teams )
3627  {
3628  if ( !isdefined( game["migratedHost"] ) )
3629  game["teamScores"][team] = 0;
3630 
3631  game["teamSuddenDeath"][team] = false;
3632 
3633  game["totalKillsTeam"][team] = 0;
3634  }
3635 
3636  level.prematchRequirement = GetGametypeSetting( "prematchRequirement" );
3637  level.prematchPeriod = GetGametypeSetting( "prematchperiod" );
3638 
3639  if ( GetDvarint( "xblive_clanmatch" ) != 0 )
3640  {
3641  // TODO MTEAM is this code used anymore?
3642  foreach( team in level.teams )
3643  {
3644  game["icons"][team] = "composite_emblem_team_axis";
3645  }
3646 
3647  game["icons"]["allies"] = "composite_emblem_team_allies";
3648  game["icons"]["axis"] = "composite_emblem_team_axis";
3649  }
3650  }
3651  else
3652  {
3653  if ( !level.splitscreen )
3654  level.prematchPeriod = GetGametypeSetting( "preroundperiod" );
3655  }
3656 
3657  ‪DEFAULT( game["timepassed"], 0 );
3658  ‪DEFAULT( game["playabletimepassed"], 0 );
3659  ‪DEFAULT( game["roundsplayed"], 0 );
3660 
3661  SetRoundsPlayed( game["roundsplayed"] );
3662 
3663  if ( isdefined( game["overtime_round"] ) )
3664  {
3665  SetRoundsPlayed( game["roundsplayed"] + game["overtime_round"] - 1 );
3666  SetMatchFlag( "overtime", 1 );
3667  }
3668  else
3669  {
3670  SetMatchFlag( "overtime", 0 );
3671  }
3672 
3673  if(!isdefined(game["roundwinner"] ))
3674  game["roundwinner"] = [];
3675 
3676  if(!isdefined(game["lastroundscore"] ))
3677  game["lastroundscore"] = [];
3678 
3679  if(!isdefined(game["roundswon"] ))
3680  game["roundswon"] = [];
3681 
3682  if(!isdefined(game["roundswon"]["tie"] ))
3683  game["roundswon"]["tie"] = 0;
3684 
3685  if(!isdefined(game["overtimeroundswon"] ))
3686  game["overtimeroundswon"] = [];
3687 
3688  if(!isdefined(game["overtimeroundswon"]["tie"] ))
3689  game["overtimeroundswon"]["tie"] = 0;
3690 
3691  foreach ( team in level.teams )
3692  {
3693  if(!isdefined(game["roundswon"][team] ))
3694  game["roundswon"][team] = 0;
3695  if(!isdefined(game["overtimeroundswon"][team] ))
3696  game["overtimeroundswon"][team] = 0;
3697 
3698  level.teamSpawnPoints[team] = [];
3699  level.spawn_point_team_class_names[team] = [];
3700  }
3701 
3702  level.skipVote = false;
3703  level.gameEnded = false;
3704  level.exitLevel = false;
3705  //level clientfield::set( "game_ended", 0 );
3706  SetDvar( "g_gameEnded", 0 );
3707 
3708  level.objIDStart = 0;
3709  level.forcedEnd = false;
3710  level.hostForcedEnd = false;
3711 
3712  level.hardcoreMode = GetGametypeSetting( "hardcoreMode" );
3713  if ( level.hardcoreMode )
3714  {
3715  /#print( "game mode: hardcore" );#/
3716 
3717  //set up friendly fire delay for hardcore
3718  if( !isdefined(level.friendlyFireDelayTime) )
3719  level.friendlyFireDelayTime = 0;
3720  }
3721 
3722  if ( GetDvarString( "scr_max_rank" ) == "" )
3723  SetDvar( "scr_max_rank", "0" );
3724  level.rankCap = GetDvarint( "scr_max_rank" );
3725 
3726  if ( GetDvarString( "scr_min_prestige" ) == "" )
3727  {
3728  SetDvar( "scr_min_prestige", "0" );
3729  }
3730  level.minPrestige = GetDvarint( "scr_min_prestige" );
3731 
3732  // this gets set to false when someone takes damage or a gametype-specific event happens.
3733  level.useStartSpawns = true;
3734  level.alwaysUseStartSpawns = false;
3735  level.useXCamsForEndGame = true;
3736 
3737  level.cumulativeRoundScores = GetGametypeSetting( "cumulativeRoundScores" );
3738 
3739  level.allowHitMarkers = GetGametypeSetting( "allowhitmarkers" );
3740  level.playerQueuedRespawn = GetGametypeSetting( "playerQueuedRespawn" );
3741  level.playerForceRespawn = GetGametypeSetting( "playerForceRespawn" );
3742 
3743  level.roundStartExplosiveDelay = GetGametypeSetting( "roundStartExplosiveDelay" );
3744  level.roundStartKillstreakDelay = GetGametypeSetting( "roundStartKillstreakDelay" );
3745 
3746  level.perksEnabled = GetGametypeSetting( "perksEnabled" );
3747  level.disableAttachments = GetGametypeSetting( "disableAttachments" );
3748  level.disableTacInsert = GetGametypeSetting( "disableTacInsert" );
3749  level.disableCAC = GetGametypeSetting( "disableCAC" );
3750  level.disableClassSelection = GetGametypeSetting( "disableClassSelection" );
3751  level.disableWeaponDrop = GetGametypeSetting( "disableweapondrop" );
3752  level.onlyHeadShots = GetGametypeSetting( "onlyHeadshots" );
3753 
3754  // set to 0 to disable
3755  level.minimumAllowedTeamKills = GetGametypeSetting( "teamKillPunishCount" ) - 1;
3756  level.teamKillReducedPenalty = GetGametypeSetting( "teamKillReducedPenalty" );
3757  level.teamKillPointLoss = GetGametypeSetting( "teamKillPointLoss" );
3758  level.teamKillSpawnDelay = GetGametypeSetting( "teamKillSpawnDelay" );
3759 
3760  level.deathPointLoss = GetGametypeSetting( "deathPointLoss" );
3761  level.leaderBonus = GetGametypeSetting( "leaderBonus" );
3762  level.forceRadar = GetGametypeSetting( "forceRadar" );
3763  level.playerSprintTime = GetGametypeSetting( "playerSprintTime" );
3764  level.bulletDamageScalar = GetGametypeSetting( "bulletDamageScalar" );
3765 
3766  level.playerMaxHealth = GetGametypeSetting( "playerMaxHealth" );
3767  level.playerHealthRegenTime = GetGametypeSetting( "playerHealthRegenTime" );
3768  level.scoreResetOnDeath = GetGametypeSetting( "scoreResetOnDeath" );
3769 
3770  level.playerRespawnDelay = GetGametypeSetting( "playerRespawnDelay" );
3771  level.playerIncrementalRespawnDelay = GetGametypeSetting( "incrementalSpawnDelay" );
3772 
3773  level.playerObjectiveHeldRespawnDelay = GetGametypeSetting( "playerObjectiveHeldRespawnDelay" );
3774  level.waveRespawnDelay = GetGametypeSetting( "waveRespawnDelay" );
3775  level.suicideSpawnDelay = GetGametypeSetting( "spawnsuicidepenalty" );
3776  level.teamKilledSpawnDelay = GetGametypeSetting( "spawnteamkilledpenalty" );
3777  level.maxSuicidesBeforeKick = GetGametypeSetting( "maxsuicidesbeforekick" );
3778 
3779  level.spectateType = GetGametypeSetting( "spectateType" );
3780 
3781  level.voip = SpawnStruct();
3782  level.voip.deadChatWithDead = GetGametypeSetting( "voipDeadChatWithDead" );
3783  level.voip.deadChatWithTeam = GetGametypeSetting( "voipDeadChatWithTeam" );
3784  level.voip.deadHearAllLiving = GetGametypeSetting( "voipDeadHearAllLiving" );
3785  level.voip.deadHearTeamLiving = GetGametypeSetting( "voipDeadHearTeamLiving" );
3786  level.voip.everyoneHearsEveryone = GetGametypeSetting( "voipEveryoneHearsEveryone" );
3787  level.voip.deadHearKiller = GetGametypeSetting( "voipDeadHearKiller" );
3788  level.voip.killersHearVictim = GetGametypeSetting( "voipKillersHearVictim" );
3789 
3790  level.droppedTagRespawn = GetGametypeSetting( "droppedTagRespawn" );
3791 
3792  level.disableVehicleSpawners = GetGametypeSetting( "disableVehicleSpawners" );
3793 
3794  if( ‪IS_TRUE( level.droppedTagRespawn ) )
3795  ‪dogtags::init();
3796 
3797  // this will clear out any non game mode entities before the gametype callbacks happen
3799 
3800  ‪callback::callback( #"on_start_gametype" );
3801 
3802  thread ‪hud_message::init();
3803 
3804  foreach( team in level.teams )
3805  {
3806  ‪initTeamVariables( team );
3807  }
3808 
3809  if ( !level.teambased )
3810  {
3811  ‪initTeamVariables( "free" );
3812  }
3813 
3814  level.maxPlayerCount = 0;
3815  level.activePlayers = [];
3816 
3817  level.aliveTimeMaxCount = 3;
3818  level.aliveTimesAverage = [];
3819  foreach( team in level.teams )
3820  {
3821  level.aliveTimesAverage[team] = 0;
3822  }
3823 
3824  if( !isdefined( level.livesDoNotReset ) || !level.livesDoNotReset )
3825  {
3826  foreach( team in level.teams )
3827  {
3828  game[team+"_lives"] = level.numTeamLives;
3829  }
3830  }
3831 
3832  level.allowAnnouncer = GetGametypeSetting( "allowAnnouncer" );
3833 
3834  if ( !isdefined( level.timeLimit ) )
3835  ‪util::registerTimeLimit( 1, 1440 );
3836 
3837  if ( !isdefined( level.scoreLimit ) )
3838  ‪util::registerScoreLimit( 1, 500 );
3839 
3840  if ( !isdefined( level.roundScoreLimit ) )
3842 
3843  if ( !isdefined( level.roundLimit ) )
3844  ‪util::registerRoundLimit( 0, 10 );
3845 
3846  if ( !isdefined( level.roundWinLimit ) )
3848 
3849  // The order the following functions are registered in are the order they will get called
3851 
3852  //makeDvarServerInfo( "ui_scorelimit" );
3853  //makeDvarServerInfo( "ui_timelimit" );
3854  //makeDvarServerInfo( "ui_allow_classchange", GetDvarString( "ui_allow_classchange" ) );
3855 
3856  waveDelay = level.waveRespawnDelay;
3857  if ( waveDelay )
3858  {
3859  foreach ( team in level.teams )
3860  {
3861  level.waveDelay[team] = waveDelay;
3862  level.lastWave[team] = 0;
3863  }
3864 
3865  level thread [[level.waveSpawnTimer]]();
3866  }
3867 
3868  level.inPrematchPeriod = true;
3869 
3870  if ( level.prematchPeriod > 2.0 && level.rankedMatch )
3871  level.prematchPeriod = level.prematchPeriod + (randomFloat( 4 ) - 2); // live host obfuscation
3872 
3873  if ( level.numLives || ‪anyTeamHasWaveDelay() || level.playerQueuedRespawn )
3874  level.gracePeriod = 15;
3875  else
3876  level.gracePeriod = 5;
3877 
3878  level.inGracePeriod = true;
3879 
3880  level.roundEndDelay = 5;
3881  level.halftimeRoundEndDelay = 3;
3882 
3884 
3885  level.killstreaksenabled = 1;
3886  level.missileLockPlaySpaceCheckEnabled = true;
3887  level.missileLockPlaySpaceCheckExtraRadius = 5000;
3888 
3889  if ( GetDvarString( "scr_game_rankenabled" ) == "" )
3890  SetDvar( "scr_game_rankenabled", true );
3891  level.rankEnabled = GetDvarint( "scr_game_rankenabled" );
3892 
3893  if ( GetDvarString( "scr_game_medalsenabled" ) == "" )
3894  SetDvar( "scr_game_medalsenabled", true );
3895  level.medalsEnabled = GetDvarint( "scr_game_medalsenabled" );
3896 
3897  if( level.hardcoreMode && level.rankedMatch && GetDvarString( "scr_game_friendlyFireDelay" ) == "" )
3898  SetDvar( "scr_game_friendlyFireDelay", true );
3899  level.friendlyFireDelay = GetDvarint( "scr_game_friendlyFireDelay" );
3900 
3901  // level gametype and features globals should be defaulted before this, and level.onstartgametype should reset them if desired
3902  [[level.onStartGameType]]();
3903 
3904  // disable killstreaks for custom game modes
3905  if( GetDvarInt( "custom_killstreak_mode" ) == 1 )
3906  {
3907  level.killstreaksenabled = 0;
3908  }
3909 
3910  level thread ‪killcam::do_final_killcam();
3911 
3912  thread ‪startGame();
3913  level thread ‪updateGameTypeDvars();
3914  level thread simple_hostmigration::UpdateHostMigrationData();
3915 }
3916 
3917 function ‪registerFriendlyFireDelay( dvarString, defaultValue, minValue, maxValue )
3918 {
3919  dvarString = ("scr_" + dvarString + "_friendlyFireDelayTime");
3920  if ( GetDvarString( dvarString ) == "" )
3921  SetDvar( dvarString, defaultValue );
3922 
3923  if ( getDvarInt( dvarString ) > maxValue )
3924  SetDvar( dvarString, maxValue );
3925  else if ( getDvarInt( dvarString ) < minValue )
3926  SetDvar( dvarString, minValue );
3927 
3928  level.friendlyFireDelayTime = getDvarInt( dvarString );
3929 }
3930 
3932 {
3933  if ( !isdefined( level.roundSwitch ) || !level.roundSwitch )
3934  return false;
3935  if ( !isdefined( level.onRoundSwitch ) )
3936  return false;
3937 
3938  assert( game["roundsplayed"] > 0 );
3939 
3940  if ( game["roundsplayed"] % level.roundswitch == 0 )
3941  {
3942  [[level.onRoundSwitch]]();
3943  return true;
3944  }
3945 
3946  return false;
3947 }
3948 
3949 
3951 {
3952  self waittill( "host_sucks_end_game" );
3953  //if ( level.console )
3954  // endparty();
3955  level.skipVote = true;
3956 
3957  if ( !level.gameEnded )
3958  level thread ‪globallogic::forceEnd(true);
3959 }
3960 
3961 
3962 function ‪getKillStreaks( player )
3963 {
3964  for ( killstreakNum = 0; killstreakNum < level.maxKillstreaks; killstreakNum++ )
3965  {
3966  killstreak[ killstreakNum ] = "killstreak_null";
3967  }
3968 
3969  if ( isPlayer( player ) &&
3970  level.disableClassSelection != 1 &&
3971  !isdefined( player.pers["isBot"] ) &&
3972  isdefined( player.killstreak) )
3973  {
3974  currentKillstreak = 0;
3975  for ( killstreakNum = 0; killstreakNum < level.maxKillstreaks; killstreakNum++ )
3976  {
3977  if ( isdefined( player.killstreak[ killstreakNum ] ) )
3978  {
3979  killstreak[ currentKillstreak ] = player.killstreak[ killstreakNum ];
3980  currentKillstreak++;
3981  }
3982  }
3983  }
3984 
3985  return killstreak;
3986 }
3987 
3988 function ‪updateRankedMatch(winner)
3989 {
3990  if ( level.rankedMatch )
3991  {
3992  if ( ‪hostIdledOut() )
3993  {
3994  level.hostForcedEnd = true;
3995  /#print( "host idled out" );#/
3996  endLobby();
3997  }
3998  }
4000 }
4001 
4002 
4003 function ‪annihilatorGunPlayerKillEffect( attacker, weapon )
4004 {
4005  if ( weapon.fusetime != 0 )
4006  wait( weapon.fusetime * 0.001 );
4007  else
4008  wait(0.45);
4009 
4010  if ( !isdefined( self ) )
4011  {
4012  return;
4013  }
4014 
4015  self playsoundtoplayer( "evt_annihilation", attacker );
4016  self playsoundtoallbutplayer( "evt_annihilation_npc", attacker );
4017 
4018  CodeSetClientField(self, "annihilate_effect", 1);
4019  self ‪shake_and_rumble(0, 0.3, 0.75, 1);
4020 
4021  wait 0.1;
4022 
4023  if ( !isdefined( self ) )
4024  {
4025  return;
4026  }
4027 
4028  self NotSolid();
4029  self Ghost();
4030 }
4031 
4032 function ‪annihilatorGunActorKillEffect( attacker, weapon )
4033 {
4034  self waittill("actor_corpse",body); //now a corpse!
4035 
4036  if ( weapon.fusetime != 0 )
4037  wait( weapon.fusetime * 0.001 );
4038  else
4039  wait(0.45);
4040 
4041  if ( !isdefined( self ) )
4042  {
4043  return;
4044  }
4045 
4046  self playsoundtoplayer( "evt_annihilation", attacker );
4047  self playsoundtoallbutplayer( "evt_annihilation_npc", attacker );
4048 
4049  if ( !isdefined( body ) )
4050  {
4051  return;
4052  }
4053 
4054  CodeSetClientField(body, "annihilate_effect", 1);
4055  body ‪shake_and_rumble(0, 0.6, 0.2, 1);
4056  body NotSolid();
4057  body Ghost();
4058 }
4059 
4061 {
4062  wait 0.1;
4063 
4064  if ( !isdefined( self ) )
4065  {
4066  return;
4067  }
4068 
4069  playsoundatposition ("evt_annihilation_npc", (self.origin));
4070  CodeSetClientField(self, "pineapplegun_effect", 1);
4071  self ‪shake_and_rumble(0, 0.3, 0.35, 1);
4072  wait 0.1;
4073 
4074  if ( !isdefined( self ) )
4075  {
4076  return;
4077  }
4078 
4079  self NotSolid();
4080  self Ghost();
4081 }
4082 
4084 {
4085  wait 0.05;
4086  if ( !isdefined( self ) )
4087  {
4088  return;
4089  }
4090 
4091  playsoundatposition ("evt_annihilation_npc", (self.origin));
4092  CodeSetClientField(self, "annihilate_effect", 1);
4093  self ‪shake_and_rumble(0, 0.3, 0.35, 1);
4094 
4095  if ( !isdefined( self ) )
4096  {
4097  return;
4098  }
4099 
4100  self NotSolid();
4101  self Ghost();
4102 }
4103 
4105 {
4106  self waittill("actor_corpse",body); //now a corpse!
4107  wait(0.75);
4108 
4109  if ( !isdefined( self ) )
4110  {
4111  return;
4112  }
4113 
4114  playsoundatposition ("evt_annihilation_npc", (self.origin));
4115 
4116  if ( !isdefined( body ) )
4117  {
4118  return;
4119  }
4120 
4121  CodeSetClientField(body, "pineapplegun_effect", 1);
4122  body ‪shake_and_rumble(0, 0.3, 0.75, 1);
4123  body NotSolid();
4124  body Ghost();
4125 }
4126 
4127 // ============================================================================
4128 // self = player
4129 function ‪shake_and_rumble( n_delay, shake_size, shake_time, rumble_num )
4130 {
4131  if( IsDefined(n_delay) && (n_delay > 0) )
4132  {
4133  wait( n_delay );
4134  }
4135 
4136  // Earthquake
4137  nMagnitude = shake_size;
4138  nduration = shake_time;
4139  nRadius = 500;
4140  v_pos = self.origin;
4141  Earthquake( nMagnitude, nDuration, v_pos, nRadius );
4142 
4143  // Pad Rumble
4144  for( i=0; i<rumble_num; i++ )
4145  {
4146  self PlayRumbleOnEntity( "damage_heavy" );
4147  wait( 0.1 );
4148  }
4149 }
4150 
4151 function ‪DoWeaponSpecificKillEffects(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
4152 {
4153  if( weapon.name=="hero_pineapplegun" && isPlayer( attacker ) && sMeansOfDeath == "MOD_GRENADE" )
4154  {
4155  attacker playLocalSound( "wpn_pineapple_grenade_explode_flesh_2D" );
4156  }
4157 }
4158 
4159 #define ANNIHILATE_PUSH_SCALE 100
4160 #define ANNIHILATE_UPPUSH_SCALE 25
4161 function ‪DoWeaponSpecificCorpseEffects(body, eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
4162 {
4163  if ( weapon.doannihilate&& isPlayer( attacker ) && ( sMeansOfDeath == "MOD_IMPACT" || sMeansOfDeath == "MOD_GRENADE" ) ) //this does the annihilation effect and launches ragdoll
4164  {
4165  if (IsActor(body))
4166  {
4167  body thread ‪annihilatorGunActorKillEffect( attacker, weapon );
4168  }
4169  else
4170  {
4171  body thread ‪annihilatorGunPlayerKillEffect( attacker, weapon );
4172  }
4173  }
4174  else if( sMeansOfDeath == "MOD_BURNED" )
4175  {
4176  if( !IsActor(body) )
4177  {
4178  body thread ‪BurnCorpse();
4179  }
4180  }
4181  else if( weapon.isheroweapon == 1 && isPlayer( attacker ) )
4182  {
4183  /*if (weapon.name == "hero_pineapplegun" && sMeansOfDeath == "MOD_GRENADE") //this does an annilhation effect and launches ragdoll
4184  {
4185  //modify the launch direction to give it some up vector - John Woo style
4186  newVector = ((0,0,1)*ANNIHILATE_UPPUSH_SCALE) + (vDir * ANNIHILATE_PUSH_SCALE);
4187  body LaunchRagdoll( newVector, sHitLoc);
4188  if (IsActor(body))
4189  {
4190  body thread pineappleGunActorKillEffect();
4191  }
4192  else
4193  {
4194  body thread pineappleGunPlayerKillEffect();
4195  }
4196  }
4197  */
4198  if ( weapon.name == "hero_firefly_swarm" )
4199  {
4200  value = RandomInt(2) + 1;
4201  if( !IsActor(body) )
4202  {
4203  CodeSetClientField(body, "firefly_effect", value);
4204  }
4205  }
4206  }
4207 }
4208 
4209 #define CORPSE_BURN_DURATION 3
4210 function ‪BurnCorpse()
4211 {
4212  self endon( "death" );
4213  CodeSetClientField( self, "burned_effect", 1 );
4214  wait( ‪CORPSE_BURN_DURATION );
4215  CodeSetClientField( self, "burned_effect", 0 );
4216 }
‪endGame
‪function endGame(winner, endReasonText)
Definition: _globallogic.gsc:1950
‪hideOutcomeUIForAllPlayers
‪function hideOutcomeUIForAllPlayers()
Definition: _globallogic.gsc:1738
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪SetupCallbacks
‪function SetupCallbacks()
Definition: _globallogic.gsc:256
‪getRoundTimePlayed
‪function getRoundTimePlayed(roundLength)
Definition: _globallogic.gsc:2403
‪startTime
‪class AnimationAdjustmentInfoZ startTime
‪activate
‪function activate()
Definition: traps_shared.gsc:655
‪updateAllTeamScores
‪function updateAllTeamScores()
Definition: _globallogic_score.gsc:849
‪setvisiblescoreboardcolumns
‪function setvisiblescoreboardcolumns(col1, col2, col3, col4, col5)
Definition: _globallogic.gsc:545
‪shake_and_rumble
‪function shake_and_rumble(n_delay, shake_size, shake_time, rumble_num)
Definition: _globallogic.gsc:4129
‪anyTeamHasWaveDelay
‪function anyTeamHasWaveDelay()
Definition: _globallogic.gsc:3535
‪annihilatorGunPlayerKillEffect
‪function annihilatorGunPlayerKillEffect(attacker, weapon)
Definition: _globallogic.gsc:4003
‪updateAliveTimes
‪function updateAliveTimes(team)
Definition: _globallogic.gsc:3031
‪announce_round_winner
‪function announce_round_winner(winner, delay)
Definition: _globallogic_audio.gsc:103
‪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
‪GAMEMODE_PRIVATE_MATCH
‪#define GAMEMODE_PRIVATE_MATCH
Definition: shared.gsh:11
‪GAMEMODE_LEAGUE_MATCH
‪#define GAMEMODE_LEAGUE_MATCH
Definition: shared.gsh:15
‪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
‪default_onRoundScoreLimit
‪function default_onRoundScoreLimit()
Definition: _globallogic_defaults.gsc:266
‪prematchPeriod
‪function prematchPeriod()
Definition: _globallogic.gsc:3434
‪updatePlacement
‪function updatePlacement()
Definition: _globallogic.gsc:2692
‪is_bot
‪function is_bot()
Definition: util_shared.gsc:2488
‪registerRoundWinLimit
‪function registerRoundWinLimit(minValue, maxValue)
Definition: _util.gsc:630
‪totalAliveCount
‪function totalAliveCount()
Definition: _globallogic.gsc:2862
‪updateWinLossStats
‪function updateWinLossStats(winner)
Definition: _globallogic_score.gsc:1217
‪MPINTRO_VISIONSET_ALIAS
‪#define MPINTRO_VISIONSET_ALIAS
Definition: _globallogic.gsh:1
‪gameHistoryPlayerQuit
‪function gameHistoryPlayerQuit()
Definition: _globallogic.gsc:1423
‪compareTeamByTeamScore
‪function compareTeamByTeamScore(teamA, teamB, previous_winner_score)
Definition: _globallogic.gsc:597
‪figure_out_friendly_fire
‪function figure_out_friendly_fire(victim)
Definition: _globallogic_player.gsc:1614
‪updateGameEvents
‪function updateGameEvents()
Definition: _globallogic.gsc:929
‪mpintro_visionset_ramp_hold_func
‪function mpintro_visionset_ramp_hold_func()
Definition: _globallogic.gsc:990
‪hitScoreLimit
‪function hitScoreLimit()
Definition: util_shared.gsc:3650
‪any_team_hit_round_score_limit
‪function any_team_hit_round_score_limit()
Definition: util_shared.gsc:3680
‪get_round_switch_dialog
‪function get_round_switch_dialog(switchType)
Definition: _globallogic_audio.gsc:859
‪set_state_active
‪function set_state_active(player, lerp)
Definition: visionset_mgr_shared.gsc:113
‪setTopTeamStats
‪function setTopTeamStats(team)
Definition: _globallogic.gsc:1850
‪default_onTimeLimit
‪function default_onTimeLimit()
Definition: _globallogic_defaults.gsc:206
‪setClientSysState
‪function setClientSysState(sSysName, sSysState, player)
Definition: util_shared.gsc:1369
‪set_after_action_report_stat
‪function set_after_action_report_stat(statName, value, index)
Definition: persistence_shared.gsc:404
‪isTopScoringPlayer
‪function isTopScoringPlayer(player)
Definition: _globallogic.gsc:2783
‪VERSION_TU5
‪#define VERSION_TU5
Definition: version.gsh:47
‪executePostRoundEvents
‪function executePostRoundEvents()
Definition: _globallogic_utils.gsc:122
‪killserverPc
‪function killserverPc()
Definition: _globallogic.gsc:690
‪RecordPlayStyleInformation
‪function RecordPlayStyleInformation()
Definition: _globallogic.gsc:1188
‪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
‪GESTURE_TYPE_GOOD_GAME
‪#define GESTURE_TYPE_GOOD_GAME
Definition: _globallogic.gsc:83
‪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
‪prematchWaitingForPlayers
‪function prematchWaitingForPlayers()
Definition: _globallogic.gsc:3425
‪default_onRoundEndGame
‪function default_onRoundEndGame(winner)
Definition: _globallogic_defaults.gsc:143
‪getTeamScoreRatio
‪function getTeamScoreRatio()
Definition: _globallogic.gsc:1129
‪hitRoundScoreLimit
‪function hitRoundScoreLimit()
Definition: util_shared.gsc:3694
‪on_joined_team
‪function on_joined_team()
Definition: _battlechatter.gsc:133
‪gracePeriod
‪function gracePeriod()
Definition: _globallogic.gsc:3471
‪recordEndGameComScoreEventForPlayer
‪function recordEndGameComScoreEventForPlayer(player, result)
Definition: _globallogic_player.gsc:110
‪showcaseweapon_get
‪function showcaseweapon_get()
Definition: _weapons.gsc:131
‪getBaseWeaponParam
‪function getBaseWeaponParam(weapon)
Definition: _weapon_utils.gsc:7
‪roundEnd
‪function roundEnd(winner)
Definition: challenges_shared.gsc:672
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪checkForForfeit
‪function checkForForfeit()
Definition: _globallogic.gsc:761
‪spawnPlayer
‪function spawnPlayer()
Definition: _globallogic_spawn.gsc:227
‪setup_callbacks
‪function setup_callbacks()
Definition: _globallogic.gsc:337
‪isOnlyOneLeftAliveOnTeam
‪function isOnlyOneLeftAliveOnTeam(team)
Definition: _globallogic.gsc:896
‪get_current_round_score_limit
‪function get_current_round_score_limit()
Definition: util_shared.gsc:3675
‪match_end
‪function match_end(winner)
Definition: _arena.gsc:63
‪maySpawn
‪function maySpawn()
Definition: _globallogic_spawn.gsc:93
‪BowPlayerKillEffect
‪function BowPlayerKillEffect()
Definition: _globallogic.gsc:4083
‪resetPlayerScoreChainAndMomentum
‪function resetPlayerScoreChainAndMomentum(player)
Definition: _globallogic_score.gsc:310
‪teamOutcomeNotify
‪function teamOutcomeNotify(winner, endType, endReasonText)
Definition: _hud_message.gsc:80
‪registerFriendlyFireDelay
‪function registerFriendlyFireDelay(dvarString, defaultValue, minValue, maxValue)
Definition: _globallogic.gsc:3917
‪freezePlayerForRoundEnd
‪function freezePlayerForRoundEnd()
Definition: _globallogic_player.gsc:81
‪updateRankedMatch
‪function updateRankedMatch(winner)
Definition: _globallogic.gsc:3988
‪freeze_player_controls
‪function freeze_player_controls(b_frozen=true)
Definition: util_shared.gsc:2474
‪MPINTRO_VISIONSET_RAMP_IN
‪#define MPINTRO_VISIONSET_RAMP_IN
Definition: _globallogic.gsh:5
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪announce_game_winner
‪function announce_game_winner(winner)
Definition: _globallogic_audio.gsc:133
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪gameHistoryPlayerKicked
‪function gameHistoryPlayerKicked()
Definition: _globallogic.gsc:1394
‪default_onScoreLimit
‪function default_onScoreLimit()
Definition: _globallogic_defaults.gsc:234
‪waveSpawnTimer
‪function waveSpawnTimer()
Definition: _globallogic.gsc:1091
‪displayGameEnd
‪function displayGameEnd(winner, endReasonText)
Definition: _globallogic.gsc:1580
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪registerOtherLootXPAwards
‪function registerOtherLootXPAwards(func)
Definition: _globallogic.gsc:1919
‪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
‪delay
‪function delay(time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: util_shared.csc:784
‪updateAllAliveTimes
‪function updateAllAliveTimes()
Definition: _globallogic.gsc:3094
‪annihilatorGunActorKillEffect
‪function annihilatorGunActorKillEffect(attacker, weapon)
Definition: _globallogic.gsc:4032
‪doEndGameSequence
‪function doEndGameSequence()
Definition: _globallogic.gsc:2354
‪post_round_final_killcam
‪function post_round_final_killcam()
Definition: _killcam.gsc:139
‪timeLimitClock_Intermission
‪function timeLimitClock_Intermission(waitTime)
Definition: _globallogic.gsc:3201
‪compareTeamByGameStat
‪function compareTeamByGameStat(gameStat, teamA, teamB, previous_winner_score)
Definition: _globallogic.gsc:557
‪notifyTeamWaveSpawn
‪function notifyTeamWaveSpawn(team, time)
Definition: _globallogic.gsc:1081
‪awardLootXPToPlayers
‪function awardLootXPToPlayers(delay, players)
Definition: _globallogic.gsc:2232
‪update_top_scorers
‪function update_top_scorers(winner)
Definition: _globallogic.gsc:2254
‪wasLastRound
‪function wasLastRound()
Definition: util_shared.gsc:3521
‪checkTimeLimit
‪function checkTimeLimit()
Definition: _globallogic.gsc:2474
‪getRoundsPlayed
‪function getRoundsPlayed()
Definition: util_shared.gsc:3737
‪GESTURE_TYPE_BOAST
‪#define GESTURE_TYPE_BOAST
Definition: _globallogic.gsc:85
‪checkRoundScoreLimit
‪function checkRoundScoreLimit()
Definition: _globallogic.gsc:2579
‪setMatchScoreHUDElemForTeam
‪function setMatchScoreHUDElemForTeam(team)
Definition: ctf.gsc:348
‪VERSION_TU1
‪#define VERSION_TU1
Definition: version.gsh:39
‪awardLootXP
‪function awardLootXP()
Definition: _globallogic.gsc:1904
‪getEstimatedTimeUntilScoreLimit
‪function getEstimatedTimeUntilScoreLimit(team)
Definition: _globallogic_utils.gsc:353
‪sendAfterActionReport
‪function sendAfterActionReport()
Definition: _globallogic.gsc:1242
‪totalPlayerLives
‪function totalPlayerLives()
Definition: _globallogic.gsc:2872
‪registerPostRoundEvent
‪function registerPostRoundEvent(eventFunc)
Definition: _globallogic_utils.gsc:114
‪getEndReasonText
‪function getEndReasonText()
Definition: _globallogic.gsc:1704
‪IncrementMatchCompletionStat
‪function IncrementMatchCompletionStat(gameMode, playedOrHosted, stat)
Definition: _globallogic.gsc:1119
‪BurnCorpse
‪function BurnCorpse()
Definition: _globallogic.gsc:4210
‪MPINTRO_VISIONSET_RAMP_NOTIFY
‪#define MPINTRO_VISIONSET_RAMP_NOTIFY
Definition: _globallogic.gsh:8
‪Callback_StartGameType
‪function Callback_StartGameType()
Definition: _globallogic.gsc:3546
‪figure_out_attacker
‪function figure_out_attacker(eAttacker)
Definition: _globallogic_player.gsc:1557
‪do_final_killcam
‪function do_final_killcam()
Definition: _killcam.gsc:150
‪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
‪default_getTeamKillPenalty
‪function default_getTeamKillPenalty(eInflictor, attacker, sMeansOfDeath, weapon)
Definition: _globallogic_defaults.gsc:337
‪DEFAULT
‪#define DEFAULT(__var, __default)
Definition: shared.gsh:270
‪awardOtherLootXP
‪function awardOtherLootXP()
Definition: _globallogic.gsc:1927
‪registerDvars
‪function registerDvars()
Definition: _globallogic.gsc:295
‪updateTeamStatus
‪function updateTeamStatus()
Definition: _globallogic.gsc:2920
‪GetCurrentGameMode
‪function GetCurrentGameMode()
Definition: util_shared.gsc:3750
‪updateMatchBonusScores
‪function updateMatchBonusScores(winner)
Definition: _globallogic_score.gsc:40
‪_setPlayerScore
‪function _setPlayerScore(player, score)
Definition: _globallogic_score.gsc:519
‪DoWeaponSpecificKillEffects
‪function DoWeaponSpecificKillEffects(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _globallogic.gsc:4151
‪play_movie
‪function play_movie(str_movie, str_type, show_black_screen=false, b_looping=false, str_key="")
Definition: lui_shared.gsc:220
‪TAUNT_TYPE_FIRST_PLACE
‪#define TAUNT_TYPE_FIRST_PLACE
Definition: _globallogic.gsc:81
‪mpintro_visionset_activate_func
‪function mpintro_visionset_activate_func()
Definition: _globallogic.gsc:1005
‪_getPlayerScore
‪function _getPlayerScore(player)
Definition: _globallogic_score.gsc:538
‪init
‪function init()
Definition: _globallogic.gsc:141
‪WAIT_TIME_BEFORE_AWARDING_LOOT_XP
‪#define WAIT_TIME_BEFORE_AWARDING_LOOT_XP
Definition: _globallogic.gsc:89
‪getTimePassed
‪function getTimePassed()
Definition: _globallogic_utils.gsc:274
‪dog_manager_get_dogs
‪function dog_manager_get_dogs()
Definition: _dogs.gsc:625
‪flush_dialog
‪function flush_dialog()
Definition: _globallogic_audio.gsc:160
‪precache_mp_custom_leaderboards
‪function precache_mp_custom_leaderboards()
Definition: _globallogic.gsc:517
‪totalPlayerCount
‪function totalPlayerCount()
Definition: util_shared.gsc:3482
‪gameTimer
‪function gameTimer()
Definition: _globallogic_utils.gsc:196
‪figureOutWinningTeam
‪function figureOutWinningTeam(winner)
Definition: _globallogic.gsc:1877
‪determineTeamWinnerByTeamScore
‪function determineTeamWinnerByTeamScore()
Definition: _globallogic.gsc:624
‪bbPlayerMatchEnd
‪function bbPlayerMatchEnd(gameLength, endReasonString, gameOver)
Definition: _globallogic.gsc:2417
‪Finalize
‪function Finalize()
Definition: _behavior_tracker.gsc:56
‪record_misc_player_stats
‪function record_misc_player_stats()
Definition: _globallogic_player.gsc:1228
‪sndSetMatchSnapshot
‪function sndSetMatchSnapshot(num)
Definition: _globallogic.gsc:1075
‪getNextHighestScore
‪function getNextHighestScore(score)
Definition: _globallogic.gsc:1171
‪isRoundBased
‪function isRoundBased()
Definition: util_shared.gsc:3742
‪updateGameTypeDvars
‪function updateGameTypeDvars()
Definition: _globallogic.gsc:2606
‪determineTeamWinnerByGameStat
‪function determineTeamWinnerByGameStat(gameStat)
Definition: _globallogic.gsc:578
‪ARRAY_ADD
‪#define ARRAY_ADD(__array, __item)
Definition: shared.gsh:304
‪is_bot_ranked_match
‪function is_bot_ranked_match()
Definition: _bot.gsc:80
‪set_music_global
‪function set_music_global(state, wait_time=0, save_state=false, return_state=false)
Definition: _globallogic_audio.gsc:1071
‪notifyEndOfGameplay
‪function notifyEndOfGameplay()
Definition: _globallogic.gsc:1064
‪hostIdledOut
‪function hostIdledOut()
Definition: _globallogic.gsc:1108
‪atLeastTwoTeams
‪function atLeastTwoTeams()
Definition: _globallogic.gsc:728
‪precache_mp_public_leaderboards
‪function precache_mp_public_leaderboards()
Definition: _globallogic.gsc:469
‪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
‪setGestureClientField
‪function setGestureClientField(fieldName, gestureType)
Definition: _globallogic.gsc:2341
‪MATCH_FINISHED
‪#define MATCH_FINISHED
Definition: _globallogic.gsc:79
‪update_timings
‪function update_timings(newTime)
Definition: _weapons.gsc:156
‪gameRepUpdateInformationForRound
‪function gameRepUpdateInformationForRound()
Definition: _gamerep.gsc:372
‪logTeamWinString
‪function logTeamWinString(wintype, winner)
Definition: _globallogic_utils.gsc:498
‪default_getTeamKillScore
‪function default_getTeamKillScore(eInflictor, attacker, sMeansOfDeath, weapon)
Definition: _globallogic_defaults.gsc:349
‪givePlayerScore
‪function givePlayerScore(event, player, victim, descValue, weapon)
Definition: _globallogic_score.gsc:431
‪default_onOneLeftEvent
‪function default_onOneLeftEvent(team)
Definition: _globallogic_defaults.gsc:175
‪timeLimitClock
‪function timeLimitClock()
Definition: _globallogic.gsc:3146
‪announcerController
‪function announcerController()
Definition: _globallogic_audio.gsc:880
‪getTeamIndex
‪function getTeamIndex(team)
Definition: _teams.gsc:371
‪gameEnd
‪function gameEnd(winner)
Definition: challenges_shared.gsc:704
‪MATCH_QUIT
‪#define MATCH_QUIT
Definition: _globallogic.gsc:78
‪areAllTeamsDead
‪function areAllTeamsDead()
Definition: _globallogic.gsc:809
‪checkSuddenDeathScoreLimit
‪function checkSuddenDeathScoreLimit(team)
Definition: _globallogic.gsc:2558
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪getPlacementForPlayer
‪function getPlacementForPlayer(player)
Definition: _globallogic.gsc:2765
‪getPlayerByName
‪function getPlayerByName(name)
Definition: _globallogic.gsc:1224
‪getTotalTimePlayed
‪function getTotalTimePlayed(maxLength)
Definition: _globallogic.gsc:2389
‪checkForGestures
‪function checkForGestures(topPlayerIndex)
Definition: _globallogic.gsc:2303
‪checkPlayerScoreLimitSoon
‪function checkPlayerScoreLimitSoon()
Definition: _globallogic.gsc:3124
‪isPrematchRequirementConditionMet
‪function isPrematchRequirementConditionMet(activeTeamCount)
Definition: _globallogic.gsc:3298
‪onSpawnPlayer
‪function onSpawnPlayer(predictedSpawn)
Definition: _spawning.gsc:688
‪DoWeaponSpecificCorpseEffects
‪function DoWeaponSpecificCorpseEffects(body, eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _globallogic.gsc:4161
‪MPINTRO_VISIONSET_PRIORITY
‪#define MPINTRO_VISIONSET_PRIORITY
Definition: _globallogic.gsh:2
‪doSpawnQueueUpdates
‪function doSpawnQueueUpdates()
Definition: _globallogic.gsc:793
‪isTeamAllDead
‪function isTeamAllDead(team)
Definition: _globallogic.gsc:804
‪__init__
‪function __init__()
Definition: _globallogic.gsc:133
‪register_info
‪function register_info(type, name, version, lerp_step_count)
Definition: visionset_mgr_shared.csc:334
‪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
‪sndMusicSetRandomizer
‪function sndMusicSetRandomizer()
Definition: _globallogic_audio.gsc:941
‪getHighestScoringPlayer
‪function getHighestScoringPlayer()
Definition: _globallogic_score.gsc:279
‪record_global_mp_stats_for_player_at_match_end
‪function record_global_mp_stats_for_player_at_match_end()
Definition: _globallogic_player.gsc:1191
‪doOneLeftEventUpdates
‪function doOneLeftEventUpdates()
Definition: _globallogic.gsc:902
‪setTopPlayerStats
‪function setTopPlayerStats()
Definition: _globallogic.gsc:1801
‪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
‪clientNotify
‪function clientNotify(event)
Definition: util_shared.gsc:1416
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪giveTeamScore
‪function giveTeamScore(event, team, player, victim)
Definition: _globallogic_score.gsc:727
‪resetOutcomeForAllPlayers
‪function resetOutcomeForAllPlayers()
Definition: _globallogic.gsc:1728
‪_setTeamScore
‪function _setTeamScore(team, teamScore)
Definition: _globallogic_score.gsc:795
‪main
‪function main()
Definition: _global_fx.csc:17
‪ramp_in_out_thread
‪function ramp_in_out_thread(ramp_in, full_period, ramp_out)
Definition: visionset_mgr_shared.gsc:266
‪any_team_hit_score_limit
‪function any_team_hit_score_limit()
Definition: util_shared.gsc:3638
‪pineappleGunActorKillEffect
‪function pineappleGunActorKillEffect()
Definition: _globallogic.gsc:4104
‪default_onForfeit
‪function default_onForfeit(team)
Definition: _globallogic_defaults.gsc:30
‪getRoundLength
‪function getRoundLength()
Definition: _globallogic.gsc:1888
‪MATCH_KICKED
‪#define MATCH_KICKED
Definition: _globallogic.gsc:77
‪spawnSpectator
‪function spawnSpectator(origin, angles)
Definition: _globallogic_spawn.gsc:532
‪initPerkDvars
‪function initPerkDvars()
Definition: _loadout.gsc:1225
‪can_set_aar_stat
‪function can_set_aar_stat()
Definition: persistence_shared.gsc:383
‪default_getTimeLimit
‪function default_getTimeLimit()
Definition: _globallogic_defaults.gsc:332
‪set_player_uimodel
‪function set_player_uimodel(str_field_name, n_value)
Definition: clientfield_shared.gsc:75
‪precache_mp_friend_leaderboards
‪function precache_mp_friend_leaderboards()
Definition: _globallogic.gsc:404
‪checkTeamScoreLimitSoon
‪function checkTeamScoreLimitSoon(team)
Definition: _globallogic.gsc:3102
‪exit_level
‪function exit_level()
Definition: _globallogic.gsc:2245
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪WaitAndUploadStats
‪function WaitAndUploadStats(player, waitTime)
Definition: _globallogic.gsc:1909
‪startGame
‪function startGame()
Definition: _globallogic.gsc:3235
‪record_special_move_data_for_life
‪function record_special_move_data_for_life(killer)
Definition: _globallogic_player.gsc:413
‪mpintro_visionset_deactivate_func
‪function mpintro_visionset_deactivate_func()
Definition: _globallogic.gsc:1010
‪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
‪gameRepAnalyzeAndReport
‪function gameRepAnalyzeAndReport()
Definition: _gamerep.gsc:386
‪displayRoundEnd
‪function displayRoundEnd(winner, endReasonText)
Definition: _globallogic.gsc:1455
‪clamp
‪function clamp(val, val_min, val_max)
Definition: math_shared.csc:16
‪recordEndGameComScoreEvent
‪function recordEndGameComScoreEvent(result)
Definition: _globallogic.gsc:1695
‪get_killstreak_usage
‪function get_killstreak_usage(usageKey)
Definition: _killstreaks.gsc:2172
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪spawnIntermission
‪function spawnIntermission(useDefaultCallback, endGame)
Definition: _globallogic_spawn.gsc:703
‪hitRoundWinLimit
‪function hitRoundWinLimit()
Definition: util_shared.gsc:3609
‪default_determineWinner
‪function default_determineWinner(roundWinner)
Definition: _globallogic_defaults.gsc:149
‪spawnClient
‪function spawnClient(timeAlreadyPassed)
Definition: _globallogic_spawn.gsc:832
‪default_onAliveCountChange
‪function default_onAliveCountChange(team)
Definition: _globallogic_defaults.gsc:139
‪leader_dialog_on_player
‪function leader_dialog_on_player(dialogKey, objectiveKey, killstreakId, dialogBufferKey, introDialog)
Definition: _globallogic_audio.gsc:460
‪_getTeamScore
‪function _getTeamScore(team)
Definition: _globallogic_score.gsc:857
‪CORPSE_BURN_DURATION
‪#define CORPSE_BURN_DURATION
Definition: _globallogic.gsc:4209
‪default_isKillBoosting
‪function default_isKillBoosting()
Definition: _globallogic_score.gsc:1470
‪registerTimeLimit
‪function registerTimeLimit(minValue, maxValue)
Definition: _util.gsc:655
‪name
‪class GroundFx name
‪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
‪MPINTRO_VISIONSET_RAMP_OUT
‪#define MPINTRO_VISIONSET_RAMP_OUT
Definition: _globallogic.gsh:7
‪precache_mp_anticheat_leaderboards
‪function precache_mp_anticheat_leaderboards()
Definition: _globallogic.gsc:435
‪getHighestScore
‪function getHighestScore()
Definition: _globallogic.gsc:1157
‪matchStartTimer
‪function matchStartTimer()
Definition: _globallogic.gsc:1015
‪default_onLastTeamAliveEvent
‪function default_onLastTeamAliveEvent(team)
Definition: _globallogic_defaults.gsc:111
‪getLastTeamAlive
‪function getLastTeamAlive()
Definition: _globallogic.gsc:823
‪checkIfTeamForfeits
‪function checkIfTeamForfeits(team)
Definition: _globallogic.gsc:748
‪MPINTRO_VISIONSET_STEPS
‪#define MPINTRO_VISIONSET_STEPS
Definition: _globallogic.gsh:3
‪checkRoundSwitch
‪function checkRoundSwitch()
Definition: _globallogic.gsc:3931
‪spawnPlayerPrediction
‪function spawnPlayerPrediction()
Definition: _globallogic_spawn.gsc:162
‪GESTURE_TYPE_MAX
‪#define GESTURE_TYPE_MAX
Definition: _globallogic.gsc:86
‪recordBreadcrumbData
‪function recordBreadcrumbData()
Definition: _globallogic.gsc:3215
‪roundEndDOF
‪function roundEndDOF(time)
Definition: _globallogic.gsc:2468
‪sndMusicFunctions
‪function sndMusicFunctions()
Definition: _globallogic_audio.gsc:934
‪startNextRound
‪function startNextRound(winner, endReasonText)
Definition: _globallogic.gsc:1748
‪pineappleGunPlayerKillEffect
‪function pineappleGunPlayerKillEffect(attacker)
Definition: _globallogic.gsc:4060
‪registerRoundScoreLimit
‪function registerRoundScoreLimit(minValue, maxValue)
Definition: _util.gsc:647
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265
‪GESTURE_TYPE_THREATEN
‪#define GESTURE_TYPE_THREATEN
Definition: _globallogic.gsc:84
‪UpdateAndFinalizeMatchRecord
‪function UpdateAndFinalizeMatchRecord()
Definition: _globallogic.gsc:1318