Advertisement
Guest User

_playerlogic - Notesblok

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