Advertisement
Guest User

Untitled

a guest
Sep 29th, 2010
370
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 40.78 KB | None | 0 0
  1. #include maps\mp\_utility;
  2. #include maps\mp\gametypes\_hud_util;
  3. #include common_scripts\utility;
  4.  
  5.  
  6. TimeUntilWaveSpawn( minimumWait )
  7. {
  8. if ( !self.hasSpawned )
  9. return 0;
  10.  
  11. // the time we'll spawn if we only wait the minimum wait.
  12. earliestSpawnTime = gettime() + minimumWait * 1000;
  13.  
  14. lastWaveTime = level.lastWave[self.pers["team"]];
  15. waveDelay = level.waveDelay[self.pers["team"]] * 1000;
  16.  
  17. // the number of waves that will have passed since the last wave happened, when the minimum wait is over.
  18. numWavesPassedEarliestSpawnTime = (earliestSpawnTime - lastWaveTime) / waveDelay;
  19. // rounded up
  20. numWaves = ceil( numWavesPassedEarliestSpawnTime );
  21.  
  22. timeOfSpawn = lastWaveTime + numWaves * waveDelay;
  23.  
  24. // don't push our spawn out because we watched killcam
  25. if ( isDefined( self.respawnTimerStartTime ) )
  26. {
  27. timeAlreadyPassed = (gettime() - self.respawnTimerStartTime) / 1000.0;
  28.  
  29. if ( self.respawnTimerStartTime < lastWaveTime )
  30. return 0;
  31. }
  32.  
  33. // avoid spawning everyone on the same frame
  34. if ( isdefined( self.waveSpawnIndex ) )
  35. timeOfSpawn += 50 * self.waveSpawnIndex;
  36.  
  37. return (timeOfSpawn - gettime()) / 1000;
  38. }
  39.  
  40. TeamKillDelay()
  41. {
  42. teamKills = self.pers["teamkills"];
  43.  
  44. if ( level.maxAllowedTeamKills < 0 || teamkills <= level.maxAllowedTeamKills )
  45. return 0;
  46.  
  47. exceeded = (teamkills - level.maxAllowedTeamKills);
  48. return maps\mp\gametypes\_tweakables::getTweakableValue( "team", "teamkillspawndelay" ) * exceeded;
  49. }
  50.  
  51.  
  52. TimeUntilSpawn( includeTeamkillDelay )
  53. {
  54. if ( (level.inGracePeriod && !self.hasSpawned) || level.gameended )
  55. return 0;
  56.  
  57. respawnDelay = 0;
  58. if ( self.hasSpawned )
  59. {
  60. result = self [[level.onRespawnDelay]]();
  61. if ( isDefined( result ) )
  62. respawnDelay = result;
  63. else
  64. respawnDelay = getDvarInt( "scr_" + level.gameType + "_playerrespawndelay" );
  65.  
  66. if ( includeTeamkillDelay && self.pers["teamKillPunish"] )
  67. respawnDelay += TeamKillDelay();
  68.  
  69. if ( isDefined( self.respawnTimerStartTime ) )
  70. {
  71. timeAlreadyPassed = (gettime() - self.respawnTimerStartTime) / 1000.0;
  72. respawnDelay -= timeAlreadyPassed;
  73. if ( respawnDelay < 0 )
  74. respawnDelay = 0;
  75. }
  76.  
  77. // Spawning with tactical insertion
  78. if ( isDefined( self.setSpawnPoint) )
  79. respawnDelay += level.tiSpawnDelay;
  80.  
  81. }
  82.  
  83. waveBased = (getDvarInt( "scr_" + level.gameType + "_waverespawndelay" ) > 0);
  84.  
  85. if ( waveBased )
  86. return self TimeUntilWaveSpawn( respawnDelay );
  87.  
  88. return respawnDelay;
  89. }
  90.  
  91.  
  92. maySpawn()
  93. {
  94. if ( getGametypeNumLives() || isDefined( level.disableSpawning ) )
  95. {
  96. if ( isDefined( level.disableSpawning ) && level.disableSpawning )
  97. return false;
  98.  
  99. if ( self.pers["teamKillPunish"] )
  100. return false;
  101.  
  102. if ( !self.pers["lives"] && gameHasStarted() )
  103. {
  104. return false;
  105. }
  106. else if ( gameHasStarted() )
  107. {
  108. // disallow spawning for late comers
  109. if ( !level.inGracePeriod && !self.hasSpawned )
  110. return false;
  111. }
  112. }
  113. return true;
  114. }
  115.  
  116.  
  117. spawnClient()
  118. {
  119. assert( isDefined( self.team ) );
  120. assert( isValidClass( self.class ) );
  121.  
  122. if ( !self maySpawn() )
  123. {
  124. currentorigin = self.origin;
  125. currentangles = self.angles;
  126.  
  127. self notify ( "attempted_spawn" );
  128.  
  129. if ( self.pers["teamKillPunish"] )
  130. {
  131. self.pers["teamkills"] = max( self.pers["teamkills"] - 1, 0 );
  132. setLowerMessage( "friendly_fire", &"MP_FRIENDLY_FIRE_WILL_NOT" );
  133.  
  134. if ( !self.hasSpawned && self.pers["teamkills"] <= level.maxAllowedTeamkills )
  135. self.pers["teamKillPunish"] = false;
  136.  
  137. }
  138. else if ( isRoundBased() && !isLastRound() )
  139. {
  140. setLowerMessage( "spawn_info", game["strings"]["spawn_next_round"] );
  141. self thread removeSpawnMessageShortly( 3.0 );
  142. }
  143.  
  144. self thread spawnSpectator( currentorigin + (0, 0, 60), currentangles );
  145. return;
  146. }
  147.  
  148. if ( self.waitingToSpawn )
  149. return;
  150.  
  151. self.waitingToSpawn = true;
  152.  
  153. self waitAndSpawnClient();
  154.  
  155. if ( isdefined( self ) )
  156. self.waitingToSpawn = false;
  157. }
  158.  
  159.  
  160. waitAndSpawnClient()
  161. {
  162. self endon ( "disconnect" );
  163. self endon ( "end_respawn" );
  164. level endon ( "game_ended" );
  165.  
  166. self notify ( "attempted_spawn" );
  167.  
  168. spawnedAsSpectator = false;
  169.  
  170. if ( self.pers["teamKillPunish"] )
  171. {
  172. teamKillDelay = TeamKillDelay();
  173.  
  174. if ( teamKillDelay > 0 )
  175. {
  176. setLowerMessage( "friendly_fire", &"MP_FRIENDLY_FIRE_WILL_NOT", teamKillDelay );
  177.  
  178. self thread respawn_asSpectator( self.origin + (0, 0, 60), self.angles );
  179. spawnedAsSpectator = true;
  180.  
  181. wait( teamKillDelay );
  182. clearLowerMessage( "friendly_fire" );
  183. self.respawnTimerStartTime = gettime();
  184. }
  185.  
  186. self.pers["teamKillPunish"] = false;
  187. }
  188. else if ( TeamKillDelay() )
  189. {
  190. self.pers["teamkills"] = max( self.pers["teamkills"] - 1, 0 );
  191. }
  192.  
  193. // for missiles, helicopters, ac130, etc...
  194. if ( self isUsingRemote() )
  195. {
  196. self waittill ( "stopped_using_remote" );
  197. }
  198.  
  199. if ( !isdefined( self.waveSpawnIndex ) && isdefined( level.wavePlayerSpawnIndex[self.team] ) )
  200. {
  201. self.waveSpawnIndex = level.wavePlayerSpawnIndex[self.team];
  202. level.wavePlayerSpawnIndex[self.team]++;
  203. }
  204.  
  205. timeUntilSpawn = TimeUntilSpawn( false );
  206.  
  207. self thread predictAboutToSpawnPlayerOverTime( timeUntilSpawn );
  208.  
  209. if ( timeUntilSpawn > 0 )
  210. {
  211. // spawn player into spectator on death during respawn delay, if he switches teams during this time, he will respawn next round
  212. setLowerMessage( "spawn_info", game["strings"]["waiting_to_spawn"], timeUntilSpawn );
  213.  
  214. if ( !spawnedAsSpectator )
  215. self thread respawn_asSpectator( self.origin + (0, 0, 60), self.angles );
  216. spawnedAsSpectator = true;
  217.  
  218. self waitForTimeOrNotify( timeUntilSpawn, "force_spawn" );
  219.  
  220. self notify("stop_wait_safe_spawn_button");
  221. }
  222.  
  223. waveBased = (getDvarInt( "scr_" + level.gameType + "_waverespawndelay" ) > 0);
  224. if ( maps\mp\gametypes\_tweakables::getTweakableValue( "player", "forcerespawn" ) == 0 && self.hasSpawned && !waveBased && !self.wantSafeSpawn )
  225. {
  226. setLowerMessage( "spawn_info", game["strings"]["press_to_spawn"] );
  227.  
  228. if ( !spawnedAsSpectator )
  229. self thread respawn_asSpectator( self.origin + (0, 0, 60), self.angles );
  230. spawnedAsSpectator = true;
  231.  
  232. self waitRespawnButton();
  233. }
  234.  
  235. // do not wait after this point
  236.  
  237. self.waitingToSpawn = false;
  238.  
  239. self clearLowerMessage( "spawn_info" );
  240.  
  241. self.waveSpawnIndex = undefined;
  242.  
  243. self thread spawnPlayer();
  244. }
  245.  
  246.  
  247. waitRespawnButton()
  248. {
  249. self endon("disconnect");
  250. self endon("end_respawn");
  251.  
  252. while (1)
  253. {
  254. if ( self useButtonPressed() )
  255. break;
  256.  
  257. wait .05;
  258. }
  259. }
  260.  
  261.  
  262. removeSpawnMessageShortly( delay )
  263. {
  264. self endon ( "disconnect" );
  265. level endon ( "game_ended" );
  266.  
  267. waittillframeend; // so we don't endon the end_respawn from spawning as a spectator
  268.  
  269. self endon("end_respawn");
  270.  
  271. wait delay;
  272.  
  273. self clearLowerMessage( "spawn_info", 2.0 );
  274. }
  275.  
  276.  
  277. lastStandRespawnPlayer()
  278. {
  279. self LastStandRevive();
  280.  
  281. if ( self _hasPerk( "specialty_finalstand" ) && !level.dieHardMode )
  282. self _unsetPerk( "specialty_finalstand" );
  283.  
  284. if ( level.dieHardMode )
  285. self.headicon = "";
  286.  
  287. self setStance( "crouch" );
  288. self.revived = true;
  289.  
  290. self notify ( "revive" );
  291.  
  292. // should only be defined if level.diehardmode
  293. if ( isDefined( self.standardmaxHealth ) )
  294. self.maxHealth = self.standardMaxHealth;
  295.  
  296. self.health = self.maxHealth;
  297. self _enableUsability();
  298.  
  299. if ( game["state"] == "postgame" )
  300. {
  301. assert( !level.intermission );
  302. // We're in the victory screen, but before intermission
  303. self maps\mp\gametypes\_gamelogic::freezePlayerForRoundEnd();
  304. }
  305. }
  306.  
  307. getDeathSpawnPoint()
  308. {
  309. spawnpoint = spawn( "script_origin", self.origin );
  310. spawnpoint hide();
  311. spawnpoint.angles = self.angles;
  312. return spawnpoint;
  313.  
  314. }
  315.  
  316. showSpawnNotifies()
  317. {
  318. if ( isDefined( game["defcon"] ) )
  319. thread maps\mp\gametypes\_hud_message::defconSplashNotify( game["defcon"], false );
  320.  
  321. if ( self isRested() )
  322. thread maps\mp\gametypes\_hud_message::splashNotify( "rested" );
  323. }
  324.  
  325.  
  326. predictAboutToSpawnPlayerOverTime( preduration )
  327. {
  328. self endon( "disconnect" );
  329. self endon( "spawned" );
  330. self endon( "used_predicted_spawnpoint" );
  331. self notify( "predicting_about_to_spawn_player" );
  332. self endon( "predicting_about_to_spawn_player" );
  333.  
  334. if ( preduration <= 0 )
  335. return; // no point predicting if no time will pass. (if time until spawn is unknown, use 0.1)
  336.  
  337. if ( preduration > 1.0 )
  338. wait preduration - 1.0;
  339.  
  340. self predictAboutToSpawnPlayer();
  341.  
  342. self PredictStreamPos( self.predictedSpawnPoint.origin + (0,0,60), self.predictedSpawnPoint.angles );
  343. self.predictedSpawnPointTime = gettime();
  344.  
  345. for ( i = 0; i < 30; i++ )
  346. {
  347. wait .4; // this time is carefully selected: we want it as long as possible, but we want the loop to iterate about .1 to .3 seconds before people spawn for our final check
  348.  
  349. prevPredictedSpawnPoint = self.predictedSpawnPoint;
  350. self predictAboutToSpawnPlayer();
  351.  
  352. if ( self.predictedSpawnPoint != prevPredictedSpawnPoint )
  353. {
  354. self PredictStreamPos( self.predictedSpawnPoint.origin + (0,0,60), self.predictedSpawnPoint.angles );
  355. self.predictedSpawnPointTime = gettime();
  356. }
  357. }
  358. }
  359.  
  360. predictAboutToSpawnPlayer()
  361. {
  362. assert( !isReallyAlive( self ) );
  363.  
  364. // test predicting spawnpoints to see if we can eliminate streaming pops
  365.  
  366. if ( self TimeUntilSpawn( true ) > 1.0 )
  367. {
  368. spawnpointname = "mp_global_intermission";
  369. spawnpoints = getentarray(spawnpointname, "classname");
  370. assert( spawnpoints.size );
  371. self.predictedSpawnPoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random(spawnpoints);
  372. return;
  373. }
  374.  
  375. if ( isDefined( self.setSpawnPoint ) )
  376. {
  377. self.predictedSpawnPoint = self.setSpawnPoint;
  378. return;
  379. }
  380. spawnPoint = self [[level.getSpawnPoint]]();
  381. self.predictedSpawnPoint = spawnPoint;
  382. }
  383.  
  384. checkPredictedSpawnpointCorrectness( spawnpointorigin )
  385. {
  386. /#
  387. if ( !isdefined( level.spawnpointPrediction ) )
  388. {
  389. level.spawnpointPrediction = spawnstruct();
  390. level.spawnpointPrediction.failures = 0;
  391. for ( i = 0; i < 7; i++ )
  392. level.spawnpointPrediction.buckets[i] = 0;
  393. }
  394.  
  395. if ( !isdefined( self.predictedSpawnPoint ) )
  396. {
  397. println( "Failed to predict spawn for player " + self.name + " at " + spawnpointorigin );
  398. level.spawnpointPrediction.failures++;
  399. }
  400. else
  401. {
  402. dist = distance( self.predictedSpawnPoint.origin, spawnpointorigin );
  403. if ( dist <= 0 )
  404. level.spawnpointPrediction.buckets[0]++;
  405. else if ( dist <= 128 )
  406. level.spawnpointPrediction.buckets[1]++;
  407. else if ( dist <= 256 )
  408. level.spawnpointPrediction.buckets[2]++;
  409. else if ( dist <= 512 )
  410. level.spawnpointPrediction.buckets[3]++;
  411. else if ( dist <= 1024 )
  412. level.spawnpointPrediction.buckets[4]++;
  413. else if ( dist <= 2048 )
  414. level.spawnpointPrediction.buckets[5]++;
  415. else
  416. level.spawnpointPrediction.buckets[6]++;
  417.  
  418. if ( dist > 0 )
  419. println( "Predicted player " + self.name + " would spawn at " + self.predictedSpawnPoint.origin + ", but spawned " + dist + " units away at " + spawnpointorigin );
  420. else
  421. println( "Predicted " + self.name + "'s spawn " + ((gettime() - self.predictedSpawnPointTime) / 1000) + " seconds ahead of time" );
  422. }
  423. #/
  424.  
  425. self notify( "used_predicted_spawnpoint" );
  426. self.predictedSpawnPoint = undefined;
  427. }
  428.  
  429. percentage( a, b )
  430. {
  431. return a + " (" + int(a / b * 100) + "%)";
  432. }
  433.  
  434. printPredictedSpawnpointCorrectness()
  435. {
  436. /#
  437. if ( !isdefined( level.spawnpointPrediction ) )
  438. return;
  439.  
  440. total = level.spawnpointPrediction.failures;
  441. for ( i = 0; i < 7; i++ )
  442. total += level.spawnpointPrediction.buckets[i];
  443.  
  444. if ( total <= 0 )
  445. return;
  446.  
  447. println( "****** Spawnpoint Prediction *******" );
  448. println( "There were " + total + " spawns. " + percentage( level.spawnpointPrediction.failures, total ) + " failed to be predicted." );
  449.  
  450. total -= level.spawnpointPrediction.failures;
  451. if ( total > 0 )
  452. {
  453. println( "Out of the predicted ones..." );
  454.  
  455. println( " " + percentage( level.spawnpointPrediction.buckets[0], total ) + " were perfect" );
  456. println( " " + percentage( level.spawnpointPrediction.buckets[1], total ) + " were within 128 units" );
  457. println( " " + percentage( level.spawnpointPrediction.buckets[2], total ) + " were within 256 units" );
  458. println( " " + percentage( level.spawnpointPrediction.buckets[3], total ) + " were within 512 units" );
  459. println( " " + percentage( level.spawnpointPrediction.buckets[4], total ) + " were within 1024 units" );
  460. println( " " + percentage( level.spawnpointPrediction.buckets[5], total ) + " were within 2048 units" );
  461. println( " " + percentage( level.spawnpointPrediction.buckets[6], total ) + " were beyond 2048 units" );
  462. }
  463.  
  464. println( "*************" );
  465. #/
  466. }
  467.  
  468. getSpawnOrigin( spawnpoint )
  469. {
  470. if ( !positionWouldTelefrag( spawnpoint.origin ) )
  471. return spawnpoint.origin;
  472.  
  473. if ( !isdefined( spawnpoint.alternates ) )
  474. return spawnpoint.origin;
  475.  
  476. foreach( alternate in spawnpoint.alternates )
  477. {
  478. if ( !positionWouldTelefrag( alternate ) )
  479. return alternate;
  480. }
  481.  
  482. return spawnpoint.origin;
  483. }
  484.  
  485. tiValidationCheck()
  486. {
  487. if ( !isDefined( self.setSpawnPoint ) )
  488. return false;
  489.  
  490. carePackages = getEntArray( "care_package", "targetname" );
  491.  
  492. foreach ( package in carePackages )
  493. {
  494. if ( distance( package.origin, self.setSpawnPoint.playerSpawnPos ) > 64 )
  495. continue;
  496.  
  497. if ( isDefined( package.owner ) )
  498. self maps\mp\gametypes\_hud_message::playerCardSplashNotify( "destroyed_insertion", package.owner );
  499.  
  500. maps\mp\perks\_perkfunctions::deleteTI( self.setSpawnpoint );
  501. return false;
  502. }
  503.  
  504. return true;
  505. }
  506.  
  507. spawnPlayer()
  508. {
  509. self endon( "disconnect" );
  510. self endon( "joined_spectators" );
  511. self notify( "spawned" );
  512. self notify( "end_respawn" );
  513.  
  514. if ( isDefined( self.setSpawnPoint ) && self tiValidationCheck() )
  515. {
  516. spawnPoint = self.setSpawnPoint;
  517.  
  518. self playLocalSound( "tactical_spawn" );
  519.  
  520. if ( level.teamBased )
  521. self playSoundToTeam( "tactical_spawn", level.otherTeam[self.team] );
  522. else
  523. self playSound( "tactical_spawn" );
  524.  
  525. assert( isDefined( spawnPoint.playerSpawnPos ) );
  526. assert( isDefined( spawnPoint.angles ) );
  527.  
  528. spawnOrigin = self.setSpawnPoint.playerSpawnPos;
  529. spawnAngles = self.setSpawnPoint.angles;
  530.  
  531. if ( isDefined( self.setSpawnPoint.enemyTrigger ) )
  532. self.setSpawnPoint.enemyTrigger Delete();
  533.  
  534. self.setSpawnPoint delete();
  535.  
  536. spawnPoint = undefined;
  537. }
  538. else
  539. {
  540. spawnPoint = self [[level.getSpawnPoint]]();
  541.  
  542. assert( isDefined( spawnPoint ) );
  543. assert( isDefined( spawnPoint.origin ) );
  544. assert( isDefined( spawnPoint.angles ) );
  545.  
  546. spawnOrigin = spawnpoint.origin;
  547. spawnAngles = spawnpoint.angles;
  548. }
  549.  
  550.  
  551. self setSpawnVariables();
  552.  
  553. /#
  554. if ( !getDvarInt( "scr_forcerankedmatch" ) )
  555. assert( (level.teamBased && self.sessionteam == self.team) || (!level.teamBased && self.sessionteam == "none") );
  556. #/
  557.  
  558. hadSpawned = self.hasSpawned;
  559.  
  560. self.fauxDead = undefined;
  561.  
  562. self.killsThisLife = [];
  563.  
  564. self updateSessionState( "playing", "" );
  565. self ClearKillcamState();
  566. self.cancelkillcam = 1;
  567. self openMenu( "killedby_card_hide" );
  568.  
  569. self.maxhealth = maps\mp\gametypes\_tweakables::getTweakableValue( "player", "maxhealth" );
  570.  
  571. self.health = self.maxhealth;
  572.  
  573. self.friendlydamage = undefined;
  574. self.hasSpawned = true;
  575. self.spawnTime = getTime();
  576. self.wasTI = !isDefined( spawnPoint );
  577. self.afk = false;
  578. self.lastStand = undefined;
  579. self.infinalStand = undefined;
  580. self.inC4Death = undefined;
  581. self.damagedPlayers = [];
  582. self.moveSpeedScaler = 1;
  583. self.killStreakScaler = 1;
  584. self.xpScaler = 1;
  585. self.objectiveScaler = 1;
  586. self.inLastStand = false;
  587. self.clampedHealth = undefined;
  588. self.shieldDamage = 0;
  589. self.shieldBulletHits = 0;
  590. self.recentShieldXP = 0;
  591.  
  592. self.disabledWeapon = 0;
  593. self.disabledWeaponSwitch = 0;
  594. self.disabledOffhandWeapons = 0;
  595. self resetUsability();
  596.  
  597. if ( self.pers["lives"] == getGametypeNumLives() )
  598. {
  599. maps\mp\gametypes\_playerlogic::addToLivesCount();
  600. }
  601.  
  602. if ( self.pers["lives"] )
  603. self.pers["lives"]--;
  604.  
  605. self maps\mp\gametypes\_playerlogic::addToAliveCount();
  606.  
  607. if ( !hadSpawned || gameHasStarted() || (gameHasStarted() && level.inGracePeriod && self.hasDoneCombat) )
  608. self maps\mp\gametypes\_playerlogic::removeFromLivesCount();
  609.  
  610. if ( !self.wasAliveAtMatchStart )
  611. {
  612. acceptablePassedTime = 20;
  613. if ( getTimeLimit() > 0 && acceptablePassedTime < getTimeLimit() * 60 / 4 )
  614. acceptablePassedTime = getTimeLimit() * 60 / 4;
  615.  
  616. if ( level.inGracePeriod || getTimePassed() < acceptablePassedTime * 1000 )
  617. self.wasAliveAtMatchStart = true;
  618. }
  619.  
  620. self setClientDvar( "cg_thirdPerson", "0" );
  621. self setDepthOfField( 0, 0, 512, 512, 4, 0 );
  622. self setClientDvar( "cg_fov", "65" );
  623.  
  624. // Don't do this stuff for TI spawn points
  625. if ( isDefined( spawnPoint ) )
  626. {
  627. self maps\mp\gametypes\_spawnlogic::finalizeSpawnpointChoice( spawnpoint );
  628. spawnOrigin = getSpawnOrigin( spawnpoint );
  629. spawnAngles = spawnpoint.angles;
  630. }
  631. else
  632. {
  633. // the only useful part of finalizeSpawnpointChoice() when using tactical insertion
  634. self.lastSpawnTime = getTime();
  635. }
  636.  
  637. self.spawnPos = spawnOrigin;
  638.  
  639. self spawn( spawnOrigin, spawnAngles );
  640. [[level.onSpawnPlayer]]();
  641.  
  642. // Don't do this stuff for TI spawn points
  643. if ( isDefined( spawnPoint ) )
  644. self checkPredictedSpawnpointCorrectness( spawnPoint.origin );
  645.  
  646. self maps\mp\gametypes\_missions::playerSpawned();
  647.  
  648. prof_begin( "spawnPlayer_postUTS" );
  649.  
  650. assert( isValidClass( self.class ) );
  651.  
  652. self maps\mp\gametypes\_class::setClass( self.class );
  653. self maps\mp\gametypes\_class::giveLoadout( self.team, self.class );
  654.  
  655. if ( getDvarInt( "camera_thirdPerson" ) )
  656. self setThirdPersonDOF( true );
  657.  
  658. if ( !gameFlag( "prematch_done" ) )
  659. self freezeControlsWrapper( true );
  660. else
  661. self freezeControlsWrapper( false );
  662.  
  663. if ( !gameFlag( "prematch_done" ) || !hadSpawned && game["state"] == "playing" )
  664. {
  665. self setClientDvar( "scr_objectiveText", getObjectiveHintText( self.pers["team"] ) );
  666.  
  667. team = self.pers["team"];
  668.  
  669. if ( game["status"] == "overtime" )
  670. thread maps\mp\gametypes\_hud_message::oldNotifyMessage( game["strings"]["overtime"], game["strings"]["overtime_hint"], undefined, (1, 0, 0), "mp_last_stand" );
  671. else if ( getIntProperty( "useRelativeTeamColors", 0 ) )
  672. thread maps\mp\gametypes\_hud_message::oldNotifyMessage( game["strings"][team + "_name"], undefined, game["icons"][team] + "_blue", game["colors"]["blue"] );
  673. else
  674. thread maps\mp\gametypes\_hud_message::oldNotifyMessage( game["strings"][team + "_name"], undefined, game["icons"][team], game["colors"][team] );
  675.  
  676. thread showSpawnNotifies();
  677. }
  678.  
  679. if ( !level.splitscreen && getIntProperty( "scr_showperksonspawn", 1 ) == 1 && game["state"] != "postgame" )
  680. {
  681. self openMenu( "perk_display" );
  682. self thread hidePerksAfterTime( 5.0 );
  683. self thread hidePerksOnDeath();
  684. }
  685.  
  686. prof_end( "spawnPlayer_postUTS" );
  687.  
  688. //self logstring( "S " + self.origin[0] + " " + self.origin[1] + " " + self.origin[2] );
  689.  
  690. // give "connected" handlers a chance to start
  691. // many of these start onPlayerSpawned handlers which rely on the "spawned_player"
  692. // notify which can happen on the same frame as the "connected" notify
  693. waittillframeend;
  694.  
  695. self notify( "spawned_player" );
  696. level notify ( "player_spawned", self );
  697.  
  698. if ( game["state"] == "postgame" )
  699. {
  700. assert( !level.intermission );
  701. // We're in the victory screen, but before intermission
  702. self maps\mp\gametypes\_gamelogic::freezePlayerForRoundEnd();
  703. }
  704. }
  705.  
  706. hidePerksAfterTime( delay )
  707. {
  708. self endon("disconnect");
  709. self endon("perks_hidden");
  710.  
  711. wait delay;
  712.  
  713. self openMenu( "perk_hide" );
  714. self notify("perks_hidden");
  715. }
  716.  
  717. hidePerksOnDeath()
  718. {
  719. self endon("disconnect");
  720. self endon("perks_hidden");
  721.  
  722. self waittill("death");
  723.  
  724. self openMenu( "perk_hide" );
  725. self notify("perks_hidden");
  726. }
  727.  
  728. hidePerksOnKill()
  729. {
  730. self endon("disconnect");
  731. self endon("death");
  732. self endon("perks_hidden");
  733.  
  734. self waittill( "killed_player" );
  735.  
  736. self openMenu( "perk_hide" );
  737. self notify("perks_hidden");
  738. }
  739.  
  740.  
  741. spawnSpectator( origin, angles )
  742. {
  743. self notify("spawned");
  744. self notify("end_respawn");
  745. in_spawnSpectator( origin, angles );
  746. }
  747.  
  748. // spawnSpectator clone without notifies for spawning between respawn delays
  749. respawn_asSpectator( origin, angles )
  750. {
  751. in_spawnSpectator( origin, angles );
  752. }
  753.  
  754. // spawnSpectator helper
  755. in_spawnSpectator( origin, angles )
  756. {
  757. self setSpawnVariables();
  758.  
  759. // don't clear lower message if not actually a spectator,
  760. // because it probably has important information like when we'll spawn
  761. if ( isDefined( self.pers["team"] ) && self.pers["team"] == "spectator" && !level.gameEnded )
  762. self clearLowerMessage( "spawn_info" );
  763.  
  764. self.sessionstate = "spectator";
  765. self ClearKillcamState();
  766. self.friendlydamage = undefined;
  767.  
  768. if( isDefined( self.pers["team"] ) && self.pers["team"] == "spectator" )
  769. self.statusicon = "";
  770. else
  771. self.statusicon = "hud_status_dead";
  772.  
  773. maps\mp\gametypes\_spectating::setSpectatePermissions();
  774.  
  775. onSpawnSpectator( origin, angles );
  776.  
  777. if ( level.teamBased && !level.splitscreen )
  778. self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
  779. }
  780.  
  781.  
  782. getPlayerFromClientNum( clientNum )
  783. {
  784. if ( clientNum < 0 )
  785. return undefined;
  786.  
  787. for ( i = 0; i < level.players.size; i++ )
  788. {
  789. if ( level.players[i] getEntityNumber() == clientNum )
  790. return level.players[i];
  791. }
  792. return undefined;
  793. }
  794.  
  795.  
  796. onSpawnSpectator( origin, angles)
  797. {
  798. if( isDefined( origin ) && isDefined( angles ) )
  799. {
  800. self SetSpectateDefaults( origin, angles );
  801. self spawn(origin, angles);
  802.  
  803. self checkPredictedSpawnpointCorrectness( origin );
  804. return;
  805. }
  806.  
  807. spawnpointname = "mp_global_intermission";
  808. spawnpoints = getentarray(spawnpointname, "classname");
  809. assert( spawnpoints.size );
  810. spawnpoint = maps\mp\gametypes\_spawnlogic::getSpawnpoint_Random(spawnpoints);
  811.  
  812. self SetSpectateDefaults(spawnpoint.origin, spawnpoint.angles);
  813. self spawn(spawnpoint.origin, spawnpoint.angles);
  814.  
  815. self checkPredictedSpawnpointCorrectness( spawnpoint.origin );
  816. }
  817.  
  818.  
  819. spawnIntermission()
  820. {
  821. self endon( "disconnect" );
  822.  
  823. self notify( "spawned" );
  824. self notify( "end_respawn" );
  825.  
  826. self setSpawnVariables();
  827. self closepopupMenu();
  828. self closeInGameMenu();
  829.  
  830. self clearLowerMessages();
  831.  
  832. self freezeControlsWrapper( true );
  833.  
  834. self setClientDvar( "cg_everyoneHearsEveryone", 1 );
  835.  
  836. if ( level.rankedMatch && ( self.postGamePromotion || self.pers["postGameChallenges"] ) )
  837. {
  838. if ( self.postGamePromotion )
  839. self playLocalSound( "mp_level_up" );
  840. else
  841. self playLocalSound( "mp_challenge_complete" );
  842.  
  843. if ( self.postGamePromotion > level.postGameNotifies )
  844. level.postGameNotifies = 1;
  845.  
  846. if ( self.pers["postGameChallenges"] > level.postGameNotifies )
  847. level.postGameNotifies = self.pers["postGameChallenges"];
  848.  
  849. self closepopupMenu();
  850. self closeInGameMenu();
  851.  
  852. self openMenu( game["menu_endgameupdate"] );
  853.  
  854. waitTime = 4.0 + min( self.pers["postGameChallenges"], 3 );
  855. while ( waitTime )
  856. {
  857. wait ( 0.25 );
  858. waitTime -= 0.25;
  859.  
  860. self openMenu( game["menu_endgameupdate"] );
  861. }
  862.  
  863. self closeMenu( game["menu_endgameupdate"] );
  864. }
  865.  
  866. self.sessionstate = "intermission";
  867. self ClearKillcamState();
  868. self.friendlydamage = undefined;
  869.  
  870. spawnPoints = getEntArray( "mp_global_intermission", "classname" );
  871. assertEx( spawnPoints.size, "NO mp_global_intermission SPAWNPOINTS IN MAP" );
  872.  
  873. spawnPoint = spawnPoints[0];
  874. self spawn( spawnPoint.origin, spawnPoint.angles );
  875.  
  876. self checkPredictedSpawnpointCorrectness( spawnPoint.origin );
  877.  
  878. self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
  879. }
  880.  
  881.  
  882. spawnEndOfGame()
  883. {
  884. if ( 1 )
  885. {
  886. self freezeControlsWrapper( true );
  887. self spawnSpectator();
  888. self freezeControlsWrapper( true );
  889. return;
  890. }
  891.  
  892. self notify("spawned");
  893. self notify("end_respawn");
  894.  
  895. self setSpawnVariables();
  896. self closepopupMenu();
  897. self closeInGameMenu();
  898.  
  899. self clearLowerMessages();
  900.  
  901. self setClientDvar( "cg_everyoneHearsEveryone", 1 );
  902.  
  903. self.sessionstate = "dead";
  904. self ClearKillcamState();
  905. self.friendlydamage = undefined;
  906.  
  907. spawnPoints = getEntArray( "mp_global_intermission", "classname" );
  908. assertEx( spawnPoints.size, "NO mp_global_intermission SPAWNPOINTS IN MAP" );
  909.  
  910. spawnPoint = spawnPoints[0];
  911. self spawn( spawnPoint.origin, spawnPoint.angles );
  912.  
  913. self checkPredictedSpawnpointCorrectness( spawnPoint.origin );
  914.  
  915. spawnPoint setModel( "tag_origin" );
  916.  
  917. //self playerLinkTo( spawnPoint, "tag_origin", (0,0,0), spawnPoint.angles );
  918. self playerLinkTo( spawnPoint );
  919.  
  920. self PlayerHide();
  921. self freezeControlsWrapper( true );
  922.  
  923. self setDepthOfField( 0, 128, 512, 4000, 6, 1.8 );
  924. }
  925.  
  926.  
  927. setSpawnVariables()
  928. {
  929. // Stop shellshock and rumble
  930. self StopShellshock();
  931. self StopRumble( "damage_heavy" );
  932. }
  933.  
  934.  
  935. notifyConnecting()
  936. {
  937. waittillframeend;
  938.  
  939. if( isDefined( self ) )
  940. level notify( "connecting", self );
  941. }
  942.  
  943.  
  944. Callback_PlayerDisconnect()
  945. {
  946. if ( !isDefined( self.connected ) )
  947. return;
  948.  
  949. self removePlayerOnDisconnect();
  950.  
  951. if ( !level.teamBased )
  952. game["roundsWon"][self.guid] = undefined;
  953.  
  954. //if ( !level.gameEnded )
  955. // self logXPGains();
  956.  
  957. if ( level.splitscreen )
  958. {
  959. players = level.players;
  960.  
  961. if ( players.size <= 1 )
  962. level thread maps\mp\gametypes\_gamelogic::forceEnd();
  963. }
  964.  
  965. if ( isDefined( self.score ) && isDefined( self.pers["team"] ) )
  966. {
  967. setPlayerTeamRank( self, self.clientid, self.score - 5 * self.deaths );
  968. }
  969.  
  970. lpselfnum = self getEntityNumber();
  971. lpGuid = self.guid;
  972. logPrint("Q;" + lpGuid + ";" + lpselfnum + ";" + self.name + "\n");
  973.  
  974. self thread maps\mp\_events::disconnected();
  975.  
  976. if ( level.gameEnded )
  977. self maps\mp\gametypes\_gamescore::removeDisconnectedPlayerFromPlacement();
  978.  
  979. if ( isDefined( self.team ) )
  980. self maps\mp\gametypes\_playerlogic::removeFromTeamCount();
  981.  
  982. if ( self.sessionstate == "playing" )
  983. self maps\mp\gametypes\_playerlogic::removeFromAliveCount( true );
  984. else if ( self.sessionstate == "spectator" )
  985. level thread maps\mp\gametypes\_gamelogic::updateGameEvents();
  986. }
  987.  
  988.  
  989. removePlayerOnDisconnect()
  990. {
  991. found = false;
  992. for ( entry = 0; entry < level.players.size; entry++ )
  993. {
  994. if ( level.players[entry] == self )
  995. {
  996. found = true;
  997. while ( entry < level.players.size-1 )
  998. {
  999. level.players[entry] = level.players[entry + 1];
  1000. assert( level.players[entry] != self );
  1001. entry++;
  1002. }
  1003. level.players[entry] = undefined;
  1004. break;
  1005. }
  1006. }
  1007. assert( found );
  1008. }
  1009.  
  1010.  
  1011. initClientDvars()
  1012. {
  1013. makeDvarServerInfo( "cg_drawTalk", 1 );
  1014. makeDvarServerInfo( "cg_drawCrosshair", 1 );
  1015. makeDvarServerInfo( "cg_drawCrosshairNames", 1 );
  1016. makeDvarServerInfo( "cg_hudGrenadeIconMaxRangeFrag", 250 );
  1017.  
  1018. if ( level.hardcoreMode )
  1019. {
  1020. setDvar( "cg_drawTalk", 3 );
  1021. setDvar( "cg_drawCrosshair", 0 );
  1022. setDvar( "cg_drawCrosshairNames", 1 );
  1023. setDvar( "cg_hudGrenadeIconMaxRangeFrag", 0 );
  1024. }
  1025.  
  1026. self setClientDvars( "cg_drawSpectatorMessages", 1,
  1027. "g_compassShowEnemies", getDvar( "scr_game_forceuav" ),
  1028. "cg_scoreboardPingGraph", 1 );
  1029.  
  1030. if ( level.splitScreen )
  1031. {
  1032. self setClientDvars("cg_hudGrenadeIconHeight", "37.5",
  1033. "cg_hudGrenadeIconWidth", "37.5",
  1034. "cg_hudGrenadeIconOffset", "75",
  1035. "cg_hudGrenadePointerHeight", "18",
  1036. "cg_hudGrenadePointerWidth", "37.5",
  1037. "cg_hudGrenadePointerPivot", "18 40.5",
  1038. "cg_fovscale", "0.75" );
  1039. }
  1040. else
  1041. {
  1042. self setClientDvars("cg_hudGrenadeIconHeight", "25",
  1043. "cg_hudGrenadeIconWidth", "25",
  1044. "cg_hudGrenadeIconOffset", "50",
  1045. "cg_hudGrenadePointerHeight", "12",
  1046. "cg_hudGrenadePointerWidth", "25",
  1047. "cg_hudGrenadePointerPivot", "12 27",
  1048. "cg_fovscale", "1");
  1049. }
  1050.  
  1051. if ( getGametypeNumLives() )
  1052. {
  1053. self setClientDvars("cg_deadChatWithDead", 1,
  1054. "cg_deadChatWithTeam", 0,
  1055. "cg_deadHearTeamLiving", 0,
  1056. "cg_deadHearAllLiving", 0);
  1057. }
  1058. else
  1059. {
  1060. self setClientDvars("cg_deadChatWithDead", 0,
  1061. "cg_deadChatWithTeam", 1,
  1062. "cg_deadHearTeamLiving", 1,
  1063. "cg_deadHearAllLiving", 0);
  1064. }
  1065.  
  1066. if ( level.teamBased )
  1067. self setClientDvars("cg_everyonehearseveryone", 0);
  1068.  
  1069. self setClientDvar( "ui_altscene", 0 );
  1070.  
  1071. if ( getdvarint("scr_hitloc_debug") )
  1072. {
  1073. for ( i = 0; i < 6; i++ )
  1074. {
  1075. self setClientDvar( "ui_hitloc_" + i, "" );
  1076. }
  1077. self.hitlocInited = true;
  1078. }
  1079. }
  1080.  
  1081.  
  1082. Callback_PlayerConnect()
  1083. {
  1084. thread notifyConnecting();
  1085.  
  1086. self.statusicon = "hud_status_connecting";
  1087. self waittill( "begin" );
  1088. self.statusicon = "";
  1089.  
  1090. connectTime = undefined;
  1091. /#
  1092. connectTime = getTime();
  1093. #/
  1094.  
  1095. level notify( "connected", self );
  1096. self.connected = true;
  1097.  
  1098. if ( self isHost() )
  1099. level.player = self;
  1100.  
  1101. // only print that we connected if we haven't connected in a previous round
  1102. if( !level.splitscreen && !isDefined( self.pers["score"] ) )
  1103. iPrintLn(&"MP_CONNECTED", self);
  1104.  
  1105. self.usingOnlineDataOffline = self isUsingOnlineDataOffline();
  1106.  
  1107. self initClientDvars();
  1108. self initPlayerStats();
  1109.  
  1110. if( getdvar( "r_reflectionProbeGenerate" ) == "1" )
  1111. level waittill( "eternity" );
  1112.  
  1113. self.guid = self getGuid();
  1114.  
  1115. firstConnect = false;
  1116. if ( !isDefined( self.pers["clientid"] ) )
  1117. {
  1118. self.pers["clientid"] = game["clientid"];
  1119. game["clientid"]++;
  1120. firstConnect = true;
  1121. }
  1122.  
  1123. self.clientid = self.pers["clientid"];
  1124.  
  1125. logPrint("J;" + self.guid + ";" + self getEntityNumber() + ";" + self.name + "\n");
  1126.  
  1127. if ( matchMakingGame() && game["clientid"] <= 24 && game["clientid"] != getMatchData( "playerCount" ) )
  1128. {
  1129. setMatchData( "playerCount", game["clientid"] );
  1130. setMatchData( "players", self.clientid, "xuid", self getXuid() );
  1131. /#
  1132. if ( ( getDvarInt( "scr_forcerankedmatch" ) && level.teamBased ) || ( isDefined( self.pers["isBot"] ) && level.teamBased ) )
  1133. self.sessionteam = maps\mp\gametypes\_menus::getTeamAssignment();
  1134. #/
  1135. assert( getdvarint( "scr_runlevelandquit" ) == 1 || (level.teamBased && (self.sessionteam == "allies" || self.sessionteam == "axis")) || (!level.teamBased && self.sessionteam == "none" ) );
  1136. //assert( (level.teamBased && self.sessionteam == self.team) || (!level.teamBased && self.sessionteam == "none") );
  1137. setMatchData( "players", self.clientid, "team", self.sessionteam );
  1138. }
  1139.  
  1140. if ( !level.teamBased )
  1141. game["roundsWon"][self.guid] = 0;
  1142.  
  1143. self.leaderDialogQueue = [];
  1144. self.leaderDialogActive = "";
  1145. self.leaderDialogGroups = [];
  1146. self.leaderDialogGroup = "";
  1147.  
  1148. if ( !isDefined( self.pers["cur_kill_streak"] ) )
  1149. self.pers["cur_kill_streak"] = 0;
  1150. if ( !isDefined( self.pers["cur_death_streak"] ) )
  1151. self.pers["cur_death_streak"] = 0;
  1152.  
  1153. self.kill_streak = self maps\mp\gametypes\_persistence::statGet( "killStreak" );
  1154.  
  1155. self.lastGrenadeSuicideTime = -1;
  1156.  
  1157. self.teamkillsThisRound = 0;
  1158.  
  1159. self.hasSpawned = false;
  1160. self.waitingToSpawn = false;
  1161. self.wantSafeSpawn = false;
  1162.  
  1163. self.wasAliveAtMatchStart = false;
  1164. self.moveSpeedScaler = 1;
  1165. self.killStreakScaler = 1;
  1166. self.xpScaler = 1;
  1167. self.objectiveScaler = 1;
  1168. self.isSniper = false;
  1169.  
  1170. self.saved_actionSlotData = [];
  1171.  
  1172. self setRestXPGoal();
  1173.  
  1174. for( slotID = 1; slotID <= 4; slotID++ )
  1175. {
  1176. self.saved_actionSlotData[slotID] = spawnStruct();
  1177. self.saved_actionSlotData[slotID].type = "";
  1178. self.saved_actionSlotData[slotID].item = undefined;
  1179. }
  1180.  
  1181. self thread maps\mp\_flashgrenades::monitorFlash();
  1182.  
  1183. // give any threads waiting on the "connected" notify a chance to process before we are added to level.players
  1184. // this should ensure that all . variables on the player are correctly initialized by this point
  1185. waittillframeend;
  1186. /#
  1187. foreach ( player in level.players )
  1188. assert( player != self );
  1189. #/
  1190. level.players[level.players.size] = self;
  1191.  
  1192. if ( level.teambased )
  1193. self updateScores();
  1194.  
  1195. // When joining a game in progress, if the game is at the post game state (scoreboard) the connecting player should spawn into intermission
  1196. if ( game["state"] == "postgame" )
  1197. {
  1198. self.connectedPostGame = true;
  1199.  
  1200. if ( matchMakingGame() )
  1201. self maps\mp\gametypes\_menus::addToTeam( maps\mp\gametypes\_menus::getTeamAssignment(), true );
  1202. else
  1203. self maps\mp\gametypes\_menus::addToTeam( "spectator", true );
  1204.  
  1205. self setClientDvars( "cg_drawSpectatorMessages", 0 );
  1206.  
  1207. spawnIntermission();
  1208. return;
  1209. }
  1210.  
  1211. /#
  1212. if ( getDvarInt( "scr_debug_postgameconnect" ) )
  1213. {
  1214. self.pers["class"] = "";
  1215. self.class = "";
  1216. if ( self.sessionteam != "spectator" )
  1217. self.pers["team"] = self.sessionteam;
  1218. self.team = undefined;
  1219. }
  1220. #/
  1221.  
  1222. // only give a loss on the first connect
  1223. if ( firstConnect )
  1224. maps\mp\gametypes\_gamelogic::updateLossStats( self );
  1225.  
  1226. level endon( "game_ended" );
  1227.  
  1228. if ( isDefined( level.hostMigrationTimer ) )
  1229. self thread maps\mp\gametypes\_hostmigration::hostMigrationTimerThink();
  1230.  
  1231. // first connect only
  1232. if ( !isDefined( self.pers["team"] ) )
  1233. {
  1234. if ( matchMakingGame() )
  1235. {
  1236. self thread spawnSpectator();
  1237. self [[level.autoassign]]();
  1238. self thread kickIfDontSpawn();
  1239. return;
  1240. }
  1241.  
  1242. self [[level.spectator]]();
  1243. self maps\mp\gametypes\_menus::beginTeamChoice();
  1244. }
  1245. else
  1246. {
  1247. self maps\mp\gametypes\_menus::addToTeam( self.pers["team"], true );
  1248.  
  1249. if ( isValidClass( self.pers["class"] ) )
  1250. {
  1251. self thread spawnClient();
  1252. return;
  1253. }
  1254.  
  1255. self thread spawnSpectator();
  1256.  
  1257. if ( self.pers["team"] == "spectator" )
  1258. self maps\mp\gametypes\_menus::beginTeamChoice();
  1259. else
  1260. self maps\mp\gametypes\_menus::beginClassChoice();
  1261. }
  1262.  
  1263. /#
  1264. assert( connectTime == getTime() );
  1265. #/
  1266. }
  1267.  
  1268.  
  1269. Callback_PlayerMigrated()
  1270. {
  1271. println( "Player " + self.name + " finished migrating at time " + gettime() );
  1272.  
  1273. if ( isDefined( self.connected ) && self.connected )
  1274. {
  1275. self updateObjectiveText();
  1276. self updateMainMenu();
  1277.  
  1278. if ( level.teambased )
  1279. self updateScores();
  1280. }
  1281.  
  1282. level.hostMigrationReturnedPlayerCount++;
  1283. if ( level.hostMigrationReturnedPlayerCount >= level.players.size * 2 / 3 )
  1284. {
  1285. println( "2/3 of players have finished migrating" );
  1286. level notify( "hostmigration_enoughplayers" );
  1287. }
  1288. }
  1289.  
  1290.  
  1291. AddLevelsToExperience( experience, levels ) // lets you add "1500 experience + 1.5 levels" and returns the result in experience
  1292. {
  1293. rank = maps\mp\gametypes\_rank::getRankForXp( experience );
  1294.  
  1295. minXP = maps\mp\gametypes\_rank::getRankInfoMinXp( rank );
  1296. maxXP = maps\mp\gametypes\_rank::getRankInfoMaxXp( rank );
  1297. rank += (experience - minXP) / (maxXP - minXP);
  1298.  
  1299. rank += levels;
  1300.  
  1301. if ( rank < 0 )
  1302. {
  1303. rank = 0;
  1304. fractionalPart = 0.0;
  1305. }
  1306. else if ( rank >= level.maxRank + 1.0 )
  1307. {
  1308. rank = level.maxRank;
  1309. fractionalPart = 1.0;
  1310. }
  1311. else
  1312. {
  1313. fractionalPart = rank - floor( rank );
  1314. rank = int(floor( rank ));
  1315. }
  1316.  
  1317. minXP = maps\mp\gametypes\_rank::getRankInfoMinXp( rank );
  1318. maxXP = maps\mp\gametypes\_rank::getRankInfoMaxXp( rank );
  1319. return int( fractionalPart * (maxXP - minXP) ) + minXP;
  1320. }
  1321.  
  1322.  
  1323. GetRestXPCap( experience )
  1324. {
  1325. levelsToCap = getDvarFloat( "scr_restxp_cap" );
  1326. return AddLevelsToExperience( experience, levelsToCap );
  1327. }
  1328.  
  1329.  
  1330. setRestXPGoal()
  1331. {
  1332. if ( !getdvarint( "scr_restxp_enable" ) )
  1333. {
  1334. self setPlayerData( "restXPGoal", 0 );
  1335. return;
  1336. }
  1337.  
  1338. secondsSinceLastGame = self getRestedTime();
  1339. hoursSinceLastGame = secondsSinceLastGame / 3600;
  1340.  
  1341. /#
  1342. hoursSinceLastGame *= getDvarFloat( "scr_restxp_timescale" );
  1343. #/
  1344.  
  1345. experience = self getPlayerData( "experience" );
  1346.  
  1347. minRestXPTime = getDvarFloat( "scr_restxp_minRestTime" ); // hours
  1348. restXPGainRate = getDvarFloat( "scr_restxp_levelsPerDay" ) / 24.0;
  1349. restXPCap = GetRestXPCap( experience );
  1350.  
  1351. restXPGoal = self getPlayerData( "restXPGoal" );
  1352.  
  1353. if ( restXPGoal < experience )
  1354. restXPGoal = experience;
  1355.  
  1356. oldRestXPGoal = restXPGoal;
  1357.  
  1358. restLevels = 0;
  1359. if ( hoursSinceLastGame > minRestXPTime )
  1360. {
  1361. restLevels = restXPGainRate * hoursSinceLastGame;
  1362. restXPGoal = AddLevelsToExperience( restXPGoal, restLevels );
  1363. }
  1364.  
  1365. cappedString = "";
  1366. if ( restXPGoal >= restXPCap )
  1367. {
  1368. restXPGoal = restXPCap;
  1369. cappedString = " (hit cap)";
  1370. }
  1371.  
  1372. println( "Player " + self.name + " has rested for " + hoursSinceLastGame + " hours; gained " + restLevels + " levels of rest XP" + cappedString + ". Now has " + (restXPGoal - experience) + " rest XP; was " + (oldRestXPGoal - experience) );
  1373.  
  1374. self setPlayerData( "restXPGoal", restXPGoal );
  1375. }
  1376.  
  1377.  
  1378. forceSpawn()
  1379. {
  1380. self endon ( "death" );
  1381. self endon ( "disconnect" );
  1382. self endon ( "spawned" );
  1383.  
  1384. wait ( 60.0 );
  1385.  
  1386. if ( self.hasSpawned )
  1387. return;
  1388.  
  1389. if ( self.pers["team"] == "spectator" )
  1390. return;
  1391.  
  1392. if ( !isValidClass( self.pers["class"] ) )
  1393. {
  1394. self.pers["class"] = "CLASS_CUSTOM1";
  1395.  
  1396. self.class = self.pers["class"];
  1397. }
  1398.  
  1399. self closeMenus();
  1400. self thread spawnClient();
  1401. }
  1402.  
  1403.  
  1404. kickIfDontSpawn()
  1405. {
  1406. self endon ( "death" );
  1407. self endon ( "disconnect" );
  1408. self endon ( "spawned" );
  1409. self endon ( "attempted_spawn" );
  1410.  
  1411. waittime = getdvarfloat("scr_kick_time", 90 );
  1412. mintime = getdvarfloat("scr_kick_mintime", 45 );
  1413.  
  1414. starttime = gettime();
  1415.  
  1416. if ( self isHost() )
  1417. kickWait( 120 );
  1418. else
  1419. kickWait( waittime );
  1420.  
  1421. timePassed = (gettime() - starttime)/1000;
  1422. if ( timePassed < waittime - .1 && timePassed < mintime )
  1423. return;
  1424.  
  1425. if ( self.hasSpawned )
  1426. return;
  1427.  
  1428. if ( self.pers["team"] == "spectator" )
  1429. return;
  1430.  
  1431. kick( self getEntityNumber(), "EXE_PLAYERKICKED_INACTIVE" );
  1432.  
  1433. level thread maps\mp\gametypes\_gamelogic::updateGameEvents();
  1434. }
  1435.  
  1436.  
  1437. kickWait( waittime )
  1438. {
  1439. level endon("game_ended");
  1440.  
  1441. maps\mp\gametypes\_hostmigration::waitLongDurationWithHostMigrationPause( waittime );
  1442. }
  1443.  
  1444.  
  1445. updateSessionState( sessionState, statusIcon )
  1446. {
  1447. assert( sessionState == "playing" || sessionState == "dead" || sessionState == "spectator" || sessionState == "intermission" );
  1448. self.sessionstate = sessionState;
  1449. self.statusicon = statusIcon;
  1450. }
  1451.  
  1452.  
  1453. initPlayerStats()
  1454. {
  1455. self maps\mp\gametypes\_persistence::initBufferedStats();
  1456.  
  1457. self initPersStat( "score" );
  1458. self.score = self.pers["score"];
  1459.  
  1460. self initPersStat( "deaths" );
  1461. self.deaths = self getPersStat( "deaths" );
  1462.  
  1463. self initPersStat( "suicides" );
  1464. self.suicides = self getPersStat( "suicides" );
  1465.  
  1466. self initPersStat( "kills" );
  1467. self.kills = self getPersStat( "kills" );
  1468.  
  1469. self initPersStat( "headshots" );
  1470. self.headshots = self getPersStat( "headshots" );
  1471.  
  1472. self initPersStat( "assists" );
  1473. self.assists = self getPersStat( "assists" );
  1474.  
  1475. self initPersStat( "teamkills" );
  1476.  
  1477. if ( !isDefined( self.pers["teamKillPunish"] ) )
  1478. self.pers["teamKillPunish"] = false;
  1479.  
  1480. self initPersStat( "longestStreak" );
  1481.  
  1482. self.pers["lives"] = getGametypeNumLives();
  1483.  
  1484. self maps\mp\gametypes\_persistence::statSetChild( "round", "kills", 0 );
  1485. self maps\mp\gametypes\_persistence::statSetChild( "round", "killStreak", 0 );
  1486. self maps\mp\gametypes\_persistence::statSetChild( "round", "deaths", 0 );
  1487. self maps\mp\gametypes\_persistence::statSetChild( "round", "score", 0 );
  1488. self maps\mp\gametypes\_persistence::statSetChild( "round", "loss", false );
  1489. self maps\mp\gametypes\_persistence::statSetChild( "round", "win", false );
  1490. self maps\mp\gametypes\_persistence::statSetChild( "round", "scoreboardType", "none" );
  1491. self maps\mp\gametypes\_persistence::statSetChildBuffered( "round", "timePlayed", 0 );
  1492. }
  1493.  
  1494.  
  1495. addToTeamCount()
  1496. {
  1497. assert( isPlayer( self ) );
  1498. assert( isDefined( self.team ) );
  1499. assert( isDefined( self.pers["team"] ) );
  1500. assert( self.team == self.pers["team"] );
  1501.  
  1502. level.teamCount[self.team]++;
  1503. maps\mp\gametypes\_gamelogic::updateGameEvents();
  1504. }
  1505.  
  1506.  
  1507. removeFromTeamCount()
  1508. {
  1509. assert( isPlayer( self ) );
  1510. assert( isDefined( self.team ) );
  1511. assert( isDefined( self.pers["team"] ) );
  1512. assert( self.team == self.pers["team"] );
  1513.  
  1514. level.teamCount[self.team]--;
  1515. }
  1516.  
  1517.  
  1518. addToAliveCount()
  1519. {
  1520. assert( isPlayer( self ) );
  1521. level.aliveCount[self.team]++;
  1522. level.hasSpawned[self.team]++;
  1523.  
  1524. if ( level.aliveCount["allies"] + level.aliveCount["axis"] > level.maxPlayerCount )
  1525. level.maxPlayerCount = level.aliveCount["allies"] + level.aliveCount["axis"];
  1526. }
  1527.  
  1528.  
  1529. removeFromAliveCount( disconnected )
  1530. {
  1531. assert( isPlayer( self ) );
  1532.  
  1533. if ( isDefined( self.switching_teams ) || isDefined( disconnected ) )
  1534. {
  1535. self maps\mp\gametypes\_playerlogic::removeAllFromLivesCount();
  1536.  
  1537. if ( isDefined( self.switching_teams ) )
  1538. self.pers["lives"] = 0;
  1539. }
  1540.  
  1541. level.aliveCount[self.team]--;
  1542. return maps\mp\gametypes\_gamelogic::updateGameEvents();
  1543. }
  1544.  
  1545.  
  1546. addToLivesCount()
  1547. {
  1548. assert( isPlayer( self ) );
  1549. level.livesCount[self.team] += self.pers["lives"];
  1550. }
  1551.  
  1552.  
  1553. removeFromLivesCount()
  1554. {
  1555. assert( isPlayer( self ) );
  1556. level.livesCount[self.team]--;
  1557.  
  1558. // defensive, but we need to allow players to die/respawn when they're the only player in an offline game
  1559. level.livesCount[self.team] = int( max( 0, level.livesCount[self.team] ) );
  1560. }
  1561.  
  1562.  
  1563. removeAllFromLivesCount()
  1564. {
  1565. assert( isPlayer( self ) );
  1566. level.livesCount[self.team] -= self.pers["lives"];
  1567.  
  1568. // defensive, but we need to allow players to die/respawn when they're the only player in an offline game
  1569. level.livesCount[self.team] = int( max( 0, level.livesCount[self.team] ) );
  1570. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement