Advertisement
Guest User

Untitled

a guest
Sep 28th, 2016
62
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 109.90 KB | None | 0 0
  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 );
  136. visionset_mgr::register_info( "visionset", MPINTRO_VISIONSET_ALIAS, VERSION_SHIP, level.vsmgr_prio_visionset_mpintro, MPINTRO_VISIONSET_STEPS, false, &visionset_mgr::ramp_in_out_thread, false );
  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.  
  242. globallogic_ui::init();
  243.  
  244. registerDvars();
  245. loadout::initPerkDvars();
  246.  
  247. level.oldschool = GetGametypeSetting( "oldschoolMode" );
  248.  
  249. precache_mp_leaderboards();
  250.  
  251. if ( !isdefined( game["tiebreaker"] ) )
  252. game["tiebreaker"] = false;
  253.  
  254. thread gameadvertisement::init();
  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.  
  267. setup_callbacks();
  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.  
  295. function registerDvars()
  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.  
  337. function setup_callbacks()
  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.  
  357. level.onForfeit = &globallogic_defaults::default_onForfeit;
  358. level.onTimeLimit = &globallogic_defaults::default_onTimeLimit;
  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 = []; ///< Array of other CB function pointers
  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.  
  399. callback::on_joined_team( &globallogic_player::on_joined_team );
  400.  
  401. globallogic_ui::SetupCallbacks();
  402. }
  403.  
  404. function precache_mp_friend_leaderboards()
  405. {
  406.  
  407. hardcoreMode = GetGametypeSetting( "hardcoreMode" );
  408. if( !isdefined( hardcoreMode ) )
  409. {
  410. hardcoreMode = false;
  411. }
  412.  
  413. arenaMode = IsArenaMode();
  414.  
  415. /////////////////////////////////////////////////////////
  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
  435. function precache_mp_anticheat_leaderboards()
  436. {
  437.  
  438. hardcoreMode = GetGametypeSetting( "hardcoreMode" );
  439. if( !isdefined( hardcoreMode ) )
  440. {
  441. hardcoreMode = false;
  442. }
  443.  
  444. arenaMode = IsArenaMode();
  445.  
  446. /////////////////////////////////////////////////////////
  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.  
  469. function precache_mp_public_leaderboards()
  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.  
  482. /////////////////////////////////////////////////////////
  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.  
  517. function precache_mp_custom_leaderboards()
  518. {
  519. customLeaderboards = "LB_MP_CG_" + level.gametype;
  520.  
  521. precacheLeaderboards( "LB_MP_CG_GENERAL " + customLeaderboards );
  522.  
  523. return;
  524. }
  525.  
  526. function precache_mp_leaderboards()
  527. {
  528. if( bot::is_bot_ranked_match() )
  529. {
  530. return;
  531. }
  532.  
  533. if( level.rankedMatch || level.gametype == "fr" )
  534. {
  535. precache_mp_public_leaderboards();
  536. precache_mp_friend_leaderboards();
  537. precache_mp_anticheat_leaderboards();
  538. }
  539. else
  540. {
  541. precache_mp_custom_leaderboards();
  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.  
  578. function determineTeamWinnerByGameStat( gameStat )
  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.  
  624. function determineTeamWinnerByTeamScore( )
  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. {
  660. winner = globallogic_score::getHighestScoringPlayer();
  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. {
  704. winner = globallogic_score::getHighestScoringPlayer();
  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.  
  728. function atLeastTwoTeams()
  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.  
  761. function checkForForfeit()
  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.  
  793. function doSpawnQueueUpdates()
  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.  
  809. function areAllTeamsDead( )
  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.  
  823. function getLastTeamAlive()
  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.  
  850. function doDeadEventUpdates()
  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.  
  896. function isOnlyOneLeftAliveOnTeam( team )
  897. {
  898. return (level.lastAliveCount[team] > 1 && level.aliveCount[team] == 1 && level.playerLives[team] == 1 );
  899. }
  900.  
  901.  
  902. function doOneLeftEventUpdates()
  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.  
  929. function updateGameEvents()
  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. {
  980. doSpawnQueueUpdates();
  981. }
  982.  
  983. if ( doDeadEventUpdates() )
  984. return;
  985.  
  986. if ( doOneLeftEventUpdates() )
  987. return;
  988. }
  989.  
  990. function mpintro_visionset_ramp_hold_func()
  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.  
  1001. WAIT_SERVER_FRAME;
  1002. }
  1003. }
  1004.  
  1005. function mpintro_visionset_activate_func()
  1006. {
  1007. visionset_mgr::activate( "visionset", MPINTRO_VISIONSET_ALIAS, undefined, MPINTRO_VISIONSET_RAMP_IN, &mpintro_visionset_ramp_hold_func, MPINTRO_VISIONSET_RAMP_OUT );
  1008. }
  1009.  
  1010. function mpintro_visionset_deactivate_func()
  1011. {
  1012. level notify( MPINTRO_VISIONSET_RAMP_NOTIFY );
  1013. }
  1014.  
  1015. function matchStartTimer()
  1016. {
  1017. mpintro_visionset_activate_func();
  1018. level thread sndSetMatchSnapshot( 1 );
  1019. waitForPlayers();
  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. {
  1031. mpintro_visionset_deactivate_func();
  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. {
  1060. mpintro_visionset_deactivate_func();
  1061. }
  1062. }
  1063.  
  1064. function notifyEndOfGameplay()
  1065. {
  1066. level waittill( "game_ended" );
  1067. level clientfield::set("gameplay_started", 0);
  1068. }
  1069.  
  1070. function matchStartTimerSkip()
  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.  
  1091. function waveSpawnTimer()
  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. }
  1103. WAIT_SERVER_FRAME;
  1104. }
  1105. }
  1106.  
  1107.  
  1108. function hostIdledOut()
  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.  
  1129. function getTeamScoreRatio()
  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.  
  1157. function getHighestScore()
  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.  
  1188. function RecordPlayStyleInformation()
  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.  
  1224. function getPlayerByName( name )
  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.  
  1242. function sendAfterActionReport()
  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.  
  1299. player persistence::set_after_action_report_stat( "team", teams::getTeamIndex( player.team ) );
  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.  
  1318. function UpdateAndFinalizeMatchRecord()
  1319. {
  1320. for ( index = 0; index < level.players.size; index++ )
  1321. {
  1322. player = level.players[index];
  1323.  
  1324. player globallogic_player::record_special_move_data_for_life( undefined );
  1325.  
  1326. if ( player util::is_bot() )
  1327. {
  1328. continue;
  1329. }
  1330.  
  1331. player globallogic_player::record_global_mp_stats_for_player_at_match_end();
  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.  
  1384. player RecordPlayStyleInformation();
  1385.  
  1386. recordPlayerMatchEnd( player );
  1387. RecordPlayerStats(player, "presentAtEnd", 1 );
  1388. }
  1389. }
  1390.  
  1391. finalizeMatchRecord();
  1392. }
  1393.  
  1394. function gameHistoryPlayerKicked()
  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.  
  1423. function gameHistoryPlayerQuit()
  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.  
  1641. thread globallogic_audio::announce_game_winner( winner );
  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.  
  1695. function recordEndGameComScoreEvent( result )
  1696. {
  1697. players = level.players;
  1698. for ( index = 0; index < players.size; index++ )
  1699. {
  1700. globallogic_player::recordEndGameComScoreEventForPlayer( players[index], result );
  1701. }
  1702. }
  1703.  
  1704. function getEndReasonText()
  1705. {
  1706. if ( isdefined( level.endReasonText ) )
  1707. {
  1708. return level.endReasonText;
  1709. }
  1710.  
  1711. if ( util::hitRoundLimit() || util::hitRoundWinLimit() )
  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.  
  1728. function resetOutcomeForAllPlayers()
  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.  
  1738. function hideOutcomeUIForAllPlayers()
  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.  
  1754. globallogic_utils::executePostRoundEvents();
  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 );
  1793. hideOutcomeUIForAllPlayers();
  1794. return true;
  1795. }
  1796. }
  1797. return false;
  1798. }
  1799.  
  1800.  
  1801. function setTopPlayerStats( )
  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.  
  1888. function getRoundLength()
  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. if( !GetDvarInt( "loot_enabled" ) )
  1907. {
  1908. return;
  1909. }
  1910.  
  1911. maxPlayableGameTime = game["playabletimepassed"] / 1000;
  1912. timePlayed = self getTotalTimePlayed( maxPlayableGameTime );
  1913. lootXPAwarded = 0;
  1914.  
  1915. if ( self.pers["participation"] >= 1 )
  1916. {
  1917. lootXPPerKey = int( GetDvarInt( "loot_cryptokeyCost", 100 ) );
  1918. avgGameLen = int( GetDvarInt( "loot_earnTime", 267 ) );
  1919. minPlayTime = int( GetDvarInt( "loot_earnPlayThreshold", 10 ) );
  1920. maxLootXp = int( GetDvarInt( "loot_earnMax", 10000 ) );
  1921. minLootXp = int( GetDvarInt( "loot_earnMin", 0 ) );
  1922. winMultiplier = int( GetDvarInt( "loot_winBonusPercent", 30 ) );
  1923.  
  1924. if( maxPlayableGameTime > 0 && timePlayed > minPlayTime )
  1925. {
  1926. // account for time spent in arena ban/protect
  1927. if( level.arenaMatch )
  1928. {
  1929. draftEnabled = ( GetGametypeSetting( "pregameDraftEnabled" ) == 1 );
  1930. voteEnabled = ( GetGametypeSetting( "pregameItemVoteEnabled" ) == 1 );
  1931.  
  1932. if( draftEnabled && voteEnabled )
  1933. {
  1934. arenaMin = GetDvarInt( "arena_minPregameCryptoSeconds", 0 );
  1935. arenaMax = GetDvarInt( "arena_maxPregameCryptoSeconds", 0 );
  1936.  
  1937. if( arenaMax > 0 && arenaMin >= 0 && arenaMin <= arenaMax )
  1938. {
  1939. bonusTime = RandomIntRange( arenaMin, arenaMax );
  1940. timePlayed += bonusTime;
  1941. }
  1942. }
  1943. }
  1944.  
  1945. // award enough lootxp for 1 cryptokey for each 'avgGameLen' seconds of time played
  1946. lootXpScale = timePlayed / avgGameLen;
  1947. lootXPAwarded = lootXPPerKey * lootXpScale;
  1948.  
  1949. // bonus for winner
  1950. if( isDefined( self.lootXpMultiplier ) && self.lootXpMultiplier == true )
  1951. {
  1952. lootXPAwarded = lootXPAwarded + ( lootXPAwarded * ( winMultiplier / 100 ) );
  1953. }
  1954.  
  1955. // scale for double lootxp
  1956. lootXPAwarded *= math::clamp( GetDvarFloat( "lootxp_multiplier", 1.0 ), 0.0, 4.0 );
  1957.  
  1958. lootXPAwarded = int( lootXPAwarded );
  1959.  
  1960. // sanity
  1961. if( lootXPAwarded > maxLootXp )
  1962. {
  1963. lootXPAwarded = maxLootXp;
  1964. }
  1965. else if( lootXPAwarded < minLootXp )
  1966. {
  1967. lootXPAwarded = minLootXp;
  1968. }
  1969.  
  1970. otherLootXPAwarded = self awardOtherLootXP();
  1971. lootXPAwarded += otherLootXPAwarded;
  1972.  
  1973. if( lootXPAwarded > 0 )
  1974. {
  1975. self ReportLootReward( 1, lootXPAwarded );
  1976. }
  1977.  
  1978. // if other loot xp was awarded, let client receive stats before requesting an upload
  1979. if ( otherLootXPAwarded > 0 )
  1980. {
  1981. level thread WaitAndUploadStats( self, GetDvarFloat( "src_other_lootxp_uploadstat_waittime", OTHER_LOOTXP_UPLOADSTAT_WAITTIME ) );
  1982. }
  1983. }
  1984. }
  1985.  
  1986. self setAARStat( "lootXpEarned", lootXPAwarded );
  1987. recordPlayerStats( self, "lootXpEarned", lootXPAwarded );
  1988. recordPlayerStats( self, "lootTimePlayed", timePlayed );
  1989. }
  1990.  
  1991. function WaitAndUploadStats( player, waitTime )
  1992. {
  1993. wait waitTime;
  1994.  
  1995. if ( isPlayer( player ) )
  1996. {
  1997. UploadStats( player );
  1998. }
  1999. }
  2000.  
  2001. function registerOtherLootXPAwards( func )
  2002. {
  2003. if ( !isdefined( level.awardOtherLootXPfunctions ) )
  2004. level.awardOtherLootXPfunctions = [];
  2005.  
  2006. ARRAY_ADD( level.awardOtherLootXPfunctions, func );
  2007. }
  2008.  
  2009. function awardOtherLootXP()
  2010. {
  2011. player = self;
  2012.  
  2013. if ( !isdefined( level.awardOtherLootXPfunctions ) )
  2014. return 0;
  2015.  
  2016. if ( !isPlayer( player ) )
  2017. return 0;
  2018.  
  2019. lootXP = 0;
  2020.  
  2021. foreach( func in level.awardOtherLootXPfunctions )
  2022. {
  2023. if ( !isdefined( func ) )
  2024. continue;
  2025.  
  2026. lootXP += player [[ func ]]();
  2027. }
  2028.  
  2029. return lootXP;
  2030. }
  2031.  
  2032. function endGame( winner, endReasonText )
  2033. {
  2034. // return if already ending via host quit or victory
  2035. if ( game["state"] == "postgame" || level.gameEnded )
  2036. return;
  2037.  
  2038. if ( isdefined( level.onEndGame ) )
  2039. [[level.onEndGame]]( winner );
  2040.  
  2041. if ( !isdefined( level.disableOutroVisionSet ) || level.disableOutroVisionSet == false )
  2042. {
  2043. visionSetNaked( "mpOutro", 2.0 );
  2044. }
  2045.  
  2046. setmatchflag( "cg_drawSpectatorMessages", 0 );
  2047. setmatchflag( "game_ended", 1 );
  2048.  
  2049. game["state"] = "postgame";
  2050. level.gameEndTime = getTime();
  2051. level.gameEnded = true;
  2052. SetDvar( "g_gameEnded", 1 );
  2053. level.inGracePeriod = false;
  2054. level notify ( "game_ended" );
  2055. level clientfield::set( "game_ended", 1 );
  2056. globallogic_audio::flush_dialog();
  2057.  
  2058. foreach( team in level.teams )
  2059. {
  2060. game["lastroundscore"][team] = getTeamScore( team );
  2061. }
  2062.  
  2063. if( util::isRoundBased() )
  2064. {
  2065. matchRecordRoundEnd();
  2066. }
  2067.  
  2068. winning_team = figureOutWinningTeam( winner );
  2069.  
  2070. if ( isdefined( game["overtime_round"] ) && isdefined( game["overtimeroundswon"][winning_team] ) )
  2071. {
  2072. game["overtimeroundswon"][winning_team]++;
  2073. }
  2074.  
  2075. if ( !isdefined( game["overtime_round"] ) || util::wasLastRound() ) // Want to treat all overtime rounds as a single round
  2076. {
  2077. game["roundsplayed"]++;
  2078. game["roundwinner"][game["roundsplayed"]] = winner;
  2079.  
  2080. if ( isdefined( game["roundswon"][winning_team] ) )
  2081. game["roundswon"][winning_team]++;
  2082. }
  2083.  
  2084. if ( isdefined( winner ) && isdefined( level.teams[ winning_team ] ) )
  2085. {
  2086. level.finalKillCam_winner = winner;
  2087. }
  2088. else
  2089. {
  2090. level.finalKillCam_winner = "none";
  2091. }
  2092.  
  2093. level.finalKillCam_winnerPicked = true; // consider "none" as picked too
  2094.  
  2095. setGameEndTime( 0 ); // stop/hide the timers
  2096.  
  2097. updatePlacement();
  2098.  
  2099. updateRankedMatch( winner );
  2100.  
  2101. // freeze players
  2102. players = level.players;
  2103.  
  2104. newTime = getTime();
  2105. roundLength = getRoundLength();
  2106.  
  2107. SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
  2108.  
  2109. bbGameOver = 0;
  2110. if ( util::isOneRound() || util::wasLastRound() )
  2111. {
  2112. bbGameOver = 1;
  2113. }
  2114.  
  2115. surveyId = 0;
  2116. if( RandomFloat(1) <= GetDvarFloat("survey_chance") )
  2117. surveyId = RandomIntRange(1, GetDvarInt( "survey_count" ) + 1 );
  2118.  
  2119. for ( index = 0; index < players.size; index++ )
  2120. {
  2121. player = players[index];
  2122. player globallogic_player::freezePlayerForRoundEnd();
  2123. player thread roundEndDoF( 4.0 );
  2124.  
  2125. player globallogic_ui::freeGameplayHudElems();
  2126.  
  2127. player.pers["lastroundscore"] = player.pointstowin;
  2128.  
  2129. // Update weapon usage stats
  2130. player weapons::update_timings( newTime );
  2131.  
  2132. if ( bbGameOver )
  2133. player behaviorTracker::Finalize();
  2134.  
  2135. player bbPlayerMatchEnd( roundLength, endReasonText, bbGameOver );
  2136.  
  2137. player.pers["totalTimePlayed"] += player.timePlayed["total"];
  2138.  
  2139. if ( bbGameOver )
  2140. {
  2141. if ( level.leagueMatch )
  2142. {
  2143. player setAARStat( "lobbyPopup", "leaguesummary" );
  2144. }
  2145. else
  2146. {
  2147. player setAARStat( "lobbyPopup", "summary" );
  2148. }
  2149. }
  2150.  
  2151. player setAARStat( "surveyId", surveyId );
  2152. player setAARStat( "hardcore", level.hardcoreMode );
  2153. }
  2154.  
  2155. // music::setmusicstate( "silent" );
  2156.  
  2157. // temporarily disabling round end sound call to prevent the final killcam from not having sound
  2158. if ( !level.inFinalKillcam )
  2159. {
  2160. // util::clientNotify( "snd_end_rnd" );
  2161. }
  2162.  
  2163. gamerep::gameRepUpdateInformationForRound();
  2164. thread challenges::roundEnd( winner );
  2165.  
  2166. // update now
  2167. game_winner = winner;
  2168. if ( !util::isOneRound() )
  2169. {
  2170. game_winner = [[level.determineWinner]]( winner );
  2171. }
  2172. update_top_scorers(game_winner);
  2173.  
  2174. if ( startNextRound( winner, endReasonText ) )
  2175. {
  2176. return;
  2177. }
  2178.  
  2179. ///////////////////////////////////////////
  2180. // After this the match is really ending //
  2181. ///////////////////////////////////////////
  2182.  
  2183. if ( !util::isOneRound() )
  2184. {
  2185. if ( isdefined( level.onRoundEndGame ) )
  2186. winner = [[level.onRoundEndGame]]( winner );
  2187.  
  2188. endReasonText = getEndReasonText();
  2189. }
  2190.  
  2191. globallogic_score::updateWinLossStats( winner );
  2192.  
  2193. // this needs to happen after updateWinLossStats to award winner multipliers correctly
  2194. if( level.rankedmatch || level.arenaMatch )
  2195. {
  2196. thread awardLootXPToPlayers( WAIT_TIME_BEFORE_AWARDING_LOOT_XP, players );
  2197. }
  2198.  
  2199. if( level.arenaMatch )
  2200. {
  2201. arena::match_end( winner );
  2202. }
  2203.  
  2204. result = "";
  2205.  
  2206. if ( level.teambased )
  2207. {
  2208. if ( winner == "tie" )
  2209. {
  2210. result = "draw";
  2211. }
  2212. else
  2213. {
  2214. result = winner;
  2215. }
  2216. }
  2217. else
  2218. {
  2219. if ( !isDefined( winner ) )
  2220. {
  2221. result = "draw";
  2222. }
  2223. else
  2224. {
  2225. result = winner.team;
  2226. }
  2227. }
  2228.  
  2229. recordGameResult( result );
  2230.  
  2231. // we want the end time for each player the moment the match is done, not post-final-killcam-presentation
  2232. players = level.players;
  2233. for ( index = 0; index < players.size; index++ )
  2234. {
  2235. player = players[index];
  2236. player globallogic_player::record_misc_player_stats();
  2237. }
  2238.  
  2239. skillUpdate( winner, level.teamBased );
  2240. recordLeagueWinner( winner );
  2241.  
  2242. setTopPlayerStats();
  2243. thread challenges::gameEnd( winner );
  2244.  
  2245. UpdateAndFinalizeMatchRecord();
  2246.  
  2247. recordEndGameComScoreEvent( result );
  2248.  
  2249. level.finalGameEnd = true;
  2250.  
  2251. if ( !isdefined( level.skipGameEnd ) || !level.skipGameEnd )
  2252. displayGameEnd( winner, endReasonText );
  2253.  
  2254. level.finalGameEnd = undefined;
  2255.  
  2256. if ( util::isOneRound() )
  2257. {
  2258. globallogic_utils::executePostRoundEvents();
  2259. }
  2260.  
  2261. level.intermission = true;
  2262.  
  2263. gamerep::gameRepAnalyzeAndReport();
  2264.  
  2265. util::setClientSysState("levelNotify", "fkcs" );
  2266.  
  2267. // update again
  2268. // update_top_scorers(winner);
  2269.  
  2270. if( persistence::can_set_aar_stat() )
  2271. {
  2272. thread sendAfterActionReport();
  2273. }
  2274.  
  2275. stopdemorecording();
  2276.  
  2277. SetMatchTalkFlag( "EveryoneHearsEveryone", 1 );
  2278.  
  2279. //regain players array since some might've disconnected during the wait above
  2280. players = level.players;
  2281. for ( index = 0; index < players.size; index++ )
  2282. {
  2283. player = players[index];
  2284.  
  2285. player notify ( "reset_outcome" );
  2286. player thread [[level.spawnIntermission]]( false, level.useXCamsForEndGame );
  2287. player setClientUIVisibilityFlag( "hud_visible", 1 );
  2288. }
  2289.  
  2290. level clientfield::set( "post_game", 1 );
  2291.  
  2292. doEndGameSequence();
  2293.  
  2294. if ( isdefined ( level.endGameFunction ) )
  2295. {
  2296. level thread [[level.endGameFunction]]();
  2297. }
  2298. //Eckert - Fading out sound
  2299. level notify ( "sfade");
  2300. /#print( "game ended" );#/
  2301.  
  2302. if ( !isdefined( level.skipGameEnd ) || !level.skipGameEnd )
  2303. wait 5.0;
  2304.  
  2305. if( isDefined( level.end_game_video ) )
  2306. {
  2307. level thread lui::play_movie( level.end_game_video.name, "fullscreen", true );
  2308. wait( level.end_game_video.duration + 4.5 );
  2309. }
  2310.  
  2311. exit_level();
  2312. }
  2313.  
  2314. function awardLootXPToPlayers( delay, players )
  2315. {
  2316. wait delay;
  2317.  
  2318. foreach( player in players )
  2319. {
  2320. if ( !isdefined( player ) )
  2321. continue;
  2322.  
  2323. player awardLootXP();
  2324. }
  2325. }
  2326.  
  2327. function exit_level()
  2328. {
  2329. if ( level.exitLevel )
  2330. return;
  2331.  
  2332. level.exitLevel = true;
  2333. exitLevel( false );
  2334. }
  2335.  
  2336. function update_top_scorers(winner)
  2337. {
  2338. topscorers = [];
  2339.  
  2340. winning_team = figureOutWinningTeam( winner );
  2341.  
  2342. if ( level.teambased && isdefined(winner) && isdefined( level.placement[winning_team] ) )
  2343. {
  2344. topscorers = level.placement[winning_team];
  2345. }
  2346. else
  2347. {
  2348. topscorers = level.placement["all"];
  2349. }
  2350.  
  2351. if ( topscorers.size )
  2352. {
  2353. level.doTopScorers = true;
  2354. }
  2355. else
  2356. {
  2357. level.doTopScorers = false;
  2358. }
  2359.  
  2360. ClearTopScorers();
  2361.  
  2362. for ( i = 0; i < 3 && i < topscorers.size; i++ )
  2363. {
  2364. player = topscorers[i];
  2365.  
  2366. player thread checkForGestures( i );
  2367.  
  2368. showcase_weapon = player weapons::showcaseweapon_get();
  2369. tauntIndex = player GetPlayerSelectedTaunt( TAUNT_TYPE_FIRST_PLACE );
  2370. gesture0Index = player GetPlayerSelectedGesture( GESTURE_TYPE_GOOD_GAME );
  2371. gesture1Index = player GetPlayerSelectedGesture( GESTURE_TYPE_THREATEN );
  2372. gesture2Index = player GetPlayerSelectedGesture( GESTURE_TYPE_BOAST );
  2373. // if they dont have a weapon then they never spawned in
  2374. if ( !isDefined( showcase_weapon ) )
  2375. {
  2376. SetTopScorer( i, player, tauntIndex, gesture0Index, gesture1Index, gesture2Index, GetWeapon("ar_standard") );
  2377. continue;
  2378. }
  2379.  
  2380. SetTopScorer( i, player, tauntIndex, gesture0Index, gesture1Index, gesture2Index, showcase_weapon["weapon"], showcase_weapon["options"], showcase_weapon["acvi"] );
  2381. }
  2382. }
  2383.  
  2384. // self = player
  2385. function checkForGestures( topPlayerIndex )
  2386. {
  2387. self endon( "disconnect" );
  2388.  
  2389. fieldName = "playTop" + topPlayerIndex + "Gesture";
  2390.  
  2391. // Initialize the field
  2392. level clientfield::set( fieldName, GESTURE_TYPE_MAX );
  2393. WAIT_SERVER_FRAME;
  2394.  
  2395. while(true)
  2396. {
  2397. if ( self actionSlotOneButtonPressed() )
  2398. {
  2399. // Up - Good Game
  2400. self setGestureClientField( fieldName, GESTURE_TYPE_GOOD_GAME );
  2401. }
  2402. else if ( self actionSlotThreeButtonPressed() )
  2403. {
  2404. // Left - Threaten
  2405. self setGestureClientField( fieldName, GESTURE_TYPE_THREATEN );
  2406. }
  2407. else if ( self actionSlotFourButtonPressed() )
  2408. {
  2409. // Right - Boast
  2410. self setGestureClientField( fieldName, GESTURE_TYPE_BOAST );
  2411. }
  2412. /*
  2413. else if ( self actionSlotTwoButtonPressed() )
  2414. {
  2415. Down - Unused
  2416. self setGestureClientField( topPlayerIndex, 3 );
  2417. }
  2418. */
  2419. WAIT_SERVER_FRAME;
  2420. }
  2421. }
  2422.  
  2423. function setGestureClientField( fieldName, gestureType )
  2424. {
  2425. self notify ( "setGestureClientField" );
  2426. self endon ( "setGestureClientField" );
  2427.  
  2428. level clientfield::set( fieldName, gestureType );
  2429.  
  2430. WAIT_SERVER_FRAME;
  2431.  
  2432. // Reset the field
  2433. level clientfield::set( fieldName, GESTURE_TYPE_MAX );
  2434. }
  2435.  
  2436. function doEndGameSequence()
  2437. {
  2438. // This should be done only if the end game flow prefab is in the map.
  2439. level notify ( "endgame_sequence" );
  2440.  
  2441. preloadingEnabled = GetDvarInt( "sv_mapSwitchPreloadFrontend", 0 );
  2442. if ( level.doTopScorers && isDefined( struct::get( "endgame_top_players_struct", "targetname" ) ) )
  2443. {
  2444. //setMatchFlag( "full_screen", 1 );
  2445. setMatchFlag( "enable_popups", 1 ); // replace full_screen when new exes come in
  2446.  
  2447. // get rid of the corpses so they dont show up in the top scorers screen
  2448. ClearPlayerCorpses();
  2449.  
  2450. level thread sndSetMatchSnapshot( 3 );
  2451. level thread globallogic_audio::set_music_global("endmatch");
  2452. level clientfield::set( "displayTop3Players", 1 );
  2453.  
  2454. if( preloadingEnabled )
  2455. SwitchMap_Preload( "core_frontend" );
  2456.  
  2457. wait 15.0;
  2458. level clientfield::set( "triggerScoreboardCamera", 1 );
  2459. wait 5.0;
  2460. //setMatchFlag( "full_screen", 0 );
  2461. setMatchFlag( "enable_popups", 0 ); // replace full_screen when new exes come in
  2462. }
  2463. else if ( level.doEndgameScoreboard )
  2464. {
  2465. if( preloadingEnabled )
  2466. SwitchMap_Preload( "core_frontend" );
  2467. LUINotifyEvent( &"force_scoreboard", 0 );
  2468. }
  2469. }
  2470.  
  2471. function getTotalTimePlayed( maxLength ) // self == player
  2472. {
  2473. totalTimePlayed = 0;
  2474. if ( isdefined( self.pers["totalTimePlayed"] ) )
  2475. {
  2476. totalTimePlayed = self.pers["totalTimePlayed"];
  2477. if ( totalTimePlayed > maxLength )
  2478. {
  2479. totalTimePlayed = maxLength;
  2480. }
  2481. }
  2482. return totalTimePlayed;
  2483. }
  2484.  
  2485. function getRoundTimePlayed( roundLength ) // self == player
  2486. {
  2487. totalTimePlayed = 0;
  2488. if ( isdefined( self.timePlayed ) && isdefined( self.timePlayed["total"] ) )
  2489. {
  2490. totalTimePlayed = self.timePlayed["total"];
  2491. if ( totalTimePlayed > roundLength )
  2492. {
  2493. totalTimePlayed = roundLength;
  2494. }
  2495. }
  2496. return totalTimePlayed;
  2497. }
  2498.  
  2499. function bbPlayerMatchEnd( gameLength, endReasonString, gameOver ) // self == player
  2500. {
  2501. }
  2502.  
  2503. function roundEndWait( defaultDelay, matchBonus )
  2504. {
  2505. notifiesDone = false;
  2506. while ( !notifiesDone )
  2507. {
  2508. players = level.players;
  2509. notifiesDone = true;
  2510. for ( index = 0; index < players.size; index++ )
  2511. {
  2512. if ( !isdefined( players[index].doingNotify ) || !players[index].doingNotify )
  2513. continue;
  2514.  
  2515. notifiesDone = false;
  2516. }
  2517. wait ( 0.5 );
  2518. }
  2519.  
  2520. if ( !matchBonus )
  2521. {
  2522. wait ( defaultDelay );
  2523. level notify ( "round_end_done" );
  2524. return;
  2525. }
  2526.  
  2527. wait ( defaultDelay / 2 );
  2528. level notify ( "give_match_bonus" );
  2529. wait ( defaultDelay / 2 );
  2530.  
  2531. notifiesDone = false;
  2532. while ( !notifiesDone )
  2533. {
  2534. players = level.players;
  2535. notifiesDone = true;
  2536. for ( index = 0; index < players.size; index++ )
  2537. {
  2538. if ( !isdefined( players[index].doingNotify ) || !players[index].doingNotify )
  2539. continue;
  2540.  
  2541. notifiesDone = false;
  2542. }
  2543. wait ( 0.5 );
  2544. }
  2545.  
  2546. level notify ( "round_end_done" );
  2547. }
  2548.  
  2549.  
  2550. function roundEndDOF( time )
  2551. {
  2552. self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
  2553. }
  2554.  
  2555.  
  2556. function checkTimeLimit()
  2557. {
  2558. if ( isdefined( level.timeLimitOverride ) && level.timeLimitOverride )
  2559. return;
  2560.  
  2561. if ( game["state"] != "playing" )
  2562. {
  2563. setGameEndTime( 0 );
  2564. return;
  2565. }
  2566.  
  2567. if ( level.timeLimit <= 0 )
  2568. {
  2569. setGameEndTime( 0 );
  2570. return;
  2571. }
  2572.  
  2573. if ( level.inPrematchPeriod )
  2574. {
  2575. setGameEndTime( 0 );
  2576. return;
  2577. }
  2578.  
  2579. if( IS_TRUE( level.timerPaused ) )
  2580. {
  2581. timeRemaining = globallogic_utils::getTimeRemaining();
  2582. if ( timeRemaining > 30000 )
  2583. {
  2584. // round down to the nearest number so it doesn't jump back and forth
  2585. setGameEndTime( -int(timeRemaining - 999) );
  2586. }
  2587. else
  2588. {
  2589. // we show tenths of a second under 30
  2590. setGameEndTime( -int(timeRemaining - 99) );
  2591. }
  2592. return;
  2593. }
  2594.  
  2595. if ( level.timerStopped )
  2596. {
  2597. setGameEndTime( 0 );
  2598. return;
  2599. }
  2600.  
  2601. if ( !isdefined( level.startTime ) )
  2602. return;
  2603.  
  2604. timeLeft = globallogic_utils::getTimeRemaining();
  2605.  
  2606. // want this accurate to the millisecond
  2607. setGameEndTime( getTime() + int(timeLeft) );
  2608.  
  2609. if ( timeLeft > 0 )
  2610. return;
  2611.  
  2612. [[level.onTimeLimit]]();
  2613. }
  2614.  
  2615. function checkScoreLimit()
  2616. {
  2617. if ( game["state"] != "playing" )
  2618. return false;
  2619.  
  2620. if ( level.scoreLimit <= 0 )
  2621. return false;
  2622.  
  2623. if ( level.teamBased )
  2624. {
  2625. if( !util::any_team_hit_score_limit() )
  2626. return false;
  2627. }
  2628. else
  2629. {
  2630. if ( !isPlayer( self ) )
  2631. return false;
  2632.  
  2633. if ( self.pointstowin < level.scoreLimit )
  2634. return false;
  2635. }
  2636.  
  2637. [[level.onScoreLimit]]();
  2638. }
  2639.  
  2640. function checkSuddenDeathScoreLimit( team )
  2641. {
  2642. if ( game["state"] != "playing" )
  2643. return false;
  2644.  
  2645. if ( level.roundScoreLimit <= 0 )
  2646. return false;
  2647.  
  2648. if ( level.teamBased )
  2649. {
  2650. if( !game["teamSuddenDeath"][team] )
  2651. return false;
  2652. }
  2653. else
  2654. {
  2655. return false;
  2656. }
  2657.  
  2658. [[level.onScoreLimit]]();
  2659. }
  2660.  
  2661. function checkRoundScoreLimit()
  2662. {
  2663. if ( game["state"] != "playing" )
  2664. return false;
  2665.  
  2666. if ( level.roundScoreLimit <= 0 )
  2667. return false;
  2668.  
  2669. if ( level.teamBased )
  2670. {
  2671. if( !util::any_team_hit_round_score_limit() )
  2672. return false;
  2673. }
  2674. else
  2675. {
  2676. if ( !isPlayer( self ) )
  2677. return false;
  2678.  
  2679. roundScoreLimit = util::get_current_round_score_limit();
  2680.  
  2681. if ( self.pointstowin < roundScoreLimit )
  2682. return false;
  2683. }
  2684.  
  2685. [[level.onRoundScoreLimit]]();
  2686. }
  2687.  
  2688. function updateGameTypeDvars()
  2689. {
  2690. level endon ( "game_ended" );
  2691.  
  2692. while ( game["state"] == "playing" )
  2693. {
  2694. roundlimit = math::clamp( GetGametypeSetting( "roundLimit" ), level.roundLimitMin, level.roundLimitMax );
  2695. if ( roundlimit != level.roundlimit )
  2696. {
  2697. level.roundlimit = roundlimit;
  2698. level notify ( "update_roundlimit" );
  2699. }
  2700.  
  2701. timeLimit = [[level.getTimeLimit]]();
  2702. if ( timeLimit != level.timeLimit )
  2703. {
  2704. level.timeLimit = timeLimit;
  2705. SetDvar( "ui_timelimit", level.timeLimit );
  2706. level notify ( "update_timelimit" );
  2707. }
  2708. thread checkTimeLimit();
  2709.  
  2710. scoreLimit = math::clamp( GetGametypeSetting( "scoreLimit" ), level.scoreLimitMin, level.scoreLimitMax );
  2711. if ( scoreLimit != level.scoreLimit )
  2712. {
  2713. level.scoreLimit = scoreLimit;
  2714. SetDvar( "ui_scorelimit", level.scoreLimit );
  2715. level notify ( "update_scorelimit" );
  2716. }
  2717. thread checkScoreLimit();
  2718.  
  2719. roundScoreLimit = math::clamp( GetGametypeSetting( "roundScoreLimit" ), level.roundScoreLimitMin, level.roundScoreLimitMax );
  2720. if ( roundScoreLimit != level.roundScoreLimit )
  2721. {
  2722. level.roundScoreLimit = roundScoreLimit;
  2723. level notify ( "update_roundScoreLimit" );
  2724. }
  2725. thread checkRoundScoreLimit();
  2726.  
  2727. // make sure we check time limit right when game ends
  2728. if ( isdefined( level.startTime ) )
  2729. {
  2730. if ( globallogic_utils::getTimeRemaining() < 3000 )
  2731. {
  2732. wait .1;
  2733. continue;
  2734. }
  2735. }
  2736. wait 1;
  2737. }
  2738. }
  2739.  
  2740.  
  2741. function removeDisconnectedPlayerFromPlacement()
  2742. {
  2743. offset = 0;
  2744. numPlayers = level.placement["all"].size;
  2745. found = false;
  2746. for ( i = 0; i < numPlayers; i++ )
  2747. {
  2748. if ( level.placement["all"][i] == self )
  2749. found = true;
  2750.  
  2751. if ( found )
  2752. level.placement["all"][i] = level.placement["all"][ i + 1 ];
  2753. }
  2754. if ( !found )
  2755. return;
  2756.  
  2757. level.placement["all"][ numPlayers - 1 ] = undefined;
  2758. assert( level.placement["all"].size == numPlayers - 1 );
  2759.  
  2760. updateTeamPlacement();
  2761.  
  2762. if ( level.teamBased )
  2763. return;
  2764.  
  2765. numPlayers = level.placement["all"].size;
  2766. for ( i = 0; i < numPlayers; i++ )
  2767. {
  2768. player = level.placement["all"][i];
  2769. player notify( "update_outcome" );
  2770. }
  2771.  
  2772. }
  2773.  
  2774. function updatePlacement()
  2775. {
  2776.  
  2777. if ( !level.players.size )
  2778. return;
  2779.  
  2780. level.placement["all"] = [];
  2781. foreach ( player in level.players )
  2782. {
  2783. if ( !level.teambased || isdefined( level.teams[ player.team ] ) )
  2784. level.placement["all"][level.placement["all"].size] = player;
  2785. }
  2786.  
  2787. placementAll = level.placement["all"];
  2788.  
  2789. if ( level.teamBased )
  2790. {
  2791. for ( i = 1; i < placementAll.size; i++ )
  2792. {
  2793. player = placementAll[i];
  2794. playerScore = player.score;
  2795. for ( j = i - 1; j >= 0 && (playerScore > placementAll[j].score || (playerScore == placementAll[j].score && player.deaths < placementAll[j].deaths)); j-- )
  2796. placementAll[j + 1] = placementAll[j];
  2797. placementAll[j + 1] = player;
  2798. }
  2799. }
  2800. else
  2801. {
  2802. for ( i = 1; i < placementAll.size; i++ )
  2803. {
  2804. player = placementAll[i];
  2805. playerScore = player.pointstowin;
  2806. 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-- )
  2807. placementAll[j + 1] = placementAll[j];
  2808. placementAll[j + 1] = player;
  2809. }
  2810. }
  2811.  
  2812. level.placement["all"] = placementAll;
  2813.  
  2814. updateTeamPlacement();
  2815.  
  2816. }
  2817.  
  2818.  
  2819. function updateTeamPlacement()
  2820. {
  2821. foreach( team in level.teams )
  2822. {
  2823. placement[team] = [];
  2824. }
  2825. placement["spectator"] = [];
  2826.  
  2827. if ( !level.teamBased )
  2828. return;
  2829.  
  2830. placementAll = level.placement["all"];
  2831. placementAllSize = placementAll.size;
  2832.  
  2833. for ( i = 0; i < placementAllSize; i++ )
  2834. {
  2835. player = placementAll[i];
  2836. team = player.pers["team"];
  2837.  
  2838. placement[team][ placement[team].size ] = player;
  2839. }
  2840.  
  2841. foreach( team in level.teams )
  2842. {
  2843. level.placement[team] = placement[team];
  2844. }
  2845. }
  2846.  
  2847. function getPlacementForPlayer( player )
  2848. {
  2849. updatePlacement();
  2850.  
  2851. playerRank = -1;
  2852. placement = level.placement["all"];
  2853. for ( placementIndex = 0; placementIndex < placement.size; placementIndex++ )
  2854. {
  2855. if ( level.placement["all"][placementIndex] == player )
  2856. {
  2857. playerRank = (placementIndex + 1);
  2858. break;
  2859. }
  2860. }
  2861.  
  2862. return playerRank;
  2863. }
  2864.  
  2865. function isTopScoringPlayer( player )
  2866. {
  2867. topScoringPlayer = false;
  2868. updatePlacement();
  2869.  
  2870. assert( level.placement["all"].size > 0 );
  2871. if ( level.placement["all"].size == 0 )
  2872. {
  2873. return false;
  2874. }
  2875.  
  2876. if ( level.teambased )
  2877. {
  2878. topScore = level.placement["all"][0].score;
  2879. for ( index = 0; index < level.placement["all"].size; index++ )
  2880. {
  2881. if ( level.placement["all"][index].score == 0 )
  2882. {
  2883. break;
  2884. }
  2885. if ( topScore > level.placement["all"][index].score )
  2886. {
  2887. break;
  2888. }
  2889. if ( player == level.placement["all"][index] )
  2890. {
  2891. topScoringPlayer = true;
  2892. break;
  2893. }
  2894. }
  2895. }
  2896. else
  2897. {
  2898. topScore = level.placement["all"][0].pointsToWin;
  2899. for ( index = 0; index < level.placement["all"].size; index++ )
  2900. {
  2901. if ( level.placement["all"][index].pointsToWin == 0 )
  2902. {
  2903. break;
  2904. }
  2905. if ( topScore > level.placement["all"][index].pointsToWin )
  2906. {
  2907. break;
  2908. }
  2909. if ( player == level.placement["all"][index] )
  2910. {
  2911. topScoringPlayer = true;
  2912. break;
  2913. }
  2914. }
  2915. }
  2916. return topScoringPlayer;
  2917. }
  2918.  
  2919. function sortDeadPlayers( team )
  2920. {
  2921. // only need to sort if we are running queued respawn
  2922. if ( !level.playerQueuedRespawn )
  2923. return;
  2924.  
  2925. // sort by death time
  2926. for ( i = 1; i < level.deadPlayers[team].size; i++ )
  2927. {
  2928. player = level.deadPlayers[team][i];
  2929. for ( j = i - 1; j >= 0 && player.deathTime < level.deadPlayers[team][j].deathTime; j-- )
  2930. level.deadPlayers[team][j + 1] = level.deadPlayers[team][j];
  2931. level.deadPlayers[team][j + 1] = player;
  2932. }
  2933.  
  2934. for ( i = 0; i < level.deadPlayers[team].size; i++ )
  2935. {
  2936. if ( level.deadPlayers[team][i].spawnQueueIndex != i )
  2937. {
  2938. level.spawnQueueModified[team] = true;
  2939. }
  2940. level.deadPlayers[team][i].spawnQueueIndex = i;
  2941. }
  2942. }
  2943.  
  2944. function totalAliveCount()
  2945. {
  2946. count = 0;
  2947. foreach( team in level.teams )
  2948. {
  2949. count += level.aliveCount[team];
  2950. }
  2951. return count;
  2952. }
  2953.  
  2954. function totalPlayerLives()
  2955. {
  2956. count = 0;
  2957. foreach( team in level.teams )
  2958. {
  2959. count += level.playerLives[team];
  2960. }
  2961. return count;
  2962. }
  2963.  
  2964. function initTeamVariables( team )
  2965. {
  2966.  
  2967. if ( !isdefined( level.aliveCount ) )
  2968. level.aliveCount = [];
  2969.  
  2970. level.aliveCount[team] = 0;
  2971. level.lastAliveCount[team] = 0;
  2972.  
  2973. if ( !isdefined( game["everExisted"] ) )
  2974. {
  2975. game["everExisted"] = [];
  2976. }
  2977. if ( !isdefined( game["everExisted"][team] ) )
  2978. {
  2979. game["everExisted"][team] = false;
  2980. }
  2981. level.everExisted[team] = false;
  2982. level.waveDelay[team] = 0;
  2983. level.lastWave[team] = 0;
  2984. level.wavePlayerSpawnIndex[team] = 0;
  2985.  
  2986. resetTeamVariables( team );}
  2987.  
  2988. function resetTeamVariables( team )
  2989. {
  2990. level.playerCount[team] = 0;
  2991. level.botsCount[team] = 0;
  2992. level.lastAliveCount[team] = level.aliveCount[team];
  2993. level.aliveCount[team] = 0;
  2994. level.playerLives[team] = 0;
  2995. level.alivePlayers[team] = [];
  2996. level.spawningPlayers[team] = [];
  2997. level.deadPlayers[team] = [];
  2998. level.squads[team] = [];
  2999. level.spawnQueueModified[team] = false;
  3000. }
  3001.  
  3002. function updateTeamStatus()
  3003. {
  3004. // run only once per frame, at the end of the frame.
  3005. level notify("updating_team_status");
  3006. level endon("updating_team_status");
  3007. level endon ( "game_ended" );
  3008. waittillframeend;
  3009.  
  3010. wait 0; // Required for Callback_PlayerDisconnect to complete before updateTeamStatus can execute
  3011.  
  3012. if ( game["state"] == "postgame" )
  3013. return;
  3014.  
  3015. resetTimeout();
  3016.  
  3017. foreach( team in level.teams )
  3018. {
  3019. resetTeamVariables( team );
  3020. }
  3021.  
  3022. if ( !level.teambased )
  3023. {
  3024. resetTeamVariables( "free" );
  3025. }
  3026.  
  3027. level.activePlayers = [];
  3028.  
  3029. players = level.players;
  3030. for ( i = 0; i < players.size; i++ )
  3031. {
  3032. player = players[i];
  3033.  
  3034. if ( !isdefined( player ) && level.splitscreen )
  3035. continue;
  3036.  
  3037. if ( level.teambased || player.team == "spectator" )
  3038. {
  3039. team = player.team;
  3040. }
  3041. else
  3042. {
  3043. team = "free";
  3044. }
  3045.  
  3046. playerclass = player.curClass;
  3047.  
  3048. if ( team != "spectator" && (isdefined( playerclass ) && playerclass != "") )
  3049. {
  3050. level.playerCount[team]++;
  3051.  
  3052. if( isdefined( player.pers["isBot"] ) )
  3053. level.botsCount[team]++;
  3054.  
  3055. not_quite_dead = false;
  3056.  
  3057. // used by the resurrect gadget to keep players that could self-resurrect from appearing dead
  3058. if ( isdefined( player.overridePlayerDeadStatus ) )
  3059. {
  3060. not_quite_dead = player [[ player.overridePlayerDeadStatus ]]();
  3061. }
  3062.  
  3063. if ( player.sessionstate == "playing" )
  3064. {
  3065. level.aliveCount[team]++;
  3066. level.playerLives[team]++;
  3067. player.spawnQueueIndex = -1;
  3068.  
  3069. if ( isAlive( player ) )
  3070. {
  3071. level.alivePlayers[team][level.alivePlayers[team].size] = player;
  3072. level.activeplayers[ level.activeplayers.size ] = player;
  3073. }
  3074. else
  3075. {
  3076. level.deadPlayers[team][level.deadPlayers[team].size] = player;
  3077. }
  3078. }
  3079. else if ( not_quite_dead )
  3080. {
  3081. level.aliveCount[team]++;
  3082. level.playerLives[team]++;
  3083. level.alivePlayers[team][level.alivePlayers[team].size] = player;
  3084. }
  3085. else
  3086. {
  3087. level.deadPlayers[team][level.deadPlayers[team].size] = player;
  3088. if ( player globallogic_spawn::maySpawn() )
  3089. level.playerLives[team]++;
  3090. }
  3091. }
  3092. }
  3093.  
  3094. totalAlive = totalAliveCount();
  3095.  
  3096. if ( totalAlive > level.maxPlayerCount )
  3097. level.maxPlayerCount = totalAlive;
  3098.  
  3099. foreach( team in level.teams )
  3100. {
  3101. if ( level.aliveCount[team] )
  3102. {
  3103. game["everExisted"][team] = true;
  3104. level.everExisted[team] = true;
  3105. }
  3106.  
  3107. sortDeadPlayers( team );
  3108. }
  3109.  
  3110. level updateGameEvents();
  3111. }
  3112.  
  3113. function updateAliveTimes(team)
  3114. {
  3115. level.aliveTimesAverage[team] = 0;
  3116.  
  3117. if ( game["state"] == "postgame" )
  3118. return;
  3119.  
  3120. total_player_count = 0;
  3121. average_player_spawn_time = 0;
  3122. total_value_count = 0;
  3123.  
  3124. foreach( player in level.alivePlayers[team] )
  3125. {
  3126. average_time = 0;
  3127. count = 0;
  3128. foreach( time in player.aliveTimes )
  3129. {
  3130. if ( time != 0 )
  3131. {
  3132. average_time += time;
  3133. count++;
  3134. }
  3135. }
  3136.  
  3137. if ( count )
  3138. {
  3139. total_value_count += count;
  3140. average_player_spawn_time += average_time / count;
  3141. total_player_count++;
  3142. }
  3143. }
  3144.  
  3145. foreach( player in level.deadPlayers[team] )
  3146. {
  3147. average_time = 0;
  3148. count = 0;
  3149. foreach( time in player.aliveTimes )
  3150. {
  3151. if ( time != 0 )
  3152. {
  3153. average_time += time;
  3154. count++;
  3155. }
  3156. }
  3157.  
  3158. if ( count )
  3159. {
  3160. total_value_count += count;
  3161. average_player_spawn_time += average_time / count;
  3162. total_player_count++;
  3163. }
  3164. }
  3165.  
  3166. // if we dont have player or dont have enough data dont bother
  3167. if ( total_player_count == 0 || total_value_count < 3 )
  3168. {
  3169. level.aliveTimesAverage[team] = 0;
  3170. return;
  3171. }
  3172.  
  3173. level.aliveTimesAverage[team] = average_player_spawn_time / total_player_count;
  3174. }
  3175.  
  3176. function updateAllAliveTimes()
  3177. {
  3178. foreach( team in level.teams )
  3179. {
  3180. updateAliveTimes(team);
  3181. }
  3182. }
  3183.  
  3184. function checkTeamScoreLimitSoon( team )
  3185. {
  3186. assert( isdefined( team ) );
  3187.  
  3188. if ( level.scoreLimit <= 0 )
  3189. return;
  3190.  
  3191. if ( !level.teamBased )
  3192. return;
  3193.  
  3194. // Give the data a minute to converge/settle
  3195. if ( globallogic_utils::getTimePassed() < ( 60 * 1000 ) )
  3196. return;
  3197.  
  3198. timeLeft = globallogic_utils::getEstimatedTimeUntilScoreLimit( team );
  3199.  
  3200. if ( timeLeft < 1 )
  3201. {
  3202. level notify( "match_ending_soon", "score" );
  3203. }
  3204. }
  3205.  
  3206. function checkPlayerScoreLimitSoon()
  3207. {
  3208. assert( IsPlayer( self ) );
  3209.  
  3210. if ( level.scoreLimit <= 0 )
  3211. return;
  3212.  
  3213. if ( level.teamBased )
  3214. return;
  3215.  
  3216. // Give the data a minute to converge/settle
  3217. if ( globallogic_utils::getTimePassed() < ( 60 * 1000 ) )
  3218. return;
  3219.  
  3220. timeLeft = globallogic_utils::getEstimatedTimeUntilScoreLimit( undefined );
  3221.  
  3222. if ( timeLeft < 1 )
  3223. {
  3224. level notify( "match_ending_soon", "score" );
  3225. }
  3226. }
  3227.  
  3228. function timeLimitClock()
  3229. {
  3230. level endon ( "game_ended" );
  3231.  
  3232. wait .05;
  3233.  
  3234. clockObject = spawn( "script_origin", (0,0,0) );
  3235.  
  3236. while ( game["state"] == "playing" )
  3237. {
  3238. if ( !level.timerStopped && level.timeLimit )
  3239. {
  3240. timeLeft = globallogic_utils::getTimeRemaining() / 1000;
  3241. timeLeftInt = int(timeLeft + 0.5); // adding .5 and flooring rounds it.
  3242.  
  3243. if ( timeLeftInt == 601 )
  3244. util::clientNotify( "notify_10" );
  3245.  
  3246. if ( timeLeftInt == 301 )
  3247. util::clientNotify( "notify_5" );
  3248.  
  3249. if ( timeLeftInt == 60 )
  3250. util::clientNotify( "notify_1" );
  3251.  
  3252. if ( timeLeftInt == 12 )
  3253. util::clientNotify( "notify_count" );
  3254.  
  3255. if ( timeLeftInt >= 40 && timeLeftInt <= 60 )
  3256. level notify ( "match_ending_soon", "time" );
  3257.  
  3258. if ( timeLeftInt >= 30 && timeLeftInt <= 40 )
  3259. level notify ( "match_ending_pretty_soon", "time" );
  3260.  
  3261. if( timeLeftInt <= 32 )
  3262. level notify ( "match_ending_vox" );
  3263.  
  3264. if ( timeLeftInt <= 10 || (timeLeftInt <= 30 && timeLeftInt % 2 == 0) )
  3265. {
  3266. level notify ( "match_ending_very_soon", "time" );
  3267. // don't play a tick at exactly 0 seconds, that's when something should be happening!
  3268. if ( timeLeftInt == 0 )
  3269. break;
  3270.  
  3271. clockObject playSound( "mpl_ui_timer_countdown" );
  3272. }
  3273.  
  3274. // synchronize to be exactly on the second
  3275. if ( timeLeft - floor(timeLeft) >= .05 )
  3276. wait timeLeft - floor(timeLeft);
  3277. }
  3278.  
  3279. wait ( 1.0 );
  3280. }
  3281. }
  3282.  
  3283. function timeLimitClock_Intermission( waitTime )
  3284. {
  3285. setGameEndTime( getTime() + int(waitTime*1000) );
  3286. clockObject = spawn( "script_origin", (0,0,0) );
  3287.  
  3288. if ( waitTime >= 10.0 )
  3289. wait ( waitTime - 10.0 );
  3290.  
  3291. for ( ;; )
  3292. {
  3293. clockObject playSound( "mpl_ui_timer_countdown" );
  3294. wait ( 1.0 );
  3295. }
  3296. }
  3297. function recordBreadcrumbData()
  3298. {
  3299. level endon ( "game_ended" );
  3300.  
  3301. while(1)
  3302. {
  3303. for ( i = 0; i < level.players.size; i++ )
  3304. {
  3305. player = level.players[i];
  3306. if( isAlive( player ) )
  3307. {
  3308. RecordBreadcrumbDataForPlayer( player, player.lastShotBy );
  3309. }
  3310. }
  3311.  
  3312. wait( 2.0 ); // make sure #define BREADCRUMBDATA_INTERVAL_SECONDS in code matches this!
  3313. }
  3314.  
  3315. }
  3316.  
  3317. function startGame()
  3318. {
  3319. thread globallogic_utils::gameTimer();
  3320. level.timerStopped = false;
  3321. level.playableTimerStopped = false;
  3322. // RF, disabled this, as it is not required anymore.
  3323. //thread spawnlogic::spawn_per_frame_update();
  3324.  
  3325. SetMatchTalkFlag( "DeadChatWithDead", level.voip.deadChatWithDead );
  3326. SetMatchTalkFlag( "DeadChatWithTeam", level.voip.deadChatWithTeam );
  3327. SetMatchTalkFlag( "DeadHearTeamLiving", level.voip.deadHearTeamLiving );
  3328. SetMatchTalkFlag( "DeadHearAllLiving", level.voip.deadHearAllLiving );
  3329. SetMatchTalkFlag( "EveryoneHearsEveryone", level.voip.everyoneHearsEveryone );
  3330. SetMatchTalkFlag( "DeadHearKiller", level.voip.deadHearKiller );
  3331. SetMatchTalkFlag( "KillersHearVictim", level.voip.killersHearVictim );
  3332.  
  3333. ClearTopScorers();
  3334.  
  3335. if(IsDefined(level.custom_prematch_period))
  3336. {
  3337. [[level.custom_prematch_period]]();
  3338. }
  3339. else
  3340. {
  3341. prematchPeriod();
  3342. }
  3343.  
  3344. level notify("prematch_over");
  3345. level.prematch_over = true;
  3346.  
  3347. level clientfield::set("gameplay_started", 1);
  3348.  
  3349. thread notifyEndOfGameplay();
  3350.  
  3351. thread timeLimitClock();
  3352. thread gracePeriod();
  3353. thread watchMatchEndingSoon();
  3354.  
  3355. thread globallogic_audio::announcerController();
  3356. thread globallogic_audio::sndMusicFunctions();
  3357. thread recordBreadcrumbData();
  3358.  
  3359. if( util::isRoundBased() )
  3360. {
  3361. if( util::getRoundsPlayed() == 0 )
  3362. {
  3363. // true beginning of a round-based game
  3364. recordMatchBegin();
  3365. }
  3366. matchRecordRoundStart();
  3367.  
  3368. if ( isdefined( game["overtime_round"] ) )
  3369. {
  3370. matchRecordOvertimeRound();
  3371. }
  3372. }
  3373. else
  3374. {
  3375. // not round based
  3376. recordMatchBegin();
  3377. }
  3378. }
  3379.  
  3380. function isPrematchRequirementConditionMet(activeTeamCount)
  3381. {
  3382. if ( level.prematchRequirement == 0 )
  3383. return true;
  3384.  
  3385. if ( level.teamBased )
  3386. {
  3387. if ( activeTeamCount.size <= 1 )
  3388. return false;
  3389.  
  3390. foreach( teamCount in activeTeamCount )
  3391. {
  3392. if ( teamCount != level.prematchRequirement )
  3393. return false;
  3394. }
  3395. }
  3396. else
  3397. {
  3398. if ( activeTeamCount["free"] != level.prematchRequirement )
  3399. return false;
  3400. }
  3401. return true;
  3402. }
  3403.  
  3404. function waitForPlayers()
  3405. {
  3406. level endon( "game_ended" );
  3407. startTime = getTime();
  3408.  
  3409. playerReady = false;
  3410. activePlayerCount = 0;
  3411. acceptTestClient = false;
  3412.  
  3413. activeTeamCount = [];
  3414. player_ready = [];
  3415.  
  3416. while ( !playerReady || activePlayerCount == 0 || !isprematchRequirementConditionMet(activeTeamCount) )
  3417. {
  3418. activePlayerCount = 0;
  3419.  
  3420. if ( level.teamBased )
  3421. {
  3422. foreach( team in level.teams )
  3423. {
  3424. activeTeamCount[team] = 0;
  3425. }
  3426. }
  3427. else
  3428. {
  3429. activeTeamCount["free"] = 0;
  3430. }
  3431.  
  3432. temp_player_ready = [];
  3433.  
  3434. foreach( player in level.players )
  3435. {
  3436. // only consider real players
  3437. if ( player istestclient() && acceptTestClient == false )
  3438. continue;
  3439.  
  3440. if ( player.team != "spectator" )
  3441. {
  3442. activePlayerCount++;
  3443.  
  3444. player_num = player GetEntityNumber();
  3445. if ( isDefined( player_ready[player_num] ) )
  3446. {
  3447. temp_player_ready[player_num] = player_ready[player_num];
  3448. }
  3449. else
  3450. {
  3451. temp_player_ready[player_num] = GetTime();
  3452. }
  3453.  
  3454. // streamer gets marked ready well before the player is done "loading"
  3455. // we want to wait until the player is done loading but will have a five second failsafe
  3456. // this mechanic should probably be a core system as we have several places that we want to know
  3457. // when the player is done loading
  3458. if ( ((temp_player_ready[player_num] + 5000) < GetTime()) || player isStreamerReady( -1, true ) )
  3459. {
  3460. if ( level.teamBased )
  3461. {
  3462. activeTeamCount[player.team]++;
  3463. }
  3464. else
  3465. {
  3466. activeTeamCount["free"]++;
  3467. }
  3468. }
  3469. }
  3470.  
  3471. if( player isStreamerReady( -1, true ) )
  3472. {
  3473. if ( playerReady == false )
  3474. {
  3475. level notify("first_player_ready", player );
  3476. }
  3477. playerReady = true;
  3478. }
  3479. }
  3480.  
  3481. // this causes any players that no longer exist in the list to flush
  3482. player_read = temp_player_ready;
  3483.  
  3484. WAIT_SERVER_FRAME;
  3485. if( getTime() - startTime > ( 20 * 1000 ) )
  3486. {
  3487. if ( level.rankedmatch == false && level.arenamatch == false )
  3488. {
  3489. acceptTestClient = true;
  3490. }
  3491. }
  3492.  
  3493. if( level.rankedMatch && ((getTime() - startTime) > ( 120 * 1000 )) )
  3494. {
  3495. //EOughton: if we've been sitting here for 2 minutes without anyone making it in, it's time to call it a night
  3496. exit_level();
  3497.  
  3498. while(1)
  3499. {
  3500. // dont do anything just let the level exit
  3501. wait(10);
  3502. }
  3503. }
  3504. }
  3505. }
  3506.  
  3507. function prematchWaitingForPlayers()
  3508. {
  3509. if ( level.prematchRequirement != 0 )
  3510. {
  3511. level waittill ("first_player_ready", player );
  3512. LUINotifyEvent( &"prematch_waiting_for_players" );
  3513. }
  3514. }
  3515.  
  3516. function prematchPeriod()
  3517. {
  3518. setMatchFlag( "hud_hardcore", level.hardcoreMode );
  3519.  
  3520. level endon( "game_ended" );
  3521.  
  3522. globallogic_audio::sndMusicSetRandomizer();
  3523.  
  3524. if ( level.prematchPeriod > 0 )
  3525. {
  3526. thread matchStartTimer();
  3527. thread prematchWaitingForPlayers();
  3528.  
  3529. waitForPlayers();
  3530.  
  3531. wait ( level.prematchPeriod );
  3532. }
  3533. else
  3534. {
  3535. matchStartTimerSkip();
  3536.  
  3537. WAIT_SERVER_FRAME;
  3538. }
  3539.  
  3540. level.inPrematchPeriod = false;
  3541. level thread sndSetMatchSnapshot( 0 );
  3542.  
  3543. for ( index = 0; index < level.players.size; index++ )
  3544. {
  3545. level.players[index] util::freeze_player_controls( false );
  3546. level.players[index] enableWeapons();
  3547. }
  3548.  
  3549. if ( game["state"] != "playing" )
  3550. return;
  3551. }
  3552.  
  3553. function gracePeriod()
  3554. {
  3555. level endon("game_ended");
  3556.  
  3557. if ( isdefined( level.gracePeriodFunc ) )
  3558. {
  3559. [[ level.gracePeriodFunc ]]();
  3560. }
  3561. else
  3562. {
  3563. wait ( level.gracePeriod );
  3564. }
  3565.  
  3566. level notify ( "grace_period_ending" );
  3567. WAIT_SERVER_FRAME;
  3568.  
  3569. level.inGracePeriod = false;
  3570.  
  3571. if ( game["state"] != "playing" )
  3572. return;
  3573.  
  3574. if ( level.numLives )
  3575. {
  3576. // Players on a team but without a weapon show as dead since they can not get in this round
  3577. players = level.players;
  3578.  
  3579. for ( i = 0; i < players.size; i++ )
  3580. {
  3581. player = players[i];
  3582.  
  3583. if ( !player.hasSpawned && player.sessionteam != "spectator" && !isAlive( player ) )
  3584. player.statusicon = "hud_status_dead";
  3585. }
  3586. }
  3587.  
  3588. level thread updateTeamStatus();
  3589. level thread updateAllAliveTimes();
  3590. }
  3591.  
  3592. function watchMatchEndingSoon()
  3593. {
  3594. SetDvar( "xblive_matchEndingSoon", 0 );
  3595. level waittill( "match_ending_soon", reason );
  3596. SetDvar( "xblive_matchEndingSoon", 1 );
  3597. }
  3598.  
  3599. function assertTeamVariables( )
  3600. {
  3601. // these are defined in the teamset file
  3602. foreach ( team in level.teams )
  3603. {
  3604. Assert( isdefined( game["strings"][ team + "_win"] ), "game[\"strings\"][\"" + team + "_win\"] does not exist" );
  3605. Assert( isdefined( game["strings"][ team + "_win_round"] ), "game[\"strings\"][\"" + team + "_win_round\"] does not exist" );
  3606. Assert( isdefined( game["strings"][ team + "_mission_accomplished"] ), "game[\"strings\"][\"" + team + "_mission_accomplished\"] does not exist" );
  3607. Assert( isdefined( game["strings"][ team + "_eliminated"] ), "game[\"strings\"][\"" + team + "_eliminated\"] does not exist" );
  3608. Assert( isdefined( game["strings"][ team + "_forfeited"] ), "game[\"strings\"][\"" + team + "_forfeited\"] does not exist" );
  3609. Assert( isdefined( game["strings"][ team + "_name"] ), "game[\"strings\"][\"" + team + "_name\"] does not exist" );
  3610. Assert( isdefined( game["music"]["spawn_" + team] ), "game[\"music\"][\"spawn_" + team + "\"] does not exist" );
  3611. Assert( isdefined( game["music"]["victory_" + team] ), "game[\"music\"][\"victory_" + team + "\"] does not exist" );
  3612. Assert( isdefined( game["icons"][team] ), "game[\"icons\"][\"" + team + "\"] does not exist" );
  3613. Assert( isdefined( game["voice"][team] ), "game[\"voice\"][\"" + team + "\"] does not exist" );
  3614. }
  3615. }
  3616.  
  3617. function anyTeamHasWaveDelay()
  3618. {
  3619. foreach ( team in level.teams )
  3620. {
  3621. if ( level.waveDelay[team] )
  3622. return true;
  3623. }
  3624.  
  3625. return false;
  3626. }
  3627.  
  3628. function Callback_StartGameType()
  3629. {
  3630. level.prematchRequirement = 0;
  3631. level.prematchPeriod = 0;
  3632. level.intermission = false;
  3633.  
  3634. setmatchflag( "cg_drawSpectatorMessages", 1 );
  3635. setmatchflag( "game_ended", 0 );
  3636.  
  3637. if ( !isdefined( game["gamestarted"] ) )
  3638. {
  3639. // defaults if not defined in level script
  3640. if ( !isdefined( game["allies"] ) )
  3641. game["allies"] = "seals";
  3642. if ( !isdefined( game["axis"] ) )
  3643. game["axis"] = "pmc";
  3644. if ( !isdefined( game["attackers"] ) )
  3645. game["attackers"] = "allies";
  3646. if ( !isdefined( game["defenders"] ) )
  3647. game["defenders"] = "axis";
  3648.  
  3649. // if this hits the teams are not setup right
  3650. assert( game["attackers"] != game["defenders"] );
  3651.  
  3652. // TODO MTEAM - need to update this valid team
  3653. foreach( team in level.teams )
  3654. {
  3655. if ( !isdefined( game[team] ) )
  3656. game[team] = "pmc";
  3657. }
  3658.  
  3659. if ( !isdefined( game["state"] ) )
  3660. game["state"] = "playing";
  3661.  
  3662. //makeDvarServerInfo( "cg_thirdPersonAngle", 354 );
  3663.  
  3664. SetDvar( "cg_thirdPersonAngle", 354 );
  3665.  
  3666. game["strings"]["press_to_spawn"] = &"PLATFORM_PRESS_TO_SPAWN";
  3667. if ( level.teamBased )
  3668. {
  3669. game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_TEAMS";
  3670. game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
  3671. }
  3672. else
  3673. {
  3674. game["strings"]["waiting_for_teams"] = &"MP_WAITING_FOR_PLAYERS";
  3675. game["strings"]["opponent_forfeiting_in"] = &"MP_OPPONENT_FORFEITING_IN";
  3676. }
  3677. game["strings"]["match_starting_in"] = &"MP_MATCH_STARTING_IN";
  3678. game["strings"]["spawn_next_round"] = &"MP_SPAWN_NEXT_ROUND";
  3679. game["strings"]["waiting_to_spawn"] = &"MP_WAITING_TO_SPAWN";
  3680. game["strings"]["waiting_to_spawn_ss"] = &"MP_WAITING_TO_SPAWN_SS";
  3681. //game["strings"]["waiting_to_safespawn"] = &"MP_WAITING_TO_SAFESPAWN";
  3682. game["strings"]["you_will_spawn"] = &"MP_YOU_WILL_RESPAWN";
  3683. game["strings"]["match_starting"] = &"MP_MATCH_STARTING";
  3684. game["strings"]["change_class"] = &"MP_CHANGE_CLASS_NEXT_SPAWN";
  3685. game["strings"]["last_stand"] = &"MPUI_LAST_STAND";
  3686.  
  3687. game["strings"]["cowards_way"] = &"PLATFORM_COWARDS_WAY_OUT";
  3688.  
  3689. game["strings"]["tie"] = &"MP_MATCH_TIE";
  3690. game["strings"]["round_draw"] = &"MP_ROUND_DRAW";
  3691.  
  3692. game["strings"]["enemies_eliminated"] = &"MP_ENEMIES_ELIMINATED";
  3693. game["strings"]["score_limit_reached"] = &"MP_SCORE_LIMIT_REACHED";
  3694. game["strings"]["round_score_limit_reached"] = &"MP_SCORE_LIMIT_REACHED";
  3695. game["strings"]["round_limit_reached"] = &"MP_ROUND_LIMIT_REACHED";
  3696. game["strings"]["time_limit_reached"] = &"MP_TIME_LIMIT_REACHED";
  3697. game["strings"]["players_forfeited"] = &"MP_PLAYERS_FORFEITED";
  3698. game["strings"]["other_teams_forfeited"] = &"MP_OTHER_TEAMS_FORFEITED";
  3699.  
  3700. assertTeamVariables();
  3701.  
  3702. [[level.onPrecacheGameType]]();
  3703.  
  3704. game["gamestarted"] = true;
  3705.  
  3706. game["totalKills"] = 0;
  3707.  
  3708. foreach( team in level.teams )
  3709. {
  3710. if ( !isdefined( game["migratedHost"] ) )
  3711. game["teamScores"][team] = 0;
  3712.  
  3713. game["teamSuddenDeath"][team] = false;
  3714.  
  3715. game["totalKillsTeam"][team] = 0;
  3716. }
  3717.  
  3718. level.prematchRequirement = GetGametypeSetting( "prematchRequirement" );
  3719. level.prematchPeriod = GetGametypeSetting( "prematchperiod" );
  3720.  
  3721. if ( GetDvarint( "xblive_clanmatch" ) != 0 )
  3722. {
  3723. // TODO MTEAM is this code used anymore?
  3724. foreach( team in level.teams )
  3725. {
  3726. game["icons"][team] = "composite_emblem_team_axis";
  3727. }
  3728.  
  3729. game["icons"]["allies"] = "composite_emblem_team_allies";
  3730. game["icons"]["axis"] = "composite_emblem_team_axis";
  3731. }
  3732. }
  3733. else
  3734. {
  3735. if ( !level.splitscreen )
  3736. level.prematchPeriod = GetGametypeSetting( "preroundperiod" );
  3737. }
  3738.  
  3739. DEFAULT( game["timepassed"], 0 );
  3740. DEFAULT( game["playabletimepassed"], 0 );
  3741. DEFAULT( game["roundsplayed"], 0 );
  3742.  
  3743. SetRoundsPlayed( game["roundsplayed"] );
  3744.  
  3745. if ( isdefined( game["overtime_round"] ) )
  3746. {
  3747. SetRoundsPlayed( game["roundsplayed"] + game["overtime_round"] - 1 );
  3748. SetMatchFlag( "overtime", 1 );
  3749. }
  3750. else
  3751. {
  3752. SetMatchFlag( "overtime", 0 );
  3753. }
  3754.  
  3755. if(!isdefined(game["roundwinner"] ))
  3756. game["roundwinner"] = [];
  3757.  
  3758. if(!isdefined(game["lastroundscore"] ))
  3759. game["lastroundscore"] = [];
  3760.  
  3761. if(!isdefined(game["roundswon"] ))
  3762. game["roundswon"] = [];
  3763.  
  3764. if(!isdefined(game["roundswon"]["tie"] ))
  3765. game["roundswon"]["tie"] = 0;
  3766.  
  3767. if(!isdefined(game["overtimeroundswon"] ))
  3768. game["overtimeroundswon"] = [];
  3769.  
  3770. if(!isdefined(game["overtimeroundswon"]["tie"] ))
  3771. game["overtimeroundswon"]["tie"] = 0;
  3772.  
  3773. foreach ( team in level.teams )
  3774. {
  3775. if(!isdefined(game["roundswon"][team] ))
  3776. game["roundswon"][team] = 0;
  3777. if(!isdefined(game["overtimeroundswon"][team] ))
  3778. game["overtimeroundswon"][team] = 0;
  3779.  
  3780. level.teamSpawnPoints[team] = [];
  3781. level.spawn_point_team_class_names[team] = [];
  3782. }
  3783.  
  3784. level.skipVote = false;
  3785. level.gameEnded = false;
  3786. level.exitLevel = false;
  3787. //level clientfield::set( "game_ended", 0 );
  3788. SetDvar( "g_gameEnded", 0 );
  3789.  
  3790. level.objIDStart = 0;
  3791. level.forcedEnd = false;
  3792. level.hostForcedEnd = false;
  3793.  
  3794. level.hardcoreMode = GetGametypeSetting( "hardcoreMode" );
  3795. if ( level.hardcoreMode )
  3796. {
  3797. /#print( "game mode: hardcore" );#/
  3798.  
  3799. //set up friendly fire delay for hardcore
  3800. if( !isdefined(level.friendlyFireDelayTime) )
  3801. level.friendlyFireDelayTime = 0;
  3802. }
  3803.  
  3804. if ( GetDvarString( "scr_max_rank" ) == "" )
  3805. SetDvar( "scr_max_rank", "0" );
  3806. level.rankCap = GetDvarint( "scr_max_rank" );
  3807.  
  3808. if ( GetDvarString( "scr_min_prestige" ) == "" )
  3809. {
  3810. SetDvar( "scr_min_prestige", "0" );
  3811. }
  3812. level.minPrestige = GetDvarint( "scr_min_prestige" );
  3813.  
  3814. // this gets set to false when someone takes damage or a gametype-specific event happens.
  3815. level.useStartSpawns = true;
  3816. level.alwaysUseStartSpawns = false;
  3817. level.useXCamsForEndGame = true;
  3818.  
  3819. level.cumulativeRoundScores = GetGametypeSetting( "cumulativeRoundScores" );
  3820.  
  3821. level.allowHitMarkers = GetGametypeSetting( "allowhitmarkers" );
  3822. level.playerQueuedRespawn = GetGametypeSetting( "playerQueuedRespawn" );
  3823. level.playerForceRespawn = GetGametypeSetting( "playerForceRespawn" );
  3824.  
  3825. level.roundStartExplosiveDelay = GetGametypeSetting( "roundStartExplosiveDelay" );
  3826. level.roundStartKillstreakDelay = GetGametypeSetting( "roundStartKillstreakDelay" );
  3827.  
  3828. level.perksEnabled = GetGametypeSetting( "perksEnabled" );
  3829. level.disableAttachments = GetGametypeSetting( "disableAttachments" );
  3830. level.disableTacInsert = GetGametypeSetting( "disableTacInsert" );
  3831. level.disableCAC = GetGametypeSetting( "disableCAC" );
  3832. level.disableClassSelection = GetGametypeSetting( "disableClassSelection" );
  3833. level.disableWeaponDrop = GetGametypeSetting( "disableweapondrop" );
  3834. level.onlyHeadShots = GetGametypeSetting( "onlyHeadshots" );
  3835.  
  3836. // set to 0 to disable
  3837. level.minimumAllowedTeamKills = GetGametypeSetting( "teamKillPunishCount" ) - 1;
  3838. level.teamKillReducedPenalty = GetGametypeSetting( "teamKillReducedPenalty" );
  3839. level.teamKillPointLoss = GetGametypeSetting( "teamKillPointLoss" );
  3840. level.teamKillSpawnDelay = GetGametypeSetting( "teamKillSpawnDelay" );
  3841.  
  3842. level.deathPointLoss = GetGametypeSetting( "deathPointLoss" );
  3843. level.leaderBonus = GetGametypeSetting( "leaderBonus" );
  3844. level.forceRadar = GetGametypeSetting( "forceRadar" );
  3845. level.playerSprintTime = GetGametypeSetting( "playerSprintTime" );
  3846. level.bulletDamageScalar = GetGametypeSetting( "bulletDamageScalar" );
  3847.  
  3848. level.playerMaxHealth = GetGametypeSetting( "playerMaxHealth" );
  3849. level.playerHealthRegenTime = GetGametypeSetting( "playerHealthRegenTime" );
  3850. level.scoreResetOnDeath = GetGametypeSetting( "scoreResetOnDeath" );
  3851.  
  3852. level.playerRespawnDelay = GetGametypeSetting( "playerRespawnDelay" );
  3853. level.playerIncrementalRespawnDelay = GetGametypeSetting( "incrementalSpawnDelay" );
  3854.  
  3855. level.playerObjectiveHeldRespawnDelay = GetGametypeSetting( "playerObjectiveHeldRespawnDelay" );
  3856. level.waveRespawnDelay = GetGametypeSetting( "waveRespawnDelay" );
  3857. level.suicideSpawnDelay = GetGametypeSetting( "spawnsuicidepenalty" );
  3858. level.teamKilledSpawnDelay = GetGametypeSetting( "spawnteamkilledpenalty" );
  3859. level.maxSuicidesBeforeKick = GetGametypeSetting( "maxsuicidesbeforekick" );
  3860.  
  3861. level.spectateType = GetGametypeSetting( "spectateType" );
  3862.  
  3863. level.voip = SpawnStruct();
  3864. level.voip.deadChatWithDead = GetGametypeSetting( "voipDeadChatWithDead" );
  3865. level.voip.deadChatWithTeam = GetGametypeSetting( "voipDeadChatWithTeam" );
  3866. level.voip.deadHearAllLiving = GetGametypeSetting( "voipDeadHearAllLiving" );
  3867. level.voip.deadHearTeamLiving = GetGametypeSetting( "voipDeadHearTeamLiving" );
  3868. level.voip.everyoneHearsEveryone = GetGametypeSetting( "voipEveryoneHearsEveryone" );
  3869. level.voip.deadHearKiller = GetGametypeSetting( "voipDeadHearKiller" );
  3870. level.voip.killersHearVictim = GetGametypeSetting( "voipKillersHearVictim" );
  3871.  
  3872. level.droppedTagRespawn = GetGametypeSetting( "droppedTagRespawn" );
  3873.  
  3874. if( IS_TRUE( level.droppedTagRespawn ) )
  3875. dogtags::init();
  3876.  
  3877. // this will clear out any non game mode entities before the gametype callbacks happen
  3878. gameobjects::main();
  3879.  
  3880. callback::callback( #"on_start_gametype" );
  3881.  
  3882. thread hud_message::init();
  3883.  
  3884. foreach( team in level.teams )
  3885. {
  3886. initTeamVariables( team );
  3887. }
  3888.  
  3889. if ( !level.teambased )
  3890. {
  3891. initTeamVariables( "free" );
  3892. }
  3893.  
  3894. level.maxPlayerCount = 0;
  3895. level.activePlayers = [];
  3896.  
  3897. level.aliveTimeMaxCount = 3;
  3898. level.aliveTimesAverage = [];
  3899. foreach( team in level.teams )
  3900. {
  3901. level.aliveTimesAverage[team] = 0;
  3902. }
  3903.  
  3904. if( !isdefined( level.livesDoNotReset ) || !level.livesDoNotReset )
  3905. {
  3906. foreach( team in level.teams )
  3907. {
  3908. game[team+"_lives"] = level.numTeamLives;
  3909. }
  3910. }
  3911.  
  3912. level.allowAnnouncer = GetGametypeSetting( "allowAnnouncer" );
  3913.  
  3914. if ( !isdefined( level.timeLimit ) )
  3915. util::registerTimeLimit( 1, 1440 );
  3916.  
  3917. if ( !isdefined( level.scoreLimit ) )
  3918. util::registerScoreLimit( 1, 500 );
  3919.  
  3920. if ( !isdefined( level.roundScoreLimit ) )
  3921. util::registerRoundScoreLimit( 0, 500 );
  3922.  
  3923. if ( !isdefined( level.roundLimit ) )
  3924. util::registerRoundLimit( 0, 10 );
  3925.  
  3926. if ( !isdefined( level.roundWinLimit ) )
  3927. util::registerRoundWinLimit( 0, 10 );
  3928.  
  3929. // The order the following functions are registered in are the order they will get called
  3930. globallogic_utils::registerPostRoundEvent( &killcam::post_round_final_killcam );
  3931.  
  3932. //makeDvarServerInfo( "ui_scorelimit" );
  3933. //makeDvarServerInfo( "ui_timelimit" );
  3934. //makeDvarServerInfo( "ui_allow_classchange", GetDvarString( "ui_allow_classchange" ) );
  3935.  
  3936. waveDelay = level.waveRespawnDelay;
  3937. if ( waveDelay )
  3938. {
  3939. foreach ( team in level.teams )
  3940. {
  3941. level.waveDelay[team] = waveDelay;
  3942. level.lastWave[team] = 0;
  3943. }
  3944.  
  3945. level thread [[level.waveSpawnTimer]]();
  3946. }
  3947.  
  3948. level.inPrematchPeriod = true;
  3949.  
  3950. if ( level.prematchPeriod > 2.0 && level.rankedMatch )
  3951. level.prematchPeriod = level.prematchPeriod + (randomFloat( 4 ) - 2); // live host obfuscation
  3952.  
  3953. if ( level.numLives || anyTeamHasWaveDelay() || level.playerQueuedRespawn )
  3954. level.gracePeriod = 15;
  3955. else
  3956. level.gracePeriod = 5;
  3957.  
  3958. level.inGracePeriod = true;
  3959.  
  3960. level.roundEndDelay = 5;
  3961. level.halftimeRoundEndDelay = 3;
  3962.  
  3963. globallogic_score::updateAllTeamScores();
  3964.  
  3965. level.killstreaksenabled = 1;
  3966. level.missileLockPlaySpaceCheckEnabled = true;
  3967. level.missileLockPlaySpaceCheckExtraRadius = 5000;
  3968.  
  3969. if ( GetDvarString( "scr_game_rankenabled" ) == "" )
  3970. SetDvar( "scr_game_rankenabled", true );
  3971. level.rankEnabled = GetDvarint( "scr_game_rankenabled" );
  3972.  
  3973. if ( GetDvarString( "scr_game_medalsenabled" ) == "" )
  3974. SetDvar( "scr_game_medalsenabled", true );
  3975. level.medalsEnabled = GetDvarint( "scr_game_medalsenabled" );
  3976.  
  3977. if( level.hardcoreMode && level.rankedMatch && GetDvarString( "scr_game_friendlyFireDelay" ) == "" )
  3978. SetDvar( "scr_game_friendlyFireDelay", true );
  3979. level.friendlyFireDelay = GetDvarint( "scr_game_friendlyFireDelay" );
  3980.  
  3981. // level gametype and features globals should be defaulted before this, and level.onstartgametype should reset them if desired
  3982. [[level.onStartGameType]]();
  3983.  
  3984. // disable killstreaks for custom game modes
  3985. if( GetDvarInt( "custom_killstreak_mode" ) == 1 )
  3986. {
  3987. level.killstreaksenabled = 0;
  3988. }
  3989.  
  3990. level thread killcam::do_final_killcam();
  3991.  
  3992. thread startGame();
  3993. level thread updateGameTypeDvars();
  3994. level thread simple_hostmigration::UpdateHostMigrationData();
  3995. }
  3996.  
  3997. function registerFriendlyFireDelay( dvarString, defaultValue, minValue, maxValue )
  3998. {
  3999. dvarString = ("scr_" + dvarString + "_friendlyFireDelayTime");
  4000. if ( GetDvarString( dvarString ) == "" )
  4001. SetDvar( dvarString, defaultValue );
  4002.  
  4003. if ( getDvarInt( dvarString ) > maxValue )
  4004. SetDvar( dvarString, maxValue );
  4005. else if ( getDvarInt( dvarString ) < minValue )
  4006. SetDvar( dvarString, minValue );
  4007.  
  4008. level.friendlyFireDelayTime = getDvarInt( dvarString );
  4009. }
  4010.  
  4011. function checkRoundSwitch()
  4012. {
  4013. if ( !isdefined( level.roundSwitch ) || !level.roundSwitch )
  4014. return false;
  4015. if ( !isdefined( level.onRoundSwitch ) )
  4016. return false;
  4017.  
  4018. assert( game["roundsplayed"] > 0 );
  4019.  
  4020. if ( game["roundsplayed"] % level.roundswitch == 0 )
  4021. {
  4022. [[level.onRoundSwitch]]();
  4023. return true;
  4024. }
  4025.  
  4026. return false;
  4027. }
  4028.  
  4029.  
  4030. function listenForGameEnd()
  4031. {
  4032. self waittill( "host_sucks_end_game" );
  4033. //if ( level.console )
  4034. // endparty();
  4035. level.skipVote = true;
  4036.  
  4037. if ( !level.gameEnded )
  4038. level thread globallogic::forceEnd(true);
  4039. }
  4040.  
  4041.  
  4042. function getKillStreaks( player )
  4043. {
  4044. for ( killstreakNum = 0; killstreakNum < level.maxKillstreaks; killstreakNum++ )
  4045. {
  4046. killstreak[ killstreakNum ] = "killstreak_null";
  4047. }
  4048.  
  4049. if ( isPlayer( player ) &&
  4050. level.disableClassSelection != 1 &&
  4051. !isdefined( player.pers["isBot"] ) &&
  4052. isdefined( player.killstreak) )
  4053. {
  4054. currentKillstreak = 0;
  4055. for ( killstreakNum = 0; killstreakNum < level.maxKillstreaks; killstreakNum++ )
  4056. {
  4057. if ( isdefined( player.killstreak[ killstreakNum ] ) )
  4058. {
  4059. killstreak[ currentKillstreak ] = player.killstreak[ killstreakNum ];
  4060. currentKillstreak++;
  4061. }
  4062. }
  4063. }
  4064.  
  4065. return killstreak;
  4066. }
  4067.  
  4068. function updateRankedMatch(winner)
  4069. {
  4070. if ( level.rankedMatch )
  4071. {
  4072. if ( hostIdledOut() )
  4073. {
  4074. level.hostForcedEnd = true;
  4075. /#print( "host idled out" );#/
  4076. endLobby();
  4077. }
  4078. }
  4079. globallogic_score::updateMatchBonusScores( winner );
  4080. }
  4081.  
  4082.  
  4083. function annihilatorGunPlayerKillEffect( attacker, weapon )
  4084. {
  4085. if ( weapon.fusetime != 0 )
  4086. wait( weapon.fusetime * 0.001 );
  4087. else
  4088. wait(0.45);
  4089.  
  4090. if ( !isdefined( self ) )
  4091. {
  4092. return;
  4093. }
  4094.  
  4095. self playsoundtoplayer( "evt_annihilation", attacker );
  4096. self playsoundtoallbutplayer( "evt_annihilation_npc", attacker );
  4097.  
  4098. CodeSetClientField(self, "annihilate_effect", 1);
  4099. self shake_and_rumble(0, 0.3, 0.75, 1);
  4100.  
  4101. wait 0.1;
  4102.  
  4103. if ( !isdefined( self ) )
  4104. {
  4105. return;
  4106. }
  4107.  
  4108. self NotSolid();
  4109. self Ghost();
  4110. }
  4111.  
  4112. function annihilatorGunActorKillEffect( attacker, weapon )
  4113. {
  4114. self waittill("actor_corpse",body); //now a corpse!
  4115.  
  4116. if ( weapon.fusetime != 0 )
  4117. wait( weapon.fusetime * 0.001 );
  4118. else
  4119. wait(0.45);
  4120.  
  4121. if ( !isdefined( self ) )
  4122. {
  4123. return;
  4124. }
  4125.  
  4126. self playsoundtoplayer( "evt_annihilation", attacker );
  4127. self playsoundtoallbutplayer( "evt_annihilation_npc", attacker );
  4128.  
  4129. if ( !isdefined( body ) )
  4130. {
  4131. return;
  4132. }
  4133.  
  4134. CodeSetClientField(body, "annihilate_effect", 1);
  4135. body shake_and_rumble(0, 0.6, 0.2, 1);
  4136. body NotSolid();
  4137. body Ghost();
  4138. }
  4139.  
  4140. function pineappleGunPlayerKillEffect( attacker )
  4141. {
  4142. wait 0.1;
  4143.  
  4144. if ( !isdefined( self ) )
  4145. {
  4146. return;
  4147. }
  4148.  
  4149. playsoundatposition ("evt_annihilation_npc", (self.origin));
  4150. CodeSetClientField(self, "pineapplegun_effect", 1);
  4151. self shake_and_rumble(0, 0.3, 0.35, 1);
  4152. wait 0.1;
  4153.  
  4154. if ( !isdefined( self ) )
  4155. {
  4156. return;
  4157. }
  4158.  
  4159. self NotSolid();
  4160. self Ghost();
  4161. }
  4162.  
  4163. function BowPlayerKillEffect()
  4164. {
  4165. wait 0.05;
  4166. if ( !isdefined( self ) )
  4167. {
  4168. return;
  4169. }
  4170.  
  4171. playsoundatposition ("evt_annihilation_npc", (self.origin));
  4172. CodeSetClientField(self, "annihilate_effect", 1);
  4173. self shake_and_rumble(0, 0.3, 0.35, 1);
  4174.  
  4175. if ( !isdefined( self ) )
  4176. {
  4177. return;
  4178. }
  4179.  
  4180. self NotSolid();
  4181. self Ghost();
  4182. }
  4183.  
  4184. function pineappleGunActorKillEffect()
  4185. {
  4186. self waittill("actor_corpse",body); //now a corpse!
  4187. wait(0.75);
  4188.  
  4189. if ( !isdefined( self ) )
  4190. {
  4191. return;
  4192. }
  4193.  
  4194. playsoundatposition ("evt_annihilation_npc", (self.origin));
  4195.  
  4196. if ( !isdefined( body ) )
  4197. {
  4198. return;
  4199. }
  4200.  
  4201. CodeSetClientField(body, "pineapplegun_effect", 1);
  4202. body shake_and_rumble(0, 0.3, 0.75, 1);
  4203. body NotSolid();
  4204. body Ghost();
  4205. }
  4206.  
  4207. // ============================================================================
  4208. // self = player
  4209. function shake_and_rumble( n_delay, shake_size, shake_time, rumble_num )
  4210. {
  4211. if( IsDefined(n_delay) && (n_delay > 0) )
  4212. {
  4213. wait( n_delay );
  4214. }
  4215.  
  4216. // Earthquake
  4217. nMagnitude = shake_size;
  4218. nduration = shake_time;
  4219. nRadius = 500;
  4220. v_pos = self.origin;
  4221. Earthquake( nMagnitude, nDuration, v_pos, nRadius );
  4222.  
  4223. // Pad Rumble
  4224. for( i=0; i<rumble_num; i++ )
  4225. {
  4226. self PlayRumbleOnEntity( "damage_heavy" );
  4227. wait( 0.1 );
  4228. }
  4229. }
  4230.  
  4231. function DoWeaponSpecificKillEffects(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
  4232. {
  4233. if( weapon.name=="hero_pineapplegun" && isPlayer( attacker ) && sMeansOfDeath == "MOD_GRENADE" )
  4234. {
  4235. attacker playLocalSound( "wpn_pineapple_grenade_explode_flesh_2D" );
  4236. }
  4237. }
  4238.  
  4239. #define ANNIHILATE_PUSH_SCALE 100
  4240. #define ANNIHILATE_UPPUSH_SCALE 25
  4241. function DoWeaponSpecificCorpseEffects(body, eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
  4242. {
  4243. if ( weapon.doannihilate&& isPlayer( attacker ) && ( sMeansOfDeath == "MOD_IMPACT" || sMeansOfDeath == "MOD_GRENADE" ) ) //this does the annihilation effect and launches ragdoll
  4244. {
  4245. if (IsActor(body))
  4246. {
  4247. body thread annihilatorGunActorKillEffect( attacker, weapon );
  4248. }
  4249. else
  4250. {
  4251. body thread annihilatorGunPlayerKillEffect( attacker, weapon );
  4252. }
  4253. }
  4254. else if( sMeansOfDeath == "MOD_BURNED" )
  4255. {
  4256. if( !IsActor(body) )
  4257. {
  4258. body thread BurnCorpse();
  4259. }
  4260. }
  4261. else if( weapon.isheroweapon == 1 && isPlayer( attacker ) )
  4262. {
  4263. /*if (weapon.name == "hero_pineapplegun" && sMeansOfDeath == "MOD_GRENADE") //this does an annilhation effect and launches ragdoll
  4264. {
  4265. //modify the launch direction to give it some up vector - John Woo style
  4266. newVector = ((0,0,1)*ANNIHILATE_UPPUSH_SCALE) + (vDir * ANNIHILATE_PUSH_SCALE);
  4267. body LaunchRagdoll( newVector, sHitLoc);
  4268. if (IsActor(body))
  4269. {
  4270. body thread pineappleGunActorKillEffect();
  4271. }
  4272. else
  4273. {
  4274. body thread pineappleGunPlayerKillEffect();
  4275. }
  4276. }
  4277. */
  4278. if ( weapon.name == "hero_firefly_swarm" )
  4279. {
  4280. value = RandomInt(2) + 1;
  4281. if( !IsActor(body) )
  4282. {
  4283. CodeSetClientField(body, "firefly_effect", value);
  4284. }
  4285. }
  4286. }
  4287. }
  4288.  
  4289. #define CORPSE_BURN_DURATION 3
  4290. function BurnCorpse()
  4291. {
  4292. self endon( "death" );
  4293. CodeSetClientField( self, "burned_effect", 1 );
  4294. wait( CORPSE_BURN_DURATION );
  4295. CodeSetClientField( self, "burned_effect", 0 );
  4296. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement