Advertisement
Guest User

_damage.gsc

a guest
Feb 12th, 2016
67
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 91.32 KB | None | 0 0
  1. #include maps\mp\_utility;
  2. #include maps\mp\gametypes\_hud_util;
  3. #include common_scripts\utility;
  4.  
  5. NUM_KILLS_GIVE_NUKE = 25;
  6.  
  7. isSwitchingTeams()
  8. {
  9. if ( isDefined( self.switching_teams ) )
  10. return true;
  11.  
  12. return false;
  13. }
  14.  
  15.  
  16. isTeamSwitchBalanced()
  17. {
  18. playerCounts = self maps\mp\gametypes\_teams::CountPlayers();
  19. playerCounts[ self.leaving_team ] -- ;
  20. playerCounts[ self.joining_team ]++ ;
  21.  
  22. return( ( playerCounts[ self.joining_team ] - playerCounts[ self.leaving_team ] ) < 2 );
  23. }
  24.  
  25.  
  26. isFriendlyFire( victim, attacker )
  27. {
  28. if ( !level.teamBased )
  29. return false;
  30.  
  31. if ( !isDefined( attacker ) )
  32. return false;
  33.  
  34. if ( !isPlayer( attacker ) && !isDefined( attacker.team ) )
  35. return false;
  36.  
  37. if ( victim.team != attacker.team )
  38. return false;
  39.  
  40. if ( victim == attacker )
  41. return false;
  42.  
  43. return true;
  44. }
  45.  
  46.  
  47. killedSelf( attacker )
  48. {
  49. if ( !isPlayer( attacker ) )
  50. return false;
  51.  
  52. if ( attacker != self )
  53. return false;
  54.  
  55. return true;
  56. }
  57.  
  58.  
  59. isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, attacker )
  60. {
  61. if ( isDefined( attacker ) )
  62. {
  63. if ( attacker.code_classname == "script_vehicle" && isDefined( attacker.owner ) )
  64. return false;
  65. if ( attacker.code_classname == "misc_turret" && isDefined( attacker.owner ) )
  66. return false;
  67. if ( attacker.code_classname == "script_model" && isDefined( attacker.owner ) )
  68. return false;
  69. }
  70.  
  71. return( sHitLoc == "head" || sHitLoc == "helmet" ) && sMeansOfDeath != "MOD_MELEE" && sMeansOfDeath != "MOD_IMPACT" && !isEnvironmentWeapon( sWeapon );
  72. }
  73.  
  74.  
  75. handleTeamChangeDeath()
  76. {
  77. if ( !level.teamBased )
  78. return;
  79.  
  80. // this might be able to happen now, but we should remove instances where it can
  81. assert( self.leaving_team != self.joining_team );
  82.  
  83. if ( self.joining_team == "spectator" || !isTeamSwitchBalanced() )
  84. {
  85. self thread [[ level.onXPEvent ]]( "suicide" );
  86. self incPersStat( "suicides", 1 );
  87. self.suicides = self getPersStat( "suicides" );
  88. }
  89. }
  90.  
  91.  
  92. handleWorldDeath( attacker, lifeId, sMeansOfDeath, sHitLoc )
  93. {
  94. if ( !isDefined( attacker ) )
  95. return;
  96.  
  97. if ( !isDefined( attacker.team ) )
  98. {
  99. handleSuicideDeath( sMeansOfDeath, sHitLoc );
  100. return;
  101. }
  102.  
  103. assert( attacker.team == "axis" || attacker.team == "allies" );
  104.  
  105. if ( ( level.teamBased && attacker.team != self.team ) || !level.teamBased )
  106. {
  107. if ( isDefined( level.onNormalDeath ) && isPlayer( attacker ) && attacker.team != "spectator" )
  108. [[ level.onNormalDeath ]]( self, attacker, lifeId );
  109. }
  110. }
  111.  
  112.  
  113. handleSuicideDeath( sMeansOfDeath, sHitLoc )
  114. {
  115. self SetCardDisplaySlot( self, 7 );
  116. self openMenu( "killedby_card_display" );
  117.  
  118. self thread [[ level.onXPEvent ]]( "suicide" );
  119. self incPersStat( "suicides", 1 );
  120. self.suicides = self getPersStat( "suicides" );
  121.  
  122. if ( !matchMakingGame() )
  123. self incPlayerStat( "suicides", 1 );
  124.  
  125. scoreSub = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "suicidepointloss" );
  126. maps\mp\gametypes\_gamescore::_setPlayerScore( self, maps\mp\gametypes\_gamescore::_getPlayerScore( self ) - scoreSub );
  127.  
  128. if ( sMeansOfDeath == "MOD_SUICIDE" && sHitLoc == "none" && isDefined( self.throwingGrenade ) )
  129. self.lastGrenadeSuicideTime = gettime();
  130.  
  131. // suicide was caused by too many team kills
  132. if ( isDefined( self.friendlydamage ) )
  133. self iPrintLnBold( &"MP_FRIENDLY_FIRE_WILL_NOT" );
  134. }
  135.  
  136.  
  137. handleFriendlyFireDeath( attacker )
  138. {
  139. attacker SetCardDisplaySlot( self, 8 );
  140. attacker openMenu( "youkilled_card_display" );
  141.  
  142. self SetCardDisplaySlot( attacker, 7 );
  143. self openMenu( "killedby_card_display" );
  144.  
  145. attacker thread [[ level.onXPEvent ]]( "teamkill" );
  146. attacker.pers[ "teamkills" ] += 1.0;
  147.  
  148. attacker.teamkillsThisRound++ ;
  149.  
  150. if ( maps\mp\gametypes\_tweakables::getTweakableValue( "team", "teamkillpointloss" ) )
  151. {
  152. scoreSub = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" );
  153. maps\mp\gametypes\_gamescore::_setPlayerScore( attacker, maps\mp\gametypes\_gamescore::_getPlayerScore( attacker ) - scoreSub );
  154. }
  155.  
  156. if ( level.maxAllowedTeamkills < 0 )
  157. return;
  158.  
  159. if ( level.inGracePeriod )
  160. {
  161. teamKillDelay = 1;
  162. attacker.pers["teamkills"] += level.maxAllowedTeamkills;
  163. }
  164. else if ( attacker.pers[ "teamkills" ] > 1 && getTimePassed() < ( (level.gracePeriod * 1000) + 8000 + ( attacker.pers[ "teamkills" ] * 1000 ) ) )
  165. {
  166. teamKillDelay = 1;
  167. attacker.pers["teamkills"] += level.maxAllowedTeamkills;
  168. }
  169. else
  170. {
  171. teamKillDelay = attacker maps\mp\gametypes\_playerlogic::TeamKillDelay();
  172. }
  173.  
  174. if ( teamKillDelay > 0 )
  175. {
  176. attacker.pers["teamKillPunish"] = true;
  177. attacker _suicide();
  178. }
  179. }
  180.  
  181.  
  182. handleNormalDeath( lifeId, attacker, eInflictor, sWeapon, sMeansOfDeath )
  183. {
  184. attacker thread maps\mp\_events::killedPlayer( lifeId, self, sWeapon, sMeansOfDeath );
  185.  
  186. //if ( attacker.pers["teamkills"] <= level.maxAllowedTeamkills )
  187. // attacker.pers["teamkills"] = max( attacker.pers["teamkills"] - 1, 0 );
  188.  
  189. attacker SetCardDisplaySlot( self, 8 );
  190. attacker openMenu( "youkilled_card_display" );
  191.  
  192. self SetCardDisplaySlot( attacker, 7 );
  193. self openMenu( "killedby_card_display" );
  194.  
  195. if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
  196. {
  197. attacker incPersStat( "headshots", 1 );
  198. attacker.headshots = attacker getPersStat( "headshots" );
  199. attacker incPlayerStat( "headshots", 1 );
  200.  
  201. if ( isDefined( attacker.lastStand ) )
  202. value = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 2;
  203. else
  204. value = undefined;
  205.  
  206. attacker playLocalSound( "bullet_impact_headshot_2" );
  207. }
  208. else
  209. {
  210. if ( isDefined( attacker.lastStand ) )
  211. value = maps\mp\gametypes\_rank::getScoreInfoValue( "kill" ) * 2;
  212. else
  213. value = undefined;
  214. }
  215.  
  216. attacker thread maps\mp\gametypes\_rank::giveRankXP( "kill", value, sWeapon, sMeansOfDeath );
  217.  
  218. attacker incPersStat( "kills", 1 );
  219. attacker.kills = attacker getPersStat( "kills" );
  220. attacker updatePersRatio( "kdRatio", "kills", "deaths" );
  221. attacker maps\mp\gametypes\_persistence::statSetChild( "round", "kills", attacker.kills );
  222. attacker incPlayerStat( "kills", 1 );
  223.  
  224. if ( isFlankKill( self, attacker ) )
  225. {
  226. attacker incPlayerStat( "flankkills", 1 );
  227.  
  228. self incPlayerStat( "flankdeaths", 1 );
  229. }
  230.  
  231. lastKillStreak = attacker.pers["cur_kill_streak"];
  232.  
  233. self.pers["copyCatLoadout"] = undefined;
  234.  
  235. if ( self _hasPerk( "specialty_copycat" ) )
  236. self.pers["copyCatLoadout"] = attacker maps\mp\gametypes\_class::cloneLoadout();
  237.  
  238. if ( isAlive( attacker ) || attacker.streakType == "support" )
  239. {
  240. if ( attacker killShouldAddToKillstreak( sWeapon ) )
  241. {
  242. // NOTE: added threading to the giveAdrenaline() call because it could block the killcam from playing for a killed player
  243. // this was happening if you earned a remote mortar and had one more kill to get something like the remote tank, and earned it while in the remote mortar
  244. // there's a isChangingWeapon() loop that blocks since we're in the remote mortar not changing weapons when given the new killstreak
  245. attacker thread maps\mp\killstreaks\_killstreaks::giveAdrenaline( "kill" );
  246. attacker.pers["cur_kill_streak"]++;
  247.  
  248. // at a certain number of kills we'll give you a nuke, but not from killstreak kills
  249. if( !isKillstreakWeapon( sWeapon ) )
  250. attacker.pers["cur_kill_streak_for_nuke"]++;
  251.  
  252. numKills = NUM_KILLS_GIVE_NUKE;
  253. if( attacker _hasPerk( "specialty_hardline" ) )
  254. numKills--;
  255.  
  256. if( !isKillstreakWeapon( sWeapon ) && attacker.pers["cur_kill_streak_for_nuke"] == numKills )
  257. {
  258. attacker thread maps\mp\killstreaks\_killstreaks::giveKillstreak( "nuke", false, true, attacker, true );
  259. attacker thread maps\mp\gametypes\_hud_message::killstreakSplashNotify( "nuke", numKills );
  260. }
  261. }
  262.  
  263. attacker setPlayerStatIfGreater( "killstreak", attacker.pers["cur_kill_streak"] );
  264.  
  265. if ( attacker.pers["cur_kill_streak"] > attacker getPersStat( "longestStreak" ) )
  266. attacker setPersStat( "longestStreak", attacker.pers["cur_kill_streak"] );
  267. }
  268.  
  269. attacker.pers["cur_death_streak"] = 0;
  270.  
  271. if ( attacker.pers["cur_kill_streak"] > attacker maps\mp\gametypes\_persistence::statGetChild( "round", "killStreak" ) )
  272. {
  273. attacker maps\mp\gametypes\_persistence::statSetChild( "round", "killStreak", attacker.pers["cur_kill_streak"] );
  274. }
  275.  
  276. if ( attacker.pers["cur_kill_streak"] > attacker.kill_streak )
  277. {
  278. attacker maps\mp\gametypes\_persistence::statSet( "killStreak", attacker.pers["cur_kill_streak"] );
  279. attacker.kill_streak = attacker.pers["cur_kill_streak"];
  280. }
  281.  
  282. maps\mp\gametypes\_gamescore::givePlayerScore( "kill", attacker, self );
  283. maps\mp\_skill::processKill( attacker, self );
  284.  
  285. scoreSub = maps\mp\gametypes\_tweakables::getTweakableValue( "game", "deathpointloss" );
  286. maps\mp\gametypes\_gamescore::_setPlayerScore( self, maps\mp\gametypes\_gamescore::_getPlayerScore( self ) - scoreSub );
  287.  
  288. if ( isDefined( level.ac130player ) && level.ac130player == attacker )
  289. level notify( "ai_killed", self );
  290.  
  291. //if ( lastKillStreak != attacker.pers["cur_kill_streak"] )
  292. level notify ( "player_got_killstreak_" + attacker.pers["cur_kill_streak"], attacker );
  293. attacker notify( "got_killstreak" , attacker.pers["cur_kill_streak"] );
  294.  
  295. attacker notify ( "killed_enemy" );
  296.  
  297. // assists for marking player with remote uav (allow in FFA)
  298. if ( isDefined( self.UAVRemoteMarkedBy ) )
  299. {
  300. if ( self.UAVRemoteMarkedBy != attacker )
  301. self.UAVRemoteMarkedBy thread maps\mp\killstreaks\_remoteuav::remoteUAV_processTaggedAssist( self );
  302. self.UAVRemoteMarkedBy = undefined;
  303. }
  304.  
  305. if ( isDefined( level.onNormalDeath ) && attacker.pers[ "team" ] != "spectator" )
  306. [[ level.onNormalDeath ]]( self, attacker, lifeId );
  307.  
  308. if ( !level.teamBased )
  309. {
  310. self.attackers = [];
  311. return;
  312. }
  313.  
  314. level thread maps\mp\gametypes\_battlechatter_mp::sayLocalSoundDelayed( attacker, "kill", 0.75 );
  315.  
  316. if ( isDefined( self.lastAttackedShieldPlayer ) && isDefined( self.lastAttackedShieldTime ) && self.lastAttackedShieldPlayer != attacker )
  317. {
  318. if ( getTime() - self.lastAttackedShieldTime < 2500 )
  319. {
  320. self.lastAttackedShieldPlayer thread maps\mp\gametypes\_gamescore::processShieldAssist( self );
  321.  
  322. // if you are using the assists perk, then every assist is a kill towards a killstreak
  323. if( self.lastAttackedShieldPlayer _hasPerk( "specialty_assists" ) )
  324. {
  325. self.lastAttackedShieldPlayer.pers["assistsToKill"]++;
  326.  
  327. if( !( self.lastAttackedShieldPlayer.pers["assistsToKill"] % 2 ) )
  328. {
  329. self.lastAttackedShieldPlayer maps\mp\gametypes\_missions::processChallenge( "ch_hardlineassists" );
  330. self.lastAttackedShieldPlayer maps\mp\killstreaks\_killstreaks::giveAdrenaline( "kill" );
  331. self.lastAttackedShieldPlayer.pers["cur_kill_streak"]++;
  332. }
  333. }
  334. else
  335. {
  336. self.lastAttackedShieldPlayer.pers["assistsToKill"] = 0;
  337. }
  338. }
  339. else if ( isAlive( self.lastAttackedShieldPlayer ) && getTime() - self.lastAttackedShieldTime < 5000 )
  340. {
  341. forwardVec = vectorNormalize( anglesToForward( self.angles ) );
  342. shieldVec = vectorNormalize( self.lastAttackedShieldPlayer.origin - self.origin );
  343.  
  344. if ( vectorDot( shieldVec, forwardVec ) > 0.925 )
  345. {
  346. self.lastAttackedShieldPlayer thread maps\mp\gametypes\_gamescore::processShieldAssist( self );
  347.  
  348. // if you are using the assists perk, then every assist is a kill towards a killstreak
  349. if( self.lastAttackedShieldPlayer _hasPerk( "specialty_assists" ) )
  350. {
  351. self.lastAttackedShieldPlayer.pers["assistsToKill"]++;
  352.  
  353. if( !( self.lastAttackedShieldPlayer.pers["assistsToKill"] % 2 ) )
  354. {
  355. self.lastAttackedShieldPlayer maps\mp\gametypes\_missions::processChallenge( "ch_hardlineassists" );
  356. self.lastAttackedShieldPlayer maps\mp\killstreaks\_killstreaks::giveAdrenaline( "kill" );
  357. self.lastAttackedShieldPlayer.pers["cur_kill_streak"]++;
  358. }
  359. }
  360. else
  361. {
  362. self.lastAttackedShieldPlayer.pers["assistsToKill"] = 0;
  363. }
  364. }
  365. }
  366. }
  367.  
  368. // regular assists
  369. if ( isDefined( self.attackers ) )
  370. {
  371. foreach ( player in self.attackers )
  372. {
  373. if ( !isDefined( player ) )
  374. continue;
  375.  
  376. if ( player == attacker )
  377. continue;
  378.  
  379. player thread maps\mp\gametypes\_gamescore::processAssist( self );
  380.  
  381. // if you are using the assists perk, then every assist is a kill towards a killstreak
  382. if( player _hasPerk( "specialty_assists" ) )
  383. {
  384. player.pers["assistsToKill"]++;
  385.  
  386. if( !( player.pers["assistsToKill"] % 2 ) )
  387. {
  388. player maps\mp\gametypes\_missions::processChallenge( "ch_hardlineassists" );
  389. player maps\mp\killstreaks\_killstreaks::giveAdrenaline( "kill" );
  390. player.pers["cur_kill_streak"]++;
  391.  
  392. // at a certain number of kills in a streak we'll give you a nuke
  393. numKills = NUM_KILLS_GIVE_NUKE;
  394. if( player _hasPerk( "specialty_hardline" ) )
  395. numKills--;
  396.  
  397. if( player.pers["cur_kill_streak"] == numKills )
  398. {
  399. player thread maps\mp\killstreaks\_killstreaks::giveKillstreak( "nuke", false, true, player, true );
  400. player thread maps\mp\gametypes\_hud_message::killstreakSplashNotify( "nuke", numKills );
  401. }
  402. }
  403. }
  404. else
  405. {
  406. player.pers["assistsToKill"] = 0;
  407. }
  408. }
  409. self.attackers = [];
  410. }
  411. }
  412.  
  413. isPlayerWeapon( weaponName )
  414. {
  415. if ( weaponClass( weaponName ) == "non-player" )
  416. return false;
  417.  
  418. if ( weaponClass( weaponName ) == "turret" )
  419. return false;
  420.  
  421. if ( weaponInventoryType( weaponName ) == "primary" || weaponInventoryType( weaponName ) == "altmode" )
  422. return true;
  423.  
  424. return false;
  425. }
  426.  
  427. Callback_PlayerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
  428. {
  429. PlayerKilled_internal( eInflictor, attacker, self, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, false );
  430. }
  431.  
  432.  
  433. QueueShieldForRemoval( shield )
  434. {
  435. MY_MAX_SHIELDS_AT_A_TIME = 5;
  436.  
  437. if ( !isDefined( level.shieldTrashArray ) )
  438. level.shieldTrashArray = [];
  439.  
  440. if ( level.shieldTrashArray.size >= MY_MAX_SHIELDS_AT_A_TIME )
  441. {
  442. idxMax = (level.shieldTrashArray.size - 1);
  443. level.shieldTrashArray[0] delete();
  444. for ( idx = 0; idx < idxMax; idx++ )
  445. level.shieldTrashArray[idx] = level.shieldTrashArray[idx + 1];
  446. level.shieldTrashArray[idxMax] = undefined;
  447. }
  448.  
  449. level.shieldTrashArray[level.shieldTrashArray.size] = shield;
  450. }
  451.  
  452.  
  453. LaunchShield( damage, meansOfDeath )
  454. {
  455. shieldModel = "weapon_riot_shield_mp";
  456.  
  457. self DetachShieldModel( shieldModel, "tag_weapon_left" );
  458. self.hasRiotShield = false;
  459. self.hasRiotShieldEquipped = false;
  460. }
  461.  
  462.  
  463. PlayerKilled_internal( eInflictor, attacker, victim, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, isFauxDeath )
  464. {
  465. prof_begin( "PlayerKilled" );
  466. //prof_begin( " PlayerKilled_1" );
  467.  
  468. victim endon( "spawned" );
  469. victim notify( "killed_player" );
  470.  
  471. assert( victim.sessionteam != "spectator" );
  472.  
  473. if ( isDefined( attacker ) )
  474. attacker.assistedSuicide = undefined;
  475.  
  476. if ( !isDefined( victim.idFlags ) )
  477. {
  478. if ( sMeansOfDeath == "MOD_SUICIDE" )
  479. victim.idFlags = 0;
  480. else if ( sMeansOfDeath == "MOD_GRENADE" && isSubstr( sWeapon, "frag_grenade" ) && iDamage == 100000 )
  481. victim.idFlags = 0;
  482. else if ( sWeapon == "nuke_mp" )
  483. victim.idFlags = 0;
  484. else if ( level.friendlyfire >= 2)
  485. victim.idFlags = 0;
  486. else
  487. assertEx( 0, "Victims ID flags not set, but means of death was gr or nuke: " + sMeansOfDeath );
  488. }
  489.  
  490. if ( victim.hasRiotShieldEquipped )
  491. victim LaunchShield( iDamage, sMeansofDeath );
  492.  
  493. //victim thread checkForceBleedOut();
  494.  
  495. if ( !isFauxDeath )
  496. {
  497. if ( isDefined( victim.endGame ) )
  498. {
  499. if ( IsDefined( level.nukeDetonated ) )
  500. self VisionSetNakedForPlayer( level.nukeVisionSet, 2 );
  501. else
  502. self VisionSetNakedForPlayer( "", 2 ); // go to default visionset
  503. }
  504. else
  505. {
  506. if ( IsDefined( level.nukeDetonated ) )
  507. self VisionSetNakedForPlayer( level.nukeVisionSet, 0 );
  508. else
  509. self VisionSetNakedForPlayer( "", 0 ); // go to default visionset
  510. victim ThermalVisionOff();
  511. }
  512. }
  513. else
  514. {
  515. victim.fauxDead = true;
  516. self notify ( "death" );
  517. }
  518.  
  519. if ( game[ "state" ] == "postgame" )
  520. {
  521. //prof_end( " PlayerKilled_1" );
  522. prof_end( "PlayerKilled" );
  523. return;
  524. }
  525.  
  526. // replace params with last stand info
  527. deathTimeOffset = 0;
  528.  
  529. if ( !isPlayer( eInflictor ) && isDefined( eInflictor.primaryWeapon ) )
  530. {
  531. sPrimaryWeapon = eInflictor.primaryWeapon;
  532. }
  533. else if ( isDefined( attacker ) && isPlayer( attacker ) && attacker getCurrentPrimaryWeapon() != "none" )
  534. {
  535. sPrimaryWeapon = attacker getCurrentPrimaryWeapon();
  536. }
  537. else//getCurrentPrimaryWeapon() will return none if the player is: ladder, grenade, killstreak placment, etc...
  538. {
  539. if ( isSubStr( sWeapon, "alt_" ) )
  540. {
  541. sPrimaryWeapon = GetSubStr( sWeapon, 4, sWeapon.size );
  542. }
  543. else//killstreak weapon or offhand
  544. {
  545. sPrimaryWeapon = undefined;
  546. }
  547. }
  548.  
  549. if ( isdefined( victim.useLastStandParams ) || ( isDefined( victim.lastStandParams ) && sMeansOfDeath == "MOD_SUICIDE" ) )
  550. {
  551. victim ensureLastStandParamsValidity();
  552. victim.useLastStandParams = undefined;
  553.  
  554. assert( isdefined( victim.lastStandParams ) );
  555.  
  556. eInflictor = victim.lastStandParams.eInflictor;
  557. attacker = victim.lastStandParams.attacker;
  558. iDamage = victim.lastStandParams.iDamage;
  559. sMeansOfDeath = victim.lastStandParams.sMeansOfDeath;
  560. sWeapon = victim.lastStandParams.sWeapon;
  561. sPrimaryWeapon = victim.lastStandParams.sPrimaryWeapon;
  562. vDir = victim.lastStandParams.vDir;
  563. sHitLoc = victim.lastStandParams.sHitLoc;
  564.  
  565. deathTimeOffset = ( gettime() - victim.lastStandParams.lastStandStartTime ) / 1000;
  566. victim.lastStandParams = undefined;
  567. }
  568.  
  569. //prof_end( " PlayerKilled_1" );
  570. //prof_begin( " PlayerKilled_2" );
  571.  
  572. //used for endgame perk and assisted suicide.
  573. if ( (!isDefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || attacker == victim ) && isDefined( self.attackers ) )
  574. {
  575. bestPlayer = undefined;
  576.  
  577. foreach ( player in self.attackers )
  578. {
  579. if ( !isDefined( player ) )
  580. continue;
  581.  
  582. if (! isDefined( victim.attackerData[ player.guid ].damage ) )
  583. continue;
  584.  
  585. if ( player == victim || (level.teamBased && player.team == victim.team ) )
  586. continue;
  587.  
  588. if ( victim.attackerData[ player.guid ].lasttimedamaged + 2500 < getTime() && ( attacker != victim && ( isDefined(victim.lastStand) && victim.lastStand ) ) )
  589. continue;
  590.  
  591. if ( victim.attackerData[ player.guid ].damage > 1 && ! isDefined( bestPlayer ) )
  592. bestPlayer = player;
  593. else if ( isDefined( bestPlayer ) && victim.attackerData[ player.guid ].damage > victim.attackerData[ bestPlayer.guid ].damage )
  594. bestPlayer = player;
  595. }
  596.  
  597. if ( isDefined( bestPlayer ) )
  598. {
  599. attacker = bestPlayer;
  600. attacker.assistedSuicide = true;
  601. sWeapon = victim.attackerData[ bestPlayer.guid ].weapon;
  602. vDir = victim.attackerData[ bestPlayer.guid ].vDir;
  603. sHitLoc = victim.attackerData[ bestPlayer.guid ].sHitLoc;
  604. psOffsetTime = victim.attackerData[ bestPlayer.guid ].psOffsetTime;
  605. sMeansOfDeath = victim.attackerData[ bestPlayer.guid ].sMeansOfDeath;
  606. iDamage = victim.attackerData[ bestPlayer.guid ].damage;
  607. sPrimaryWeapon = victim.attackerData[ bestPlayer.guid ].sPrimaryWeapon;
  608. eInflictor = attacker;
  609. }
  610. }
  611. else
  612. {
  613. if ( isDefined( attacker ) )
  614. attacker.assistedSuicide = undefined;
  615. }
  616.  
  617. // override MOD
  618. if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, attacker ) )
  619. sMeansOfDeath = "MOD_HEAD_SHOT";
  620. else if ( sMeansOfDeath != "MOD_MELEE" && !isDefined( victim.nuked ) )
  621. victim playDeathSound();
  622.  
  623. friendlyFire = isFriendlyFire( victim, attacker );
  624.  
  625. if ( isDefined( attacker ) )
  626. {
  627. // override attacker if it's a vehicle
  628. if ( attacker.code_classname == "script_vehicle" && isDefined( attacker.owner ) )
  629. {
  630. attacker = attacker.owner;
  631. }
  632.  
  633. // override attacker if it's a sentry
  634. if ( attacker.code_classname == "misc_turret" && isDefined( attacker.owner ) )
  635. {
  636. if ( isDefined( attacker.vehicle ) )
  637. attacker.vehicle notify( "killedPlayer", victim );
  638.  
  639. attacker = attacker.owner;
  640. }
  641.  
  642. // override attacker if it's a crate
  643. if ( attacker.code_classname == "script_model" && isDefined( attacker.owner ) )
  644. {
  645. attacker = attacker.owner;
  646.  
  647. if ( !isFriendlyFire( victim, attacker ) && attacker != victim )
  648. attacker notify( "crushed_enemy" );
  649. }
  650. }
  651.  
  652. //prof_end( " PlayerKilled_2" );
  653. //prof_begin( " PlayerKilled_3" );
  654.  
  655. //prof_begin( " PlayerKilled_3_drop" );
  656. // drop weapons from killed player
  657. victim maps\mp\gametypes\_weapons::dropScavengerForDeath( attacker ); // must be done before dropWeaponForDeath, since we use some weapon information
  658. victim maps\mp\gametypes\_weapons::dropWeaponForDeath( attacker );
  659. //prof_end( " PlayerKilled_3_drop" );
  660.  
  661. if ( !isFauxDeath )
  662. {
  663. victim.sessionstate = "dead";
  664. victim.statusicon = "hud_status_dead";
  665. }
  666.  
  667. // UTS update aliveCount
  668. victim maps\mp\gametypes\_playerlogic::removeFromAliveCount();
  669.  
  670. if ( !isDefined( victim.switching_teams ) )
  671. {
  672. // update our various stats
  673. victim incPersStat( "deaths", 1 );
  674. victim.deaths = victim getPersStat( "deaths" );
  675. victim updatePersRatio( "kdRatio", "kills", "deaths" );
  676. victim maps\mp\gametypes\_persistence::statSetChild( "round", "deaths", victim.deaths );
  677. victim incPlayerStat( "deaths", 1 );
  678. }
  679.  
  680. if ( isDefined( attacker ) && isPlayer(attacker) )
  681. attacker checkKillSteal( victim );
  682.  
  683. // obituary
  684. obituary( victim, attacker, sWeapon, sMeansOfDeath );
  685.  
  686. doKillcam = false;
  687.  
  688. lifeId = getNextLifeId();
  689.  
  690. victim logPrintPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc );
  691. victim maps\mp\_matchdata::logPlayerLife( lifeId );
  692. victim maps\mp\_matchdata::logPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc );
  693.  
  694. if ( (sMeansOfDeath == "MOD_MELEE") )
  695. {
  696. if ( IsSubStr( sWeapon, "riotshield" ) )
  697. {
  698. attacker incPlayerStat( "shieldkills", 1 );
  699.  
  700. if ( !matchMakingGame() )
  701. victim incPlayerStat( "shielddeaths", 1 );
  702. }
  703. else
  704. attacker incPlayerStat( "knifekills", 1 );
  705. }
  706.  
  707. //prof_end( " PlayerKilled_3" );
  708. //prof_begin( " PlayerKilled_4" );
  709.  
  710. if ( victim isSwitchingTeams() )
  711. {
  712. handleTeamChangeDeath();
  713. }
  714. else if ( !isPlayer( attacker ) || (isPlayer( attacker ) && sMeansOfDeath == "MOD_FALLING") )
  715. {
  716. handleWorldDeath( attacker, lifeId, sMeansOfDeath, sHitLoc );
  717. }
  718. else if ( attacker == victim )
  719. {
  720. handleSuicideDeath( sMeansOfDeath, sHitLoc );
  721. }
  722. else if ( friendlyFire )
  723. {
  724. if ( !isDefined( victim.nuked ) )
  725. {
  726. handleFriendlyFireDeath( attacker );
  727. }
  728. }
  729. else
  730. {
  731. if ( sMeansOfDeath == "MOD_GRENADE" && eInflictor == attacker )
  732. addAttacker( victim, attacker, eInflictor, sWeapon, iDamage, (0,0,0), vDir, sHitLoc, psOffsetTime, sMeansOfDeath );
  733.  
  734. doKillcam = true;
  735. handleNormalDeath( lifeId, attacker, eInflictor, sWeapon, sMeansOfDeath );
  736. victim thread maps\mp\gametypes\_missions::playerKilled( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc, attacker.modifiers );
  737.  
  738. victim.pers["cur_death_streak"]++;
  739.  
  740. if ( !getGametypeNumLives() && !matchMakingGame() )
  741. victim setPlayerStatIfGreater( "deathstreak", victim.pers["cur_death_streak"] );
  742.  
  743. // team splash if juggernaut was killed
  744. if( IsPlayer( attacker ) && victim isJuggernaut() )
  745. {
  746. attacker thread teamPlayerCardSplash( "callout_killed_juggernaut", attacker );
  747. }
  748. }
  749.  
  750. // Don't increment weapon stats for team kills or deaths
  751. wasInLastStand = false;
  752. lastWeaponBeforeDroppingIntoLastStand = undefined;
  753. if ( isDefined( self.previousPrimary ) )
  754. {
  755. wasInLastStand = true;
  756. lastWeaponBeforeDroppingIntoLastStand = self.previousPrimary;
  757. }
  758.  
  759. if ( isPlayer( attacker ) && attacker != self && ( !level.teamBased || ( level.teamBased && self.team != attacker.team ) ) )
  760. {
  761. self thread maps\mp\gametypes\_gamelogic::trackLeaderBoardDeathStats( sWeapon, sMeansOfDeath );
  762.  
  763. if ( wasInLastStand && isDefined( lastWeaponBeforeDroppingIntoLastStand ) )
  764. weaponName = lastWeaponBeforeDroppingIntoLastStand;
  765. else
  766. weaponName = self.lastdroppableweapon;
  767.  
  768. if ( isDefined( weaponName ) && ( isSubStr( weaponName, "gl_" ) || isSubStr( weaponName, "mk_" ) || isSubStr( weaponName, "ft_" ) ) )
  769. weaponName = self.currentWeapon;
  770.  
  771. attacker thread maps\mp\gametypes\_gamelogic::trackAttackerLeaderBoardDeathStats( sWeapon, sMeansOfDeath );
  772. }
  773.  
  774. //prof_end( " PlayerKilled_4" );
  775. //prof_begin( " PlayerKilled_5" );
  776.  
  777. // clear any per life variables
  778. victim resetPlayerVariables();
  779. victim.lastAttacker = attacker;
  780. victim.lastDeathPos = victim.origin;
  781. victim.deathTime = getTime();
  782. victim.wantSafeSpawn = false;
  783. victim.revived = false;
  784. victim.sameShotDamage = 0;
  785.  
  786. if( maps\mp\killstreaks\_killstreaks::streakTypeResetsOnDeath( victim.streakType ) )
  787. victim maps\mp\killstreaks\_killstreaks::resetAdrenaline();
  788.  
  789. if ( isFauxDeath )
  790. {
  791. doKillcam = false;
  792. deathAnimDuration = (victim PlayerForceDeathAnim( eInflictor, sMeansOfDeath, sWeapon, sHitLoc, vDir ));
  793. }
  794.  
  795. victim.body = victim clonePlayer( deathAnimDuration );
  796.  
  797. if ( isFauxDeath )
  798. victim PlayerHide();
  799.  
  800. if ( victim isOnLadder() || victim isMantling() || !victim isOnGround() || isDefined( victim.nuked ) )
  801. victim.body startRagDoll();
  802.  
  803. if ( !isDefined( victim.switching_teams ) )
  804. thread maps\mp\gametypes\_deathicons::addDeathicon( victim.body, victim, victim.team, 5.0 );
  805.  
  806. thread delayStartRagdoll( victim.body, sHitLoc, vDir, sWeapon, eInflictor, sMeansOfDeath );
  807.  
  808. // allow per gametype death handling
  809. victim thread [[ level.onPlayerKilled ]]( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, lifeId );
  810.  
  811. if ( isPlayer( attacker ) )
  812. attackerNum = attacker getEntityNumber();
  813. else
  814. attackerNum = -1;
  815. killcamentity = victim getKillcamEntity( attacker, eInflictor, sWeapon );
  816. killcamentityindex = -1;
  817. killcamentitystarttime = 0;
  818.  
  819. if ( isDefined( killcamentity ) )
  820. {
  821. killcamentityindex = killcamentity getEntityNumber();// must do this before any waiting lest the entity be deleted
  822. killcamentitystarttime = killcamentity.birthtime;
  823. if ( !isdefined( killcamentitystarttime ) )
  824. killcamentitystarttime = 0;
  825. }
  826.  
  827. /#
  828. if ( getDvarInt( "scr_forcekillcam" ) != 0 )
  829. doKillcam = true;
  830. #/
  831.  
  832. ///////////////////////////////////////////////////////
  833. // KILL CAM STUFF
  834. /*
  835. // record the kill cam values for the final kill cam
  836. if ( sMeansOfDeath != "MOD_SUICIDE" && !( !isDefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || attacker == victim ) )
  837. {
  838. recordFinalKillCam( 5.0, victim, attacker, attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, deathTimeOffset, psOffsetTime );
  839. }
  840.  
  841. // tell the ingame killcam ui what to say, this was tried but has an issue with new players not understanding, maybe just needs new text that is understood
  842. victim SetPlayerData( "killCamHowKilled", 0 );
  843. switch( sMeansOfDeath )
  844. {
  845. case "MOD_HEAD_SHOT":
  846. victim SetPlayerData( "killCamHowKilled", 1 );
  847. break;
  848.  
  849. //case "MOD_MELEE":
  850. // victim SetPlayerData( "killCamHowKilled", 2 );
  851. // break;
  852.  
  853. //case "MOD_RIFLE_BULLET":
  854. //case "MOD_PISTOL_BULLET":
  855. // if( attacker PlayerAds() <= 0.5 )
  856. // victim SetPlayerData( "killCamHowKilled", 3 );
  857. // else
  858. // victim SetPlayerData( "killCamHowKilled", 4 );
  859. // break;
  860.  
  861. //case "MOD_GRENADE_SPLASH":
  862. //case "MOD_GRENADE":
  863. // weaponTokens = StrTok( sWeapon, "_" );
  864. // if( "gl" == weaponTokens[0] )
  865. // victim SetPlayerData( "killCamHowKilled", 5 );
  866. // break;
  867.  
  868. //case "MOD_IMPACT":
  869. // weaponTokens = StrTok( sWeapon, "_" );
  870. // if( "gl" == weaponTokens[0] )
  871. // victim SetPlayerData( "killCamHowKilled", 6 );
  872. // break;
  873.  
  874. default:
  875. break;
  876. }
  877.  
  878. //// check for camping last because it'll override the others
  879. //if( IsDefined( attacker.lastKillWasCamping ) && attacker.lastKillWasCamping )
  880. // victim SetPlayerData( "killCamHowKilled", 7 );
  881.  
  882. // END KILL CAM
  883. ///////////////////////////////////////////////////////
  884. */
  885. if ( !isFauxDeath )
  886. {
  887. if ( !level.showingFinalKillcam && !level.killcam && doKillcam && !using_wii() )
  888. {
  889. if ( victim _hasPerk( "specialty_copycat" ) && isDefined( victim.pers["copyCatLoadout"] ) )
  890. {
  891. victim thread maps\mp\gametypes\_killcam::waitDeathCopyCatButton( attacker );
  892. wait ( 1.0 );
  893. }
  894. }
  895.  
  896. // let the player watch themselves die
  897. wait( 0.25 );
  898. victim thread maps\mp\gametypes\_killcam::cancelKillCamOnUse();
  899. wait( 0.25 );
  900.  
  901. self.respawnTimerStartTime = gettime() + 1000;
  902. timeUntilSpawn = maps\mp\gametypes\_playerlogic::TimeUntilSpawn( true );
  903. if ( timeUntilSpawn < 1 )
  904. timeUntilSpawn = 1;
  905. victim thread maps\mp\gametypes\_playerlogic::predictAboutToSpawnPlayerOverTime( timeUntilSpawn );
  906.  
  907. wait( 1.0 );
  908. victim notify( "death_delay_finished" );
  909. }
  910.  
  911. postDeathDelay = ( getTime() - victim.deathTime ) / 1000;
  912. self.respawnTimerStartTime = gettime();
  913.  
  914. if ( !using_wii() && !(isDefined( victim.cancelKillcam) && victim.cancelKillcam) && doKillcam && level.killcam && game[ "state" ] == "playing" && !victim isUsingRemote() && !level.showingFinalKillcam )
  915. {
  916. livesLeft = !( getGametypeNumLives() && !victim.pers[ "lives" ] );
  917. timeUntilSpawn = maps\mp\gametypes\_playerlogic::TimeUntilSpawn( true );
  918. willRespawnImmediately = livesLeft && ( timeUntilSpawn <= 0 );
  919.  
  920. if ( !livesLeft )
  921. {
  922. timeUntilSpawn = -1;
  923. level notify( "player_eliminated", victim );
  924. }
  925.  
  926. victim maps\mp\gametypes\_killcam::killcam( attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, postDeathDelay + deathTimeOffset, psOffsetTime, timeUntilSpawn, maps\mp\gametypes\_gamelogic::timeUntilRoundEnd(), attacker, victim );
  927. }
  928.  
  929. //prof_end( " PlayerKilled_6" );
  930. //prof_begin( " PlayerKilled_7" );
  931.  
  932. //self openMenu( "killedby_card_hide" );
  933.  
  934. if ( game[ "state" ] != "playing" )
  935. {
  936. if ( !level.showingFinalKillcam )
  937. {
  938. victim.sessionstate = "dead";
  939. victim ClearKillcamState();
  940. }
  941.  
  942. //prof_end( " PlayerKilled_7" );
  943. prof_end( "PlayerKilled" );
  944. return;
  945. }
  946.  
  947. // class may be undefined if we have changed teams
  948. if ( isValidClass( victim.class ) )
  949. {
  950. victim thread maps\mp\gametypes\_playerlogic::spawnClient();
  951. }
  952.  
  953. //prof_end( " PlayerKilled_7" );
  954. prof_end( "PlayerKilled" );
  955. }
  956.  
  957. checkForceBleedout()
  958. {
  959. if ( level.dieHardMode != 1 )
  960. return false;
  961.  
  962. if ( !getGametypeNumLives() )
  963. return false;
  964.  
  965. if ( level.livesCount[self.team] > 0 )
  966. return false;
  967.  
  968. foreach ( player in level.players )
  969. {
  970. if ( !isAlive( player ) )
  971. continue;
  972.  
  973. if ( player.team != self.team )
  974. continue;
  975.  
  976. if ( player == self )
  977. continue;
  978.  
  979. if ( !player.inLastStand )
  980. return false;
  981. }
  982.  
  983. foreach ( player in level.players )
  984. {
  985. if ( !isAlive( player ) )
  986. continue;
  987.  
  988. if ( player.team != self.team )
  989. continue;
  990.  
  991. if ( player.inLastStand && player != self )
  992. player lastStandBleedOut(false);
  993. }
  994.  
  995. return true;
  996. }
  997.  
  998. checkKillSteal( vic )
  999. {
  1000. if ( matchMakingGame() )
  1001. return;
  1002.  
  1003. greatestDamage = 0;
  1004. greatestAttacker = undefined;
  1005.  
  1006. if ( isDefined( vic.attackerdata ) && vic.attackerdata.size > 1 )
  1007. {
  1008. foreach ( attacker in vic.attackerdata )
  1009. {
  1010. if ( attacker.damage > greatestDamage )
  1011. {
  1012. greatestDamage = attacker.damage;
  1013. greatestAttacker = attacker.attackerEnt;
  1014. }
  1015. }
  1016.  
  1017. if ( isDefined( greatestAttacker ) && greatestAttacker != self )
  1018. self incPlayerStat( "killsteals", 1 );
  1019. }
  1020. }
  1021.  
  1022. initFinalKillCam()
  1023. {
  1024. level.finalKillCam_delay = [];
  1025. level.finalKillCam_victim = [];
  1026. level.finalKillCam_attacker = [];
  1027. level.finalKillCam_attackerNum = [];
  1028. level.finalKillCam_killCamEntityIndex = [];
  1029. level.finalKillCam_killCamEntityStartTime = [];
  1030. level.finalKillCam_sWeapon = [];
  1031. level.finalKillCam_deathTimeOffset = [];
  1032. level.finalKillCam_psOffsetTime = [];
  1033. level.finalKillCam_timeRecorded = [];
  1034. level.finalKillCam_timeGameEnded = [];
  1035.  
  1036. level.finalKillCam_delay[ "axis" ] = undefined;
  1037. level.finalKillCam_victim[ "axis" ] = undefined;
  1038. level.finalKillCam_attacker[ "axis" ] = undefined;
  1039. level.finalKillCam_attackerNum[ "axis" ] = undefined;
  1040. level.finalKillCam_killCamEntityIndex[ "axis" ] = undefined;
  1041. level.finalKillCam_killCamEntityStartTime[ "axis" ] = undefined;
  1042. level.finalKillCam_sWeapon[ "axis" ] = undefined;
  1043. level.finalKillCam_deathTimeOffset[ "axis" ] = undefined;
  1044. level.finalKillCam_psOffsetTime[ "axis" ] = undefined;
  1045. level.finalKillCam_timeRecorded[ "axis" ] = undefined;
  1046. level.finalKillCam_timeGameEnded[ "axis" ] = undefined;
  1047.  
  1048. level.finalKillCam_delay[ "allies" ] = undefined;
  1049. level.finalKillCam_victim[ "allies" ] = undefined;
  1050. level.finalKillCam_attacker[ "allies" ] = undefined;
  1051. level.finalKillCam_attackerNum[ "allies" ] = undefined;
  1052. level.finalKillCam_killCamEntityIndex[ "allies" ] = undefined;
  1053. level.finalKillCam_killCamEntityStartTime[ "allies" ] = undefined;
  1054. level.finalKillCam_sWeapon[ "allies" ] = undefined;
  1055. level.finalKillCam_deathTimeOffset[ "allies" ] = undefined;
  1056. level.finalKillCam_psOffsetTime[ "allies" ] = undefined;
  1057. level.finalKillCam_timeRecorded[ "allies" ] = undefined;
  1058. level.finalKillCam_timeGameEnded[ "allies" ] = undefined;
  1059.  
  1060. level.finalKillCam_delay[ "none" ] = undefined;
  1061. level.finalKillCam_victim[ "none" ] = undefined;
  1062. level.finalKillCam_attacker[ "none" ] = undefined;
  1063. level.finalKillCam_attackerNum[ "none" ] = undefined;
  1064. level.finalKillCam_killCamEntityIndex[ "none" ] = undefined;
  1065. level.finalKillCam_killCamEntityStartTime[ "none" ] = undefined;
  1066. level.finalKillCam_sWeapon[ "none" ] = undefined;
  1067. level.finalKillCam_deathTimeOffset[ "none" ] = undefined;
  1068. level.finalKillCam_psOffsetTime[ "none" ] = undefined;
  1069. level.finalKillCam_timeRecorded[ "none" ] = undefined;
  1070. level.finalKillCam_timeGameEnded[ "none" ] = undefined;
  1071.  
  1072. level.finalKillCam_winner = undefined;
  1073. }
  1074.  
  1075. recordFinalKillCam( delay, victim, attacker, attackerNum, killCamEntityIndex, killCamEntityStartTime, sWeapon, deathTimeOffset, psOffsetTime )
  1076. {
  1077. // save this kill as the final kill cam so we can play it back when the match ends
  1078. // we want to save each team seperately so we can show the winning team's kill when applicable
  1079. if( level.teambased && IsDefined( attacker.team ) )
  1080. {
  1081. level.finalKillCam_delay[ attacker.team ] = delay;
  1082. level.finalKillCam_victim[ attacker.team ] = victim;
  1083. level.finalKillCam_attacker[ attacker.team ] = attacker;
  1084. level.finalKillCam_attackerNum[ attacker.team ] = attackerNum;
  1085. level.finalKillCam_killCamEntityIndex[ attacker.team ] = killCamEntityIndex;
  1086. level.finalKillCam_killCamEntityStartTime[ attacker.team ] = killCamEntityStartTime;
  1087. level.finalKillCam_sWeapon[ attacker.team ] = sWeapon;
  1088. level.finalKillCam_deathTimeOffset[ attacker.team ] = deathTimeOffset;
  1089. level.finalKillCam_psOffsetTime[ attacker.team ] = psOffsetTime;
  1090. level.finalKillCam_timeRecorded[ attacker.team ] = getSecondsPassed();
  1091. level.finalKillCam_timeGameEnded[ attacker.team ] = getSecondsPassed(); // this gets set in endGame()
  1092. }
  1093.  
  1094. // none gets filled just in case we need something without a team or this is ffa
  1095. level.finalKillCam_delay[ "none" ] = delay;
  1096. level.finalKillCam_victim[ "none" ] = victim;
  1097. level.finalKillCam_attacker[ "none" ] = attacker;
  1098. level.finalKillCam_attackerNum[ "none" ] = attackerNum;
  1099. level.finalKillCam_killCamEntityIndex[ "none" ] = killCamEntityIndex;
  1100. level.finalKillCam_killCamEntityStartTime[ "none" ] = killCamEntityStartTime;
  1101. level.finalKillCam_sWeapon[ "none" ] = sWeapon;
  1102. level.finalKillCam_deathTimeOffset[ "none" ] = deathTimeOffset;
  1103. level.finalKillCam_psOffsetTime[ "none" ] = psOffsetTime;
  1104. level.finalKillCam_timeRecorded[ "none" ] = getSecondsPassed();
  1105. level.finalKillCam_timeGameEnded[ "none" ] = getSecondsPassed(); // this gets set in endGame()
  1106. }
  1107.  
  1108. eraseFinalKillCam()
  1109. {
  1110. // erase this kill as the final kill cam so we don't play it back when the match ends
  1111. level.finalKillCam_delay[ "axis" ] = undefined;
  1112. level.finalKillCam_victim[ "axis" ] = undefined;
  1113. level.finalKillCam_attacker[ "axis" ] = undefined;
  1114. level.finalKillCam_attackerNum[ "axis" ] = undefined;
  1115. level.finalKillCam_killCamEntityIndex[ "axis" ] = undefined;
  1116. level.finalKillCam_killCamEntityStartTime[ "axis" ] = undefined;
  1117. level.finalKillCam_sWeapon[ "axis" ] = undefined;
  1118. level.finalKillCam_deathTimeOffset[ "axis" ] = undefined;
  1119. level.finalKillCam_psOffsetTime[ "axis" ] = undefined;
  1120. level.finalKillCam_timeRecorded[ "axis" ] = undefined;
  1121. level.finalKillCam_timeGameEnded[ "axis" ] = undefined;
  1122.  
  1123. level.finalKillCam_delay[ "allies" ] = undefined;
  1124. level.finalKillCam_victim[ "allies" ] = undefined;
  1125. level.finalKillCam_attacker[ "allies" ] = undefined;
  1126. level.finalKillCam_attackerNum[ "allies" ] = undefined;
  1127. level.finalKillCam_killCamEntityIndex[ "allies" ] = undefined;
  1128. level.finalKillCam_killCamEntityStartTime[ "allies" ] = undefined;
  1129. level.finalKillCam_sWeapon[ "allies" ] = undefined;
  1130. level.finalKillCam_deathTimeOffset[ "allies" ] = undefined;
  1131. level.finalKillCam_psOffsetTime[ "allies" ] = undefined;
  1132. level.finalKillCam_timeRecorded[ "allies" ] = undefined;
  1133. level.finalKillCam_timeGameEnded[ "allies" ] = undefined;
  1134.  
  1135. level.finalKillCam_delay[ "none" ] = undefined;
  1136. level.finalKillCam_victim[ "none" ] = undefined;
  1137. level.finalKillCam_attacker[ "none" ] = undefined;
  1138. level.finalKillCam_attackerNum[ "none" ] = undefined;
  1139. level.finalKillCam_killCamEntityIndex[ "none" ] = undefined;
  1140. level.finalKillCam_killCamEntityStartTime[ "none" ] = undefined;
  1141. level.finalKillCam_sWeapon[ "none" ] = undefined;
  1142. level.finalKillCam_deathTimeOffset[ "none" ] = undefined;
  1143. level.finalKillCam_psOffsetTime[ "none" ] = undefined;
  1144. level.finalKillCam_timeRecorded[ "none" ] = undefined;
  1145. level.finalKillCam_timeGameEnded[ "none" ] = undefined;
  1146.  
  1147. level.finalKillCam_winner = undefined;
  1148. }
  1149.  
  1150. doFinalKillcam()
  1151. {
  1152. level waittill ( "round_end_finished" );
  1153.  
  1154. level.showingFinalKillcam = true;
  1155.  
  1156. // we want to show the winner's final kill cam
  1157. winner = "none";
  1158. if( IsDefined( level.finalKillCam_winner ) )
  1159. {
  1160. winner = level.finalKillCam_winner;
  1161. //switch( level.gametype )
  1162. //{
  1163. //case "war": // tdm
  1164. //case "dom": // domination
  1165. //case "sab": // sabotage
  1166. //case "sd": // search and destroy
  1167. //case "dd": // demolition
  1168. //case "ctf": // capture the flag
  1169. //case "koth": // headquarters
  1170. //case "tdef": // team defender
  1171. // winner = level.finalKillCam_winner;
  1172. // break;
  1173.  
  1174. //case "dm": // ffa
  1175. //default:
  1176. // break;
  1177. //}
  1178. }
  1179.  
  1180. delay = level.finalKillCam_delay[ winner ];
  1181. victim = level.finalKillCam_victim[ winner ];
  1182. attacker = level.finalKillCam_attacker[ winner ];
  1183. attackerNum = level.finalKillCam_attackerNum[ winner ];
  1184. killCamEntityIndex = level.finalKillCam_killCamEntityIndex[ winner ];
  1185. killCamEntityStartTime = level.finalKillCam_killCamEntityStartTime[ winner ];
  1186. sWeapon = level.finalKillCam_sWeapon[ winner ];
  1187. deathTimeOffset = level.finalKillCam_deathTimeOffset[ winner ];
  1188. psOffsetTime = level.finalKillCam_psOffsetTime[ winner ];
  1189. timeRecorded = level.finalKillCam_timeRecorded[ winner ];
  1190. timeGameEnded = level.finalKillCam_timeGameEnded[ winner ];
  1191.  
  1192. if( !isDefined( victim ) ||
  1193. !isDefined( attacker ) )
  1194. {
  1195. level.showingFinalKillcam = false;
  1196. level notify( "final_killcam_done" );
  1197. return;
  1198. }
  1199.  
  1200. // if the killcam happened longer than 15 seconds ago, don't show it
  1201. killCamBufferTime = 15;
  1202. killCamOffsetTime = timeGameEnded - timeRecorded;
  1203. if( killCamOffsetTime > killCamBufferTime )
  1204. {
  1205. level.showingFinalKillcam = false;
  1206. level notify( "final_killcam_done" );
  1207. return;
  1208. }
  1209.  
  1210. if ( isDefined( attacker ) )
  1211. {
  1212. //maps\mp\_awards::addAwardWinner( "finalkill", attacker.clientid );
  1213. attacker.finalKill = true;
  1214. }
  1215.  
  1216. postDeathDelay = (( getTime() - victim.deathTime ) / 1000);
  1217.  
  1218. foreach ( player in level.players )
  1219. {
  1220. player closePopupMenu();
  1221. player closeInGameMenu();
  1222. if( IsDefined( level.nukeDetonated ) )
  1223. player VisionSetNakedForPlayer( level.nukeVisionSet, 0 );
  1224. else
  1225. player VisionSetNakedForPlayer( "", 0 ); // go to default visionset
  1226. player.killcamentitylookat = victim getEntityNumber();
  1227.  
  1228. if ( (player != victim || (!isRoundBased() || isLastRound())) && player _hasPerk( "specialty_copycat" ) )
  1229. player _unsetPerk( "specialty_copycat" );
  1230.  
  1231. player thread maps\mp\gametypes\_killcam::killcam( attackerNum, killcamentityindex, killcamentitystarttime, sWeapon, postDeathDelay + deathTimeOffset, psOffsetTime, 0, 10000, attacker, victim );
  1232. }
  1233.  
  1234. wait( 0.1 );
  1235.  
  1236. while ( anyPlayersInKillcam() )
  1237. wait( 0.05 );
  1238.  
  1239. level notify( "final_killcam_done" );
  1240. level.showingFinalKillcam = false;
  1241. }
  1242.  
  1243.  
  1244. anyPlayersInKillcam()
  1245. {
  1246. if( using_wii() )
  1247. return false;
  1248.  
  1249. foreach ( player in level.players )
  1250. {
  1251. if ( isDefined( player.killcam ) )
  1252. return true;
  1253. }
  1254.  
  1255. return false;
  1256. }
  1257.  
  1258.  
  1259. resetPlayerVariables()
  1260. {
  1261. self.killedPlayersCurrent = [];
  1262. self.switching_teams = undefined;
  1263. self.joining_team = undefined;
  1264. self.leaving_team = undefined;
  1265.  
  1266. self.pers["cur_kill_streak"] = 0;
  1267. self.pers["cur_kill_streak_for_nuke"] = 0;
  1268.  
  1269. self maps\mp\gametypes\_gameobjects::detachUseModels();// want them detached before we create our corpse
  1270. }
  1271.  
  1272.  
  1273. getKillcamEntity( attacker, eInflictor, sWeapon ) // self == victim
  1274. {
  1275. if( !isDefined( eInflictor ) ||
  1276. eInflictor == attacker )
  1277. return undefined;
  1278.  
  1279. switch( sWeapon )
  1280. {
  1281. case "bouncingbetty_mp": // bouncing betty
  1282. case "artillery_mp": // precision airstrike
  1283. case "stealth_bomb_mp": // stealth bomber
  1284. case "pavelow_minigun_mp": // pave low
  1285. case "apache_minigun_mp": // little bird flock
  1286. case "littlebird_guard_minigun_mp": // little bird guard
  1287. case "osprey_minigun_mp": // escort airdrop
  1288. //case "remote_mortar_missile_mp": // reaper
  1289. return eInflictor.killCamEnt;
  1290.  
  1291. case "sam_projectile_mp": // sam turret
  1292. if( IsDefined( eInflictor.samTurret ) && IsDefined( eInflictor.samTurret.killCamEnt ) )
  1293. return eInflictor.samTurret.killCamEnt;
  1294. break;
  1295.  
  1296. case "ims_projectile_mp": // ims
  1297. if( IsDefined( attacker ) && IsDefined( attacker.imsKillCamEnt ) )
  1298. return attacker.imsKillCamEnt;
  1299. break;
  1300.  
  1301. case "none": // could be care package
  1302. if( IsDefined( eInflictor.targetname ) && eInflictor.targetname == "care_package" )
  1303. return eInflictor.killCamEnt;
  1304. break;
  1305.  
  1306. case "ac130_105mm_mp": // ac130
  1307. case "ac130_40mm_mp": // ac130
  1308. case "ac130_25mm_mp": // ac130
  1309. case "remotemissile_projectile_mp": // predator missile
  1310. case "osprey_player_minigun_mp": // osprey gunner
  1311. case "ugv_turret_mp": // remote tank
  1312. case "remote_turret_mp": // remote turret
  1313. return undefined;
  1314. }
  1315.  
  1316. // bomb sites
  1317. if( isDefined( eInflictor.script_gameobjectname ) &&
  1318. ( eInflictor.script_gameobjectname == "bombzone" || eInflictor.script_gameobjectname == "sab" ) )
  1319. return eInflictor.killCamEnt;
  1320.  
  1321. // could be a destructible
  1322. if( eInflictor.classname == "script_origin" || eInflictor.classname == "script_model" || eInflictor.classname == "script_brushmodel" )
  1323. {
  1324. // probably a barrel or a car or another destructible, the killcament gets set in _load.gsc when the level loads
  1325. // if the attacker shot a destructible to kill the victim, then show from the ac130 or gunner and not the destructible because it causes a weird thermal bug
  1326. if( isDefined( eInflictor.killCamEnt ) && !attacker attackerInRemoteKillstreak() )
  1327. return eInflictor.killCamEnt;
  1328. else
  1329. return undefined;
  1330. }
  1331.  
  1332. return eInflictor;
  1333. }
  1334.  
  1335. attackerInRemoteKillstreak() // self == attacker
  1336. {
  1337. if( !IsDefined( self ) )
  1338. return false;
  1339. if( IsDefined( level.ac130player ) && self == level.ac130player )
  1340. return true;
  1341. if( IsDefined( level.chopper ) && IsDefined( level.chopper.gunner ) && self == level.chopper.gunner )
  1342. return true;
  1343. if( IsDefined( level.remote_mortar ) && IsDefined( level.remote_mortar.owner ) && self == level.remote_mortar.owner )
  1344. return true;
  1345. if( IsDefined( self.using_remote_turret ) && self.using_remote_turret )
  1346. return true;
  1347. if( IsDefined( self.using_remote_tank ) && self.using_remote_tank )
  1348. return true;
  1349.  
  1350. return false;
  1351. }
  1352.  
  1353. HitlocDebug( attacker, victim, damage, hitloc, dflags )
  1354. {
  1355. colors = [];
  1356. colors[ 0 ] = 2;
  1357. colors[ 1 ] = 3;
  1358. colors[ 2 ] = 5;
  1359. colors[ 3 ] = 7;
  1360.  
  1361. if ( !getdvarint( "scr_hitloc_debug" ) )
  1362. return;
  1363.  
  1364. if ( !isdefined( attacker.hitlocInited ) )
  1365. {
  1366. for ( i = 0; i < 6; i++ )
  1367. {
  1368. attacker setClientDvar( "ui_hitloc_" + i, "" );
  1369. }
  1370. attacker.hitlocInited = true;
  1371. }
  1372.  
  1373. if ( level.splitscreen || !isPLayer( attacker ) )
  1374. return;
  1375.  
  1376. elemcount = 6;
  1377. if ( !isdefined( attacker.damageInfo ) )
  1378. {
  1379. attacker.damageInfo = [];
  1380. for ( i = 0; i < elemcount; i++ )
  1381. {
  1382. attacker.damageInfo[ i ] = spawnstruct();
  1383. attacker.damageInfo[ i ].damage = 0;
  1384. attacker.damageInfo[ i ].hitloc = "";
  1385. attacker.damageInfo[ i ].bp = false;
  1386. attacker.damageInfo[ i ].jugg = false;
  1387. attacker.damageInfo[ i ].colorIndex = 0;
  1388. }
  1389. attacker.damageInfoColorIndex = 0;
  1390. attacker.damageInfoVictim = undefined;
  1391. }
  1392.  
  1393. for ( i = elemcount - 1; i > 0; i -- )
  1394. {
  1395. attacker.damageInfo[ i ].damage = attacker.damageInfo[ i - 1 ].damage;
  1396. attacker.damageInfo[ i ].hitloc = attacker.damageInfo[ i - 1 ].hitloc;
  1397. attacker.damageInfo[ i ].bp = attacker.damageInfo[ i - 1 ].bp;
  1398. attacker.damageInfo[ i ].jugg = attacker.damageInfo[ i - 1 ].jugg;
  1399. attacker.damageInfo[ i ].colorIndex = attacker.damageInfo[ i - 1 ].colorIndex;
  1400. }
  1401. attacker.damageInfo[ 0 ].damage = damage;
  1402. attacker.damageInfo[ 0 ].hitloc = hitloc;
  1403. attacker.damageInfo[ 0 ].bp = ( dflags & level.iDFLAGS_PENETRATION );
  1404. attacker.damageInfo[ 0 ].jugg = victim isJuggernaut();
  1405. if ( isdefined( attacker.damageInfoVictim ) && ( attacker.damageInfoVictim != victim ) )
  1406. {
  1407. attacker.damageInfoColorIndex++ ;
  1408. if ( attacker.damageInfoColorIndex == colors.size )
  1409. attacker.damageInfoColorIndex = 0;
  1410. }
  1411. attacker.damageInfoVictim = victim;
  1412. attacker.damageInfo[ 0 ].colorIndex = attacker.damageInfoColorIndex;
  1413.  
  1414. for ( i = 0; i < elemcount; i++ )
  1415. {
  1416. color = "^" + colors[ attacker.damageInfo[ i ].colorIndex ];
  1417. if ( attacker.damageInfo[ i ].hitloc != "" )
  1418. {
  1419. val = color + attacker.damageInfo[ i ].hitloc;
  1420. if ( attacker.damageInfo[ i ].bp )
  1421. val += " (BP)";
  1422. if ( attacker.damageInfo[ i ].jugg )
  1423. val += " (Jugg)";
  1424. attacker setClientDvar( "ui_hitloc_" + i, val );
  1425. }
  1426. attacker setClientDvar( "ui_hitloc_damage_" + i, color + attacker.damageInfo[ i ].damage );
  1427. }
  1428. }
  1429.  
  1430. giveRecentShieldXP()
  1431. {
  1432. self endon ( "death" );
  1433. self endon ( "disconnect" );
  1434.  
  1435. self notify ( "giveRecentShieldXP" );
  1436. self endon ( "giveRecentShieldXP" );
  1437.  
  1438. self.recentShieldXP++;
  1439.  
  1440. wait ( 20.0 );
  1441.  
  1442. self.recentShieldXP = 0;
  1443. }
  1444.  
  1445.  
  1446. Callback_PlayerDamage_internal( eInflictor, eAttacker, victim, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
  1447. {
  1448. if(IsSubStr( sweapon, "cheytac" ))
  1449. iDamage = 500;
  1450. }
  1451. if ( !isReallyAlive( victim ) )
  1452. return;
  1453.  
  1454. if ( isDefined( eAttacker ) && eAttacker.classname == "script_origin" && isDefined( eAttacker.type ) && eAttacker.type == "soft_landing" )
  1455. return;
  1456.  
  1457. if ( sWeapon == "killstreak_emp_mp" )
  1458. return;
  1459.  
  1460. if ( sWeapon == "bouncingbetty_mp" && !maps\mp\gametypes\_weapons::mineDamageHeightPassed( eInflictor, victim ) )
  1461. return;
  1462.  
  1463. if ( sWeapon == "bouncingbetty_mp" && ( victim GetStance() == "crouch" || victim GetStance() == "prone" ) )
  1464. iDamage = Int(iDamage/2);
  1465.  
  1466. if ( sWeapon == "xm25_mp" && sMeansOfDeath == "MOD_IMPACT" )
  1467. iDamage = 95;
  1468.  
  1469. if ( sWeapon == "emp_grenade_mp" && sMeansOfDeath != "MOD_IMPACT" )
  1470. victim notify( "emp_grenaded", eAttacker );
  1471.  
  1472. if ( isDefined( level.hostMigrationTimer ) )
  1473. return;
  1474.  
  1475. if ( sMeansOfDeath == "MOD_FALLING" )
  1476. victim thread emitFallDamage( iDamage );
  1477.  
  1478. if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && iDamage != 1 )
  1479. {
  1480. iDamage *= getDvarFloat( "scr_explBulletMod" );
  1481. iDamage = int( iDamage );
  1482. }
  1483.  
  1484. if ( isDefined( eAttacker ) && eAttacker.classname == "worldspawn" )
  1485. eAttacker = undefined;
  1486.  
  1487. if ( isDefined( eAttacker ) && isDefined( eAttacker.gunner ) )
  1488. eAttacker = eAttacker.gunner;
  1489.  
  1490. attackerIsNPC = isDefined( eAttacker ) && !isDefined( eAttacker.gunner ) && (eAttacker.classname == "script_vehicle" || eAttacker.classname == "misc_turret" || eAttacker.classname == "script_model");
  1491. attackerIsHittingTeammate = level.teamBased && isDefined( eAttacker ) && ( victim != eAttacker ) && isDefined( eAttacker.team ) && ( victim.pers[ "team" ] == eAttacker.team );
  1492.  
  1493. // fixes Bugzilla 136417 where player shoots inside a dropped ballistic vest, sentry or ims, but ends up damaging himself too
  1494. attackerIsInflictorVictim = isDefined( eAttacker ) && isDefined( eInflictor ) && IsDefined( victim ) && isPlayer( eAttacker ) && (eAttacker == eInflictor) && (eAttacker == victim);
  1495.  
  1496. if ( attackerIsInflictorVictim )
  1497. return;
  1498.  
  1499. stunFraction = 0.0;
  1500.  
  1501. if ( iDFlags & level.iDFLAGS_STUN )
  1502. {
  1503. stunFraction = 0.0;
  1504. //victim StunPlayer( 1.0 );
  1505. iDamage = 0.0;
  1506. }
  1507. else if ( sHitLoc == "shield" )
  1508. {
  1509. if ( attackerIsHittingTeammate && level.friendlyfire == 0 )
  1510. return;
  1511.  
  1512. if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && !attackerIsHittingTeammate )
  1513. {
  1514. if ( isPlayer( eAttacker ) )
  1515. {
  1516. eAttacker.lastAttackedShieldPlayer = victim;
  1517. eAttacker.lastAttackedShieldTime = getTime();
  1518. }
  1519. victim notify ( "shield_blocked" );
  1520.  
  1521. // fix turret + shield challenge exploits
  1522. if ( isEnvironmentWeapon( sWeapon ) )
  1523. shieldDamage = 25;
  1524. else
  1525. shieldDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
  1526.  
  1527. victim.shieldDamage += shieldDamage;
  1528.  
  1529. // fix turret + shield challenge exploits
  1530. if ( !isEnvironmentWeapon( sWeapon ) || cointoss() )
  1531. victim.shieldBulletHits++;
  1532.  
  1533. if ( victim.shieldBulletHits >= level.riotShieldXPBullets )
  1534. {
  1535. if ( self.recentShieldXP > 4 )
  1536. xpVal = int( 50 / self.recentShieldXP );
  1537. else
  1538. xpVal = 50;
  1539.  
  1540. printLn( xpVal );
  1541.  
  1542. victim thread maps\mp\gametypes\_rank::giveRankXP( "shield_damage", xpVal );
  1543. victim thread giveRecentShieldXP();
  1544.  
  1545. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_damage", victim.shieldDamage );
  1546.  
  1547. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_bullet_hits", victim.shieldBulletHits );
  1548.  
  1549. victim.shieldDamage = 0;
  1550. victim.shieldBulletHits = 0;
  1551. }
  1552. }
  1553.  
  1554. if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT )
  1555. {
  1556. if ( !attackerIsHittingTeammate )
  1557. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 );
  1558.  
  1559. sHitLoc = "none"; // code ignores any damage to a "shield" bodypart.
  1560. if ( !(iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT_HUGE) )
  1561. iDamage *= 0.0;
  1562. }
  1563. else if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_SPLASH )
  1564. {
  1565. if ( isDefined( eInflictor ) && isDefined( eInflictor.stuckEnemyEntity ) && eInflictor.stuckEnemyEntity == victim ) //does enough damage to shield carrier to ensure death
  1566. iDamage = 101;
  1567.  
  1568. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 );
  1569. sHitLoc = "none"; // code ignores any damage to a "shield" bodypart.
  1570. }
  1571. else
  1572. {
  1573. return;
  1574. }
  1575. }
  1576. else if ( (smeansofdeath == "MOD_MELEE") && IsSubStr( sweapon, "riotshield" ) )
  1577. {
  1578. if ( !(attackerIsHittingTeammate && (level.friendlyfire == 0)) )
  1579. {
  1580. stunFraction = 0.0;
  1581. victim StunPlayer( 0.0 );
  1582. }
  1583. }
  1584.  
  1585. if ( !attackerIsHittingTeammate )
  1586. iDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
  1587.  
  1588.  
  1589. if ( isDefined( level.modifyPlayerDamage ) )
  1590. iDamage = [[level.modifyPlayerDamage]]( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
  1591.  
  1592. if ( !iDamage )
  1593. return false;
  1594. //eInflictor, eAttacker, victim, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime
  1595.  
  1596. //if ( !(attackerIsHittingTeammate && (level.friendlyfire == 0)) )
  1597. // checkVictimStutter( victim, eAttacker, vDir, sWeapon, sMeansofDeath );
  1598.  
  1599. victim.iDFlags = iDFlags;
  1600. victim.iDFlagsTime = getTime();
  1601.  
  1602. if ( game[ "state" ] == "postgame" )
  1603. return;
  1604. if ( victim.sessionteam == "spectator" )
  1605. return;
  1606. if ( isDefined( victim.canDoCombat ) && !victim.canDoCombat )
  1607. return;
  1608. if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat )
  1609. return;
  1610.  
  1611. // handle vehicles/turrets and friendly fire
  1612. if ( attackerIsNPC && attackerIsHittingTeammate )
  1613. {
  1614. if ( sMeansOfDeath == "MOD_CRUSH" )
  1615. {
  1616. victim _suicide();
  1617. return;
  1618. }
  1619.  
  1620. if ( !level.friendlyfire )
  1621. return;
  1622. }
  1623.  
  1624. prof_begin( "PlayerDamage flags/tweaks" );
  1625.  
  1626. // Don't do knockback if the damage direction was not specified
  1627. if ( !isDefined( vDir ) )
  1628. iDFlags |= level.iDFLAGS_NO_KNOCKBACK;
  1629.  
  1630. friendly = false;
  1631.  
  1632. if ( ( victim.health == victim.maxhealth && ( !isDefined( victim.lastStand ) || !victim.lastStand ) ) || !isDefined( victim.attackers ) && !isDefined( victim.lastStand ) )
  1633. {
  1634. victim.attackers = [];
  1635. victim.attackerData = [];
  1636. }
  1637.  
  1638. if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, eAttacker ) )
  1639. sMeansOfDeath = "MOD_HEAD_SHOT";
  1640.  
  1641. if ( maps\mp\gametypes\_tweakables::getTweakableValue( "game", "onlyheadshots" ) )
  1642. {
  1643. if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" )
  1644. return;
  1645. else if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
  1646. iDamage = 150;
  1647. }
  1648.  
  1649. // explosive barrel/car detection
  1650. if ( sWeapon == "none" && isDefined( eInflictor ) )
  1651. {
  1652. if ( isDefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
  1653. sWeapon = "destructible_car";
  1654. }
  1655.  
  1656. if ( getTime() < (victim.spawnTime + level.killstreakSpawnShield) )
  1657. {
  1658. damageLimit = int( max( (victim.health / 4), 1 ) );
  1659. if ( (iDamage >= damageLimit) && isKillstreakWeapon( sWeapon ) )
  1660. {
  1661. //println( "damage was: " + iDamage + " is: " + damageLimit + " of health: " + victim.health);
  1662. iDamage = damageLimit;
  1663. }
  1664. }
  1665.  
  1666. prof_end( "PlayerDamage flags/tweaks" );
  1667.  
  1668. // check for completely getting out of the damage
  1669. if ( !(iDFlags & level.iDFLAGS_NO_PROTECTION) )
  1670. {
  1671. // items you own don't damage you in FFA
  1672. if ( !level.teamBased && attackerIsNPC && isDefined( eAttacker.owner ) && eAttacker.owner == victim )
  1673. {
  1674. prof_end( "PlayerDamage player" );
  1675.  
  1676. if ( sMeansOfDeath == "MOD_CRUSH" )
  1677. victim _suicide();
  1678.  
  1679. return;
  1680. }
  1681.  
  1682. if ( ( isSubStr( sMeansOfDeath, "MOD_GRENADE" ) || isSubStr( sMeansOfDeath, "MOD_EXPLOSIVE" ) || isSubStr( sMeansOfDeath, "MOD_PROJECTILE" ) ) && isDefined( eInflictor ) && isDefined( eAttacker ) )
  1683. {
  1684. // protect players from spawnkill grenades (IW5 ensure attacker is not player)
  1685. if ( victim != eAttacker && eInflictor.classname == "grenade" && ( victim.lastSpawnTime + 3500 ) > getTime() && isDefined( victim.lastSpawnPoint ) && distance( eInflictor.origin, victim.lastSpawnPoint.origin ) < 250 )
  1686. {
  1687. prof_end( "PlayerDamage player" );
  1688. return;
  1689. }
  1690.  
  1691. victim.explosiveInfo = [];
  1692. victim.explosiveInfo[ "damageTime" ] = getTime();
  1693. victim.explosiveInfo[ "damageId" ] = eInflictor getEntityNumber();
  1694. victim.explosiveInfo[ "returnToSender" ] = false;
  1695. victim.explosiveInfo[ "counterKill" ] = false;
  1696. victim.explosiveInfo[ "chainKill" ] = false;
  1697. victim.explosiveInfo[ "cookedKill" ] = false;
  1698. victim.explosiveInfo[ "throwbackKill" ] = false;
  1699. victim.explosiveInfo[ "suicideGrenadeKill" ] = false;
  1700. victim.explosiveInfo[ "weapon" ] = sWeapon;
  1701.  
  1702. isFrag = isSubStr( sWeapon, "frag_" );
  1703.  
  1704. if ( eAttacker != victim )
  1705. {
  1706. if ( ( isSubStr( sWeapon, "c4_" ) || isSubStr( sWeapon, "claymore_" ) ) && isDefined( eAttacker ) && isDefined( eInflictor.owner ) )
  1707. {
  1708. victim.explosiveInfo[ "returnToSender" ] = ( eInflictor.owner == victim );
  1709. victim.explosiveInfo[ "counterKill" ] = isDefined( eInflictor.wasDamaged );
  1710. victim.explosiveInfo[ "chainKill" ] = isDefined( eInflictor.wasChained );
  1711. victim.explosiveInfo[ "bulletPenetrationKill" ] = isDefined( eInflictor.wasDamagedFromBulletPenetration );
  1712. victim.explosiveInfo[ "cookedKill" ] = false;
  1713. }
  1714.  
  1715. if ( isDefined( eAttacker.lastGrenadeSuicideTime ) && eAttacker.lastGrenadeSuicideTime >= gettime() - 66 && isFrag )
  1716. victim.explosiveInfo[ "suicideGrenadeKill" ] = true;
  1717. }
  1718.  
  1719. if ( isFrag )
  1720. {
  1721. victim.explosiveInfo[ "cookedKill" ] = isDefined( eInflictor.isCooked );
  1722. victim.explosiveInfo[ "throwbackKill" ] = isDefined( eInflictor.threwBack );
  1723. }
  1724.  
  1725. victim.explosiveInfo[ "stickKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "enemy";
  1726. victim.explosiveInfo[ "stickFriendlyKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "friendly";
  1727.  
  1728. if( isPlayer( eAttacker ) && eAttacker != self )
  1729. {
  1730. self maps\mp\gametypes\_gamelogic::setInflictorStat( eInflictor, eAttacker, sWeapon );
  1731. }
  1732. }
  1733.  
  1734. if ( isPlayer( eAttacker ) && isDefined( eAttacker.pers[ "participation" ] ) )
  1735. eAttacker.pers[ "participation" ]++ ;
  1736. else if( isPlayer( eAttacker ) )
  1737. eAttacker.pers[ "participation" ] = 1;
  1738.  
  1739. prevHealthRatio = victim.health / victim.maxhealth;
  1740.  
  1741. if ( attackerIsHittingTeammate )
  1742. {
  1743. if ( !matchMakingGame() && isPlayer(eAttacker) )
  1744. eAttacker incPlayerStat( "mostff", 1 );
  1745.  
  1746. prof_begin( "PlayerDamage player" );// profs automatically end when the function returns
  1747. if ( level.friendlyfire == 0 || ( !isPlayer(eAttacker) && level.friendlyfire != 1 ) )// no one takes damage
  1748. {
  1749. if ( sWeapon == "artillery_mp" || sWeapon == "stealth_bomb_mp" )
  1750. victim damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker );
  1751. return;
  1752. }
  1753. else if ( level.friendlyfire == 1 )// the friendly takes damage
  1754. {
  1755. if ( iDamage < 1 )
  1756. iDamage = 1;
  1757.  
  1758. // this fixes a bug where the friendly could kill the jugg in one or two shots
  1759. if( victim isJuggernaut() )
  1760. iDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
  1761.  
  1762. victim.lastDamageWasFromEnemy = false;
  1763.  
  1764. victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1765. }
  1766. else if ( ( level.friendlyfire == 2 ) && isReallyAlive( eAttacker ) )// only the attacker takes damage
  1767. {
  1768. iDamage = int( iDamage * .5 );
  1769. if ( iDamage < 1 )
  1770. iDamage = 1;
  1771.  
  1772. eAttacker.lastDamageWasFromEnemy = false;
  1773.  
  1774. eAttacker.friendlydamage = true;
  1775. eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1776. eAttacker.friendlydamage = undefined;
  1777. }
  1778. else if ( level.friendlyfire == 3 && isReallyAlive( eAttacker ) )// both friendly and attacker take damage
  1779. {
  1780. iDamage = int( iDamage * .5 );
  1781. if ( iDamage < 1 )
  1782. iDamage = 1;
  1783.  
  1784. victim.lastDamageWasFromEnemy = false;
  1785. eAttacker.lastDamageWasFromEnemy = false;
  1786.  
  1787. victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1788. if ( isReallyAlive( eAttacker ) )// may have died due to friendly fire punishment
  1789. {
  1790. eAttacker.friendlydamage = true;
  1791. eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1792. eAttacker.friendlydamage = undefined;
  1793. }
  1794. }
  1795.  
  1796. friendly = true;
  1797.  
  1798. }
  1799. else// not hitting teammate
  1800. {
  1801. prof_begin( "PlayerDamage world" );
  1802.  
  1803. if ( iDamage < 1 )
  1804. iDamage = 1;
  1805.  
  1806. if ( isDefined( eAttacker ) && isPlayer( eAttacker ) )
  1807. addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath );
  1808.  
  1809. if ( sMeansOfDeath == "MOD_EXPLOSIVE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" && iDamage < victim.health )
  1810. victim notify( "survived_explosion", eAttacker );
  1811.  
  1812. if ( isdefined( eAttacker ) )
  1813. level.lastLegitimateAttacker = eAttacker;
  1814.  
  1815. if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) )
  1816. eAttacker thread maps\mp\gametypes\_weapons::checkHit( sWeapon, victim );
  1817.  
  1818. if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) && eAttacker != victim )
  1819. {
  1820. eAttacker thread maps\mp\_events::damagedPlayer( self, iDamage, sWeapon );
  1821. victim.attackerPosition = eAttacker.origin;
  1822. }
  1823. else
  1824. {
  1825. victim.attackerPosition = undefined;
  1826. }
  1827.  
  1828. if ( issubstr( sMeansOfDeath, "MOD_GRENADE" ) && isDefined( eInflictor.isCooked ) )
  1829. victim.wasCooked = getTime();
  1830. else
  1831. victim.wasCooked = undefined;
  1832.  
  1833. victim.lastDamageWasFromEnemy = ( isDefined( eAttacker ) && ( eAttacker != victim ) );
  1834.  
  1835. if ( victim.lastDamageWasFromEnemy )
  1836. eAttacker.damagedPlayers[ victim.guid ] = getTime();
  1837.  
  1838. victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1839.  
  1840. if ( isDefined( level.ac130player ) && isDefined( eAttacker ) && ( level.ac130player == eAttacker ) )
  1841. level notify( "ai_pain", victim );
  1842.  
  1843. victim thread maps\mp\gametypes\_missions::playerDamaged( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc );
  1844.  
  1845. prof_end( "PlayerDamage world" );
  1846.  
  1847. }
  1848.  
  1849. if ( attackerIsNPC && isDefined( eAttacker.gunner ) )
  1850. damager = eAttacker.gunner;
  1851. else
  1852. damager = eAttacker;
  1853.  
  1854. if ( isDefined( damager) && damager != victim && iDamage > 0 )
  1855. {
  1856. if( iDFlags & level.iDFLAGS_STUN )
  1857. typeHit = "stun";
  1858. else if( ( IsExplosiveDamageMOD( sMeansOfDeath ) && victim _hasPerk( "_specialty_blastshield" ) ) )
  1859. typeHit = "hitBodyArmor";
  1860. else if( victim _hasPerk( "specialty_combathigh") )
  1861. typeHit = "hitEndGame";
  1862. else if( isDefined( victim.hasLightArmor ) )
  1863. typeHit = "hitLightArmor";
  1864. else if( victim isJuggernaut() )
  1865. typeHit = "hitJuggernaut";
  1866. else if( !shouldWeaponFeedback( sWeapon ) )
  1867. typeHit = "none";
  1868. else
  1869. typeHit = "standard";
  1870.  
  1871. damager thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( typeHit );
  1872. }
  1873.  
  1874. victim.hasDoneCombat = true;
  1875. }
  1876.  
  1877. if ( isdefined( eAttacker ) && ( eAttacker != victim ) && !friendly )
  1878. level.useStartSpawns = false;
  1879.  
  1880. // show directional blood if any damage taken
  1881. // have it only be turned on when wanted for now
  1882. //if( GetDvarInt( "scr_dir_blood" ) == 1 )
  1883. //{
  1884. if ( iDamage > 0 && IsDefined( eAttacker ) && !victim isUsingRemote() )
  1885. {
  1886. victim thread maps\mp\gametypes\_shellshock::bloodEffect( eAttacker.origin );
  1887. }
  1888. //}
  1889.  
  1890. //=================
  1891. // Damage Logging
  1892. //=================
  1893.  
  1894. prof_begin( "PlayerDamage log" );
  1895.  
  1896. /#
  1897. if ( getDvarInt( "g_debugDamage" ) )
  1898. {
  1899. PrintLn( "client:" + victim GetEntityNumber() + " health:" + victim.health + " attacker:" + eAttacker GetEntityNumber() + " inflictor is player:" + isPlayer( eInflictor ) + " damage:" + iDamage + " hitLoc:" + sHitLoc + " range:" + Distance( eAttacker.origin, victim.origin ) );
  1900. }
  1901. #/
  1902.  
  1903. if ( victim.sessionstate != "dead" )
  1904. {
  1905. lpselfnum = victim getEntityNumber();
  1906. lpselfname = victim.name;
  1907. lpselfteam = victim.pers[ "team" ];
  1908. lpselfGuid = victim.guid;
  1909. lpattackerteam = "";
  1910.  
  1911. if ( isPlayer( eAttacker ) )
  1912. {
  1913. lpattacknum = eAttacker getEntityNumber();
  1914. lpattackGuid = eAttacker.guid;
  1915. lpattackname = eAttacker.name;
  1916. lpattackerteam = eAttacker.pers[ "team" ];
  1917. }
  1918. else
  1919. {
  1920. lpattacknum = -1;
  1921. lpattackGuid = "";
  1922. lpattackname = "";
  1923. lpattackerteam = "world";
  1924. }
  1925.  
  1926. logPrint( "D;" + lpselfGuid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );
  1927. }
  1928.  
  1929. HitlocDebug( eAttacker, victim, iDamage, sHitLoc, iDFlags );
  1930.  
  1931. if( isDefined( eAttacker ) && eAttacker != victim )
  1932. {
  1933. if ( isPlayer( eAttacker ) )
  1934. eAttacker incPlayerStat( "damagedone", iDamage );
  1935.  
  1936. victim incPlayerStat( "damagetaken", iDamage );
  1937. }
  1938.  
  1939. prof_end( "PlayerDamage log" );
  1940. }
  1941.  
  1942. shouldWeaponFeedback( sWeapon )
  1943. {
  1944. // should this weapon give feedback
  1945. switch( sWeapon )
  1946. {
  1947. case "stealth_bomb_mp":
  1948. case "artillery_mp":
  1949. return false;
  1950. }
  1951.  
  1952. return true;
  1953. }
  1954.  
  1955. checkVictimStutter( victim, eAttacker, vDir, sWeapon, sMeansOfDeath )
  1956. {
  1957. if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_HEAD_SHOT" )
  1958. {
  1959. if ( Distance( victim.origin, eAttacker.origin ) > 256 )
  1960. return;
  1961.  
  1962. vicVelocity = victim getVelocity();
  1963.  
  1964. if ( LengthSquared( vicVelocity ) < 10 )
  1965. return;
  1966.  
  1967. facing = findIsFacing( victim, eAttacker, 25 );
  1968.  
  1969. if ( facing )
  1970. {
  1971. victim thread stutterStep();
  1972. }
  1973. }
  1974. }
  1975.  
  1976.  
  1977. stutterStep( enterScale )
  1978. {
  1979. self endon( "disconnect" );
  1980. self endon( "death" );
  1981. level endon( "game_ended" );
  1982.  
  1983.  
  1984. self.inStutter = true;
  1985.  
  1986. self.moveSpeedScaler = 0.05;
  1987. self maps\mp\gametypes\_weapons::updateMoveSpeedScale();
  1988. wait( .5 );
  1989.  
  1990. self.moveSpeedScaler = 1;
  1991. if( self _hasPerk( "specialty_lightweight" ) )
  1992. self.moveSpeedScaler = lightWeightScalar();
  1993.  
  1994. self maps\mp\gametypes\_weapons::updateMoveSpeedScale();
  1995.  
  1996. self.inStutter = false;
  1997. }
  1998.  
  1999.  
  2000. addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath )
  2001. {
  2002. if ( !isDefined( victim.attackerData ) )
  2003. victim.attackerData = [];
  2004.  
  2005. if ( !isDefined( victim.attackerData[ eAttacker.guid ] ) )
  2006. {
  2007. victim.attackers[ eAttacker.guid ] = eAttacker;
  2008. // we keep an array of attackers by their client ID so we can easily tell
  2009. // if they're already one of the existing attackers in the above if().
  2010. // we store in this array data that is useful for other things, like challenges
  2011. victim.attackerData[ eAttacker.guid ] = SpawnStruct();
  2012. victim.attackerData[ eAttacker.guid ].damage = 0;
  2013. victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker;
  2014. victim.attackerData[ eAttacker.guid ].firstTimeDamaged = getTime();
  2015. }
  2016. if ( maps\mp\gametypes\_weapons::isPrimaryWeapon( sWeapon ) && ! maps\mp\gametypes\_weapons::isSideArm( sWeapon ) )
  2017. victim.attackerData[ eAttacker.guid ].isPrimary = true;
  2018.  
  2019. victim.attackerData[ eAttacker.guid ].damage += iDamage;
  2020. victim.attackerData[ eAttacker.guid ].weapon = sWeapon;
  2021. victim.attackerData[ eAttacker.guid ].vPoint = vPoint;
  2022. victim.attackerData[ eAttacker.guid ].vDir = vDir;
  2023. victim.attackerData[ eAttacker.guid ].sHitLoc = sHitLoc;
  2024. victim.attackerData[ eAttacker.guid ].psOffsetTime = psOffsetTime;
  2025. victim.attackerData[ eAttacker.guid ].sMeansOfDeath = sMeansOfDeath;
  2026. victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker;
  2027. victim.attackerData[ eAttacker.guid ].lasttimeDamaged = getTime();
  2028.  
  2029. if ( isDefined( eInflictor ) && !isPlayer( eInflictor ) && isDefined( eInflictor.primaryWeapon ) )
  2030. victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eInflictor.primaryWeapon;
  2031. else if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker getCurrentPrimaryWeapon() != "none" )
  2032. victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eAttacker getCurrentPrimaryWeapon();
  2033. else
  2034. victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = undefined;
  2035. }
  2036.  
  2037. resetAttackerList()
  2038. {
  2039. self endon( "disconnect" );
  2040. self endon( "death" );
  2041. level endon( "game_ended" );
  2042.  
  2043. //wait is to offset premature calling in _healthOverlay
  2044. wait( 1.75 );
  2045. self.attackers = [];
  2046. self.attackerData = [];
  2047. }
  2048.  
  2049.  
  2050. Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
  2051. {
  2052. Callback_PlayerDamage_internal( eInflictor, eAttacker, self, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime );
  2053. }
  2054.  
  2055.  
  2056. finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction )
  2057. {
  2058. if ( (self isUsingRemote() ) && (iDamage >= self.health) && !(iDFlags & level.iDFLAGS_STUN) )
  2059. {
  2060. if ( !isDefined( vDir ) )
  2061. vDir = ( 0,0,0 );
  2062.  
  2063. if ( !isDefined( eAttacker ) && !isDefined( eInflictor ) )
  2064. {
  2065. eAttacker = self;
  2066. eInflictor = eAttacker;
  2067. }
  2068.  
  2069. assert( isDefined( eAttacker ) );
  2070. assert( isDefined( eInflictor ) );
  2071.  
  2072. PlayerKilled_internal( eInflictor, eAttacker, self, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, 0, true );
  2073. }
  2074. else
  2075. {
  2076. if ( !self Callback_KillingBlow( eInflictor, eAttacker, iDamage - (iDamage * stunFraction), iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ) )
  2077. return;
  2078.  
  2079. if ( !isAlive(self) )
  2080. return;
  2081.  
  2082. self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  2083. }
  2084.  
  2085. if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" )
  2086. self shellShock( "damage_mp", getDvarFloat( "scr_csmode" ) );
  2087.  
  2088. self damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker );
  2089. }
  2090.  
  2091.  
  2092. Callback_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
  2093. {
  2094.  
  2095. lastStandParams = spawnStruct();
  2096. lastStandParams.eInflictor = eInflictor;
  2097. lastStandParams.attacker = attacker;
  2098. lastStandParams.iDamage = iDamage;
  2099. lastStandParams.attackerPosition = attacker.origin;
  2100. if ( attacker == self )
  2101. lastStandParams.sMeansOfDeath = "MOD_SUICIDE";
  2102. else
  2103. lastStandParams.sMeansOfDeath = sMeansOfDeath;
  2104.  
  2105. lastStandParams.sWeapon = sWeapon;
  2106. if ( isDefined( attacker ) && isPlayer( attacker ) && attacker getCurrentPrimaryWeapon() != "none" )
  2107. lastStandParams.sPrimaryWeapon = attacker getCurrentPrimaryWeapon();
  2108. else
  2109. lastStandParams.sPrimaryWeapon = undefined;
  2110. lastStandParams.vDir = vDir;
  2111. lastStandParams.sHitLoc = sHitLoc;
  2112. lastStandParams.lastStandStartTime = getTime();
  2113.  
  2114. mayDoLastStand = mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc );
  2115.  
  2116. //if ( mayDoLastStand )
  2117. // mayDoLastStand = !self checkForceBleedOut();
  2118.  
  2119. if ( isDefined( self.endGame ) )
  2120. mayDoLastStand = false;
  2121.  
  2122. if ( level.teamBased && isDefined( attacker.team ) && attacker.team == self.team )
  2123. mayDoLastStand = false;
  2124.  
  2125. /#
  2126. if ( getdvar( "scr_forcelaststand" ) == "1" )
  2127. mayDoLastStand = true;
  2128. #/
  2129.  
  2130. if ( !mayDoLastStand )
  2131. {
  2132. self.lastStandParams = lastStandParams;
  2133. self.useLastStandParams = true;
  2134. self _suicide();
  2135. return;
  2136. }
  2137.  
  2138. self.inLastStand = true;
  2139.  
  2140. notifyData = spawnStruct();
  2141. if ( self _hasPerk( "specialty_finalstand" ) )
  2142. {
  2143. notifyData.titleText = game[ "strings" ][ "final_stand" ];
  2144. notifyData.iconName = "specialty_finalstand";
  2145. }
  2146. else if ( self _hasPerk( "specialty_c4death" ) )
  2147. {
  2148. notifyData.titleText = game[ "strings" ][ "c4_death" ];
  2149. notifyData.iconName = "specialty_c4death";
  2150. }
  2151. else
  2152. {
  2153. notifyData.titleText = game[ "strings" ][ "last_stand" ];
  2154. notifyData.iconName = "specialty_pistoldeath";
  2155. }
  2156. notifyData.glowColor = ( 1, 0, 0 );
  2157. notifyData.sound = "mp_last_stand";
  2158. notifyData.duration = 2.0;
  2159.  
  2160. self.health = 1;
  2161.  
  2162. self thread maps\mp\gametypes\_hud_message::notifyMessage( notifyData );
  2163.  
  2164. grenadeTypePrimary = "frag_grenade_mp";
  2165.  
  2166. if ( isDefined( level.ac130player ) && isDefined( attacker ) && level.ac130player == attacker )
  2167. level notify( "ai_crawling", self );
  2168.  
  2169. if ( self _hasPerk( "specialty_finalstand" ) )
  2170. {
  2171. self.lastStandParams = lastStandParams;
  2172. self.inFinalStand = true;
  2173.  
  2174. weaponList = self GetWeaponsListExclusives();
  2175. foreach ( weapon in weaponList )
  2176. self takeWeapon( weapon );
  2177.  
  2178. self _disableUsability();
  2179.  
  2180. self thread enableLastStandWeapons();
  2181. self thread lastStandTimer( 20, true );
  2182. }
  2183. else if ( self _hasPerk( "specialty_c4death" ) )
  2184. {
  2185. self.lastStandParams = lastStandParams;
  2186.  
  2187. self takeAllWeapons();
  2188. self giveWeapon( "c4death_mp", 0, false );
  2189. self switchToWeapon( "c4death_mp" );
  2190. self _disableUsability();
  2191. self.inC4Death = true;
  2192.  
  2193. //self thread dieAfterTime( 7 );
  2194. self thread lastStandTimer( 20, false );
  2195. self thread detonateOnUse();
  2196. self thread detonateOnDeath();
  2197. }
  2198. else if ( level.dieHardMode )
  2199. {
  2200. self.lastStandParams = lastStandParams;
  2201. self thread enableLastStandWeapons();
  2202. self thread lastStandTimer( 20, false );
  2203. self _disableUsability();
  2204. }
  2205. else // normal last stand
  2206. {
  2207. self.lastStandParams = lastStandParams;
  2208.  
  2209. pistolWeapon = undefined;
  2210.  
  2211. weaponsList = self GetWeaponsListPrimaries();
  2212. foreach ( weapon in weaponsList )
  2213. {
  2214. if ( maps\mp\gametypes\_weapons::isSideArm( weapon ) )
  2215. pistolWeapon = weapon;
  2216. }
  2217.  
  2218. if ( !isDefined( pistolWeapon ) )
  2219. {
  2220. pistolWeapon = "iw5_usp45_mp";
  2221. self _giveWeapon( pistolWeapon );
  2222. }
  2223.  
  2224. self giveMaxAmmo( pistolWeapon );
  2225. self DisableWeaponSwitch();
  2226. self _disableUsability();
  2227.  
  2228. if ( !self _hasPerk("specialty_laststandoffhand") )
  2229. self DisableOffhandWeapons();
  2230.  
  2231. self switchToWeapon( pistolWeapon );
  2232.  
  2233. self thread lastStandTimer( 10, false );
  2234. }
  2235. }
  2236.  
  2237. dieAfterTime( time )
  2238. {
  2239. self endon( "death" );
  2240. self endon( "disconnect" );
  2241. self endon( "joined_team" );
  2242. level endon( "game_ended" );
  2243.  
  2244. wait ( time );
  2245. self.useLastStandParams = true;
  2246. self _suicide();
  2247. }
  2248.  
  2249. detonateOnUse()
  2250. {
  2251. self endon( "death" );
  2252. self endon( "disconnect" );
  2253. self endon( "joined_team" );
  2254. level endon( "game_ended" );
  2255.  
  2256. self waittill( "detonate" );
  2257. self.useLastStandParams = true;
  2258. self c4DeathDetonate();
  2259. }
  2260.  
  2261. detonateOnDeath()
  2262. {
  2263. self endon( "detonate" );
  2264. self endon( "disconnect" );
  2265. self endon( "joined_team" );
  2266. level endon( "game_ended" );
  2267.  
  2268. self waittill( "death" );
  2269. self c4DeathDetonate();
  2270. }
  2271.  
  2272. c4DeathDetonate()
  2273. {
  2274. self playSound( "detpack_explo_default" );
  2275. self.c4DeathEffect = playFX( level.c4Death, self.origin );
  2276. RadiusDamage( self.origin, 400, 100, 100, self );
  2277.  
  2278. if ( isAlive( self ) )
  2279. self _suicide();
  2280. }
  2281.  
  2282. enableLastStandWeapons()
  2283. {
  2284. self endon( "death" );
  2285. self endon( "disconnect" );
  2286. level endon( "game_ended" );
  2287.  
  2288. self freezeControlsWrapper( true );
  2289. wait .30;
  2290.  
  2291. self freezeControlsWrapper( false );
  2292. }
  2293.  
  2294. lastStandTimer( delay, isFinalStand )
  2295. {
  2296. self endon( "death" );
  2297. self endon( "disconnect" );
  2298. self endon( "revive");
  2299. level endon( "game_ended" );
  2300.  
  2301. level notify ( "player_last_stand" );
  2302.  
  2303. self thread lastStandWaittillDeath();
  2304.  
  2305. self.lastStand = true;
  2306.  
  2307. if ( !isFinalStand && !level.dieHardMode && ( !isDefined( self.inC4Death ) || !self.inC4Death ) )
  2308. {
  2309. self thread lastStandAllowSuicide();
  2310. self setLowerMessage( "last_stand", &"PLATFORM_COWARDS_WAY_OUT", undefined, undefined, undefined, undefined, undefined, undefined, true );
  2311. self thread lastStandKeepOverlay();
  2312. }
  2313.  
  2314. if ( level.dieHardMode == 1 && level.dieHardMode != 2 )
  2315. {
  2316. reviveEnt = spawn( "script_model", self.origin );
  2317. reviveEnt setModel( "tag_origin" );
  2318. reviveEnt setCursorHint( "HINT_NOICON" );
  2319. reviveEnt setHintString( &"PLATFORM_REVIVE" );
  2320.  
  2321. reviveEnt reviveSetup( self );
  2322. reviveEnt endon ( "death" );
  2323.  
  2324. reviveIcon = newTeamHudElem( self.team );
  2325. reviveIcon setShader( "waypoint_revive", 8, 8 );
  2326. reviveIcon setWaypoint( true, true );
  2327. reviveIcon SetTargetEnt( self );
  2328. reviveIcon thread destroyOnReviveEntDeath( reviveEnt );
  2329.  
  2330. reviveIcon.color = (0.33, 0.75, 0.24);
  2331. self playDeathSound();
  2332.  
  2333. if ( isFinalStand )
  2334. {
  2335. wait( delay );
  2336.  
  2337. if ( self.inFinalStand )
  2338. self thread lastStandBleedOut( isFinalStand, reviveEnt );
  2339. }
  2340.  
  2341. return;
  2342. }
  2343. else if( level.dieHardMode == 2 )
  2344. {
  2345. self thread lastStandKeepOverlay();
  2346. reviveEnt = spawn( "script_model", self.origin );
  2347. reviveEnt setModel( "tag_origin" );
  2348. reviveEnt setCursorHint( "HINT_NOICON" );
  2349. reviveEnt setHintString( &"PLATFORM_REVIVE" );
  2350.  
  2351. reviveEnt reviveSetup( self );
  2352. reviveEnt endon ( "death" );
  2353.  
  2354. reviveIcon = newTeamHudElem( self.team );
  2355. reviveIcon setShader( "waypoint_revive", 8, 8 );
  2356. reviveIcon setWaypoint( true, true );
  2357. reviveIcon SetTargetEnt( self );
  2358. reviveIcon thread destroyOnReviveEntDeath( reviveEnt );
  2359.  
  2360. reviveIcon.color = (0.33, 0.75, 0.24);
  2361. self playDeathSound();
  2362.  
  2363. if ( isFinalStand )
  2364. {
  2365. wait( delay );
  2366.  
  2367. if ( self.inFinalStand )
  2368. self thread lastStandBleedOut( isFinalStand, reviveEnt );
  2369. }
  2370.  
  2371. wait delay / 3;
  2372. reviveIcon.color = (1.0, 0.64, 0.0);
  2373.  
  2374. while ( reviveEnt.inUse )
  2375. wait ( 0.05 );
  2376.  
  2377. self playDeathSound();
  2378. wait delay / 3;
  2379. reviveIcon.color = (1.0, 0.0, 0.0);
  2380.  
  2381. while ( reviveEnt.inUse )
  2382. wait ( 0.05 );
  2383.  
  2384. self playDeathSound();
  2385. wait delay / 3;
  2386.  
  2387. while ( reviveEnt.inUse )
  2388. wait ( 0.05 );
  2389.  
  2390. wait( 0.05 );
  2391. self thread lastStandBleedOut( isFinalStand );
  2392. return;
  2393. }
  2394.  
  2395. self thread lastStandKeepOverlay();
  2396. wait( delay );
  2397. self thread lastStandBleedout( isFinalStand );
  2398.  
  2399. }
  2400.  
  2401. maxHealthOverlay( maxHealth, refresh )
  2402. {
  2403. self endon( "stop_maxHealthOverlay" );
  2404. self endon( "revive" );
  2405. self endon( "death" );
  2406.  
  2407. for( ;; )
  2408. {
  2409. self.health -= 1;
  2410. self.maxHealth = maxHealth;
  2411. wait( .05 );
  2412. self.maxHealth = 50;
  2413. self.health += 1;
  2414.  
  2415. wait ( .50 );
  2416. }
  2417. }
  2418.  
  2419. lastStandBleedOut( reviveOnBleedOut, reviveEnt )
  2420. {
  2421. if ( reviveOnBleedOut )
  2422. {
  2423. self.lastStand = undefined;
  2424. self.inFinalStand = false;
  2425. self notify( "revive" );
  2426. self clearLowerMessage( "last_stand" );
  2427. maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer();
  2428.  
  2429. if( isDefined( reviveEnt ) )
  2430. reviveEnt Delete();
  2431. }
  2432. else
  2433. {
  2434. self.useLastStandParams = true;
  2435. self.beingRevived = false;
  2436. self _suicide();
  2437. }
  2438. }
  2439.  
  2440.  
  2441. lastStandAllowSuicide()
  2442. {
  2443. self endon( "death" );
  2444. self endon( "disconnect" );
  2445. self endon( "game_ended" );
  2446. self endon( "revive");
  2447.  
  2448. while ( 1 )
  2449. {
  2450. if ( self useButtonPressed() )
  2451. {
  2452. pressStartTime = gettime();
  2453. while ( self useButtonPressed() )
  2454. {
  2455. wait .05;
  2456. if ( gettime() - pressStartTime > 700 )
  2457. break;
  2458. }
  2459. if ( gettime() - pressStartTime > 700 )
  2460. break;
  2461. }
  2462. wait .05;
  2463. }
  2464.  
  2465. self thread lastStandBleedOut( false );
  2466. }
  2467.  
  2468. lastStandKeepOverlay()
  2469. {
  2470. level endon( "game_ended" );
  2471. self endon( "death" );
  2472. self endon( "disconnect" );
  2473. self endon( "revive" );
  2474.  
  2475. // keep the health overlay going by making code think the player is getting damaged
  2476. while ( !level.gameEnded )
  2477. {
  2478. self.health = 2;
  2479. wait .05;
  2480. self.health = 1;
  2481. wait .5;
  2482. }
  2483.  
  2484. self.health = self.maxhealth;
  2485. }
  2486.  
  2487.  
  2488. lastStandWaittillDeath()
  2489. {
  2490. self endon( "disconnect" );
  2491. self endon( "revive" );
  2492. level endon( "game_ended" );
  2493. self waittill( "death" );
  2494.  
  2495. self clearLowerMessage( "last_stand" );
  2496. self.lastStand = undefined;
  2497. }
  2498.  
  2499.  
  2500. mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc )
  2501. {
  2502. if ( sMeansOfDeath == "MOD_TRIGGER_HURT" )
  2503. return false;
  2504.  
  2505. if ( sMeansOfDeath != "MOD_PISTOL_BULLET" && sMeansOfDeath != "MOD_RIFLE_BULLET" && sMeansOfDeath != "MOD_FALLING" && sMeansOfDeath != "MOD_EXPLOSIVE_BULLET" )
  2506. return false;
  2507.  
  2508. if ( sMeansOfDeath == "MOD_IMPACT" && sWeapon == "throwingknife_mp" )
  2509. return false;
  2510.  
  2511. if ( sMeansOfDeath == "MOD_IMPACT" && ( sWeapon == "m79_mp" || isSubStr(sWeapon, "gl_") ) )
  2512. return false;
  2513.  
  2514. if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath ) )
  2515. return false;
  2516.  
  2517. if ( self isUsingRemote() )
  2518. return false;
  2519.  
  2520. return true;
  2521. }
  2522.  
  2523.  
  2524. ensureLastStandParamsValidity()
  2525. {
  2526. // attacker may have become undefined if the player that killed me has disconnected
  2527. if ( !isDefined( self.lastStandParams.attacker ) )
  2528. self.lastStandParams.attacker = self;
  2529. }
  2530.  
  2531. getHitLocHeight( sHitLoc )
  2532. {
  2533. switch( sHitLoc )
  2534. {
  2535. case "helmet":
  2536. case "head":
  2537. case "neck":
  2538. return 60;
  2539. case "torso_upper":
  2540. case "right_arm_upper":
  2541. case "left_arm_upper":
  2542. case "right_arm_lower":
  2543. case "left_arm_lower":
  2544. case "right_hand":
  2545. case "left_hand":
  2546. case "gun":
  2547. return 48;
  2548. case "torso_lower":
  2549. return 40;
  2550. case "right_leg_upper":
  2551. case "left_leg_upper":
  2552. return 32;
  2553. case "right_leg_lower":
  2554. case "left_leg_lower":
  2555. return 10;
  2556. case "right_foot":
  2557. case "left_foot":
  2558. return 5;
  2559. }
  2560. return 48;
  2561. }
  2562.  
  2563. delayStartRagdoll( ent, sHitLoc, vDir, sWeapon, eInflictor, sMeansOfDeath )
  2564. {
  2565. if ( isDefined( ent ) )
  2566. {
  2567. deathAnim = ent getCorpseAnim();
  2568. if ( animhasnotetrack( deathAnim, "ignore_ragdoll" ) )
  2569. return;
  2570. }
  2571.  
  2572. if ( isDefined( level.noRagdollEnts ) && level.noRagdollEnts.size )
  2573. {
  2574. foreach( noRag in level.noRagdollEnts )
  2575. {
  2576. if ( distanceSquared( ent.origin, noRag.origin ) < 65536 ) //256^2
  2577. return;
  2578. }
  2579. }
  2580.  
  2581. wait( 0.2 );
  2582.  
  2583. if ( !isDefined( ent ) )
  2584. return;
  2585.  
  2586. if ( ent isRagDoll() )
  2587. return;
  2588.  
  2589. deathAnim = ent getcorpseanim();
  2590.  
  2591. startFrac = 0.35;
  2592.  
  2593. if ( animhasnotetrack( deathAnim, "start_ragdoll" ) )
  2594. {
  2595. times = getnotetracktimes( deathAnim, "start_ragdoll" );
  2596. if ( isDefined( times ) )
  2597. startFrac = times[ 0 ];
  2598. }
  2599.  
  2600. waitTime = startFrac * getanimlength( deathAnim );
  2601. wait( waitTime );
  2602.  
  2603. if ( isDefined( ent ) )
  2604. {
  2605. ent startragdoll( 1 );
  2606. }
  2607. }
  2608.  
  2609.  
  2610. getMostKilledBy()
  2611. {
  2612. mostKilledBy = "";
  2613. killCount = 0;
  2614.  
  2615. killedByNames = getArrayKeys( self.killedBy );
  2616.  
  2617. for ( index = 0; index < killedByNames.size; index++ )
  2618. {
  2619. killedByName = killedByNames[ index ];
  2620. if ( self.killedBy[ killedByName ] <= killCount )
  2621. continue;
  2622.  
  2623. killCount = self.killedBy[ killedByName ];
  2624. mostKilleBy = killedByName;
  2625. }
  2626.  
  2627. return mostKilledBy;
  2628. }
  2629.  
  2630.  
  2631. getMostKilled()
  2632. {
  2633. mostKilled = "";
  2634. killCount = 0;
  2635.  
  2636. killedNames = getArrayKeys( self.killedPlayers );
  2637.  
  2638. for ( index = 0; index < killedNames.size; index++ )
  2639. {
  2640. killedName = killedNames[ index ];
  2641. if ( self.killedPlayers[ killedName ] <= killCount )
  2642. continue;
  2643.  
  2644. killCount = self.killedPlayers[ killedName ];
  2645. mostKilled = killedName;
  2646. }
  2647.  
  2648. return mostKilled;
  2649. }
  2650.  
  2651.  
  2652. damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker )
  2653. {
  2654. self thread maps\mp\gametypes\_weapons::onWeaponDamage( eInflictor, sWeapon, sMeansOfDeath, iDamage, eAttacker );
  2655. self PlayRumbleOnEntity( "damage_heavy" );
  2656. }
  2657.  
  2658.  
  2659. reviveSetup( owner )
  2660. {
  2661. team = owner.team;
  2662.  
  2663. self linkTo( owner, "tag_origin" );
  2664.  
  2665. self.owner = owner;
  2666. self.inUse = false;
  2667. self makeUsable();
  2668. self updateUsableByTeam( team );
  2669. self thread trackTeamChanges( team );
  2670.  
  2671. self thread reviveTriggerThink( team );
  2672.  
  2673. self thread deleteOnReviveOrDeathOrDisconnect();
  2674. }
  2675.  
  2676.  
  2677. deleteOnReviveOrDeathOrDisconnect()
  2678. {
  2679. self endon ( "death" );
  2680.  
  2681. self.owner waittill_any ( "death", "disconnect" );
  2682.  
  2683. self delete();
  2684. }
  2685.  
  2686.  
  2687. updateUsableByTeam( team )
  2688. {
  2689. foreach (player in level.players)
  2690. {
  2691. if ( team == player.team && player != self.owner )
  2692. self enablePlayerUse( player );
  2693. else
  2694. self disablePlayerUse( player );
  2695. }
  2696. }
  2697.  
  2698.  
  2699. trackTeamChanges( team )
  2700. {
  2701. self endon ( "death" );
  2702.  
  2703. while ( true )
  2704. {
  2705. level waittill ( "joined_team" );
  2706.  
  2707. self updateUsableByTeam( team );
  2708. }
  2709. }
  2710.  
  2711.  
  2712. trackLastStandChanges( team )
  2713. {
  2714. self endon ( "death" );
  2715.  
  2716. while ( true )
  2717. {
  2718. level waittill ( "player_last_stand" );
  2719.  
  2720. self updateUsableByTeam( team );
  2721. }
  2722. }
  2723.  
  2724.  
  2725. reviveTriggerThink( team )
  2726. {
  2727. self endon ( "death" );
  2728. level endon ( "game_ended" );
  2729.  
  2730. for ( ;; )
  2731. {
  2732. self waittill ( "trigger", player );
  2733. self.owner.beingRevived = true;
  2734.  
  2735. if ( isDefined(player.beingRevived) && player.beingRevived )
  2736. {
  2737. self.owner.beingRevived = false;
  2738. continue;
  2739. }
  2740.  
  2741. self makeUnUsable();
  2742. self.owner freezeControlsWrapper( true );
  2743.  
  2744. revived = self useHoldThink( player );
  2745. self.owner.beingRevived = false;
  2746.  
  2747. if ( !isAlive( self.owner ) )
  2748. {
  2749. self delete();
  2750. return;
  2751. }
  2752.  
  2753. self.owner freezeControlsWrapper( false );
  2754.  
  2755. if ( revived )
  2756. {
  2757. player thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "reviver", 200 );
  2758. player thread maps\mp\gametypes\_rank::giveRankXP( "reviver", 200 );
  2759.  
  2760. self.owner.lastStand = undefined;
  2761. self.owner clearLowerMessage( "last_stand" );
  2762.  
  2763. self.owner.moveSpeedScaler = 1;
  2764. if( self.owner _hasPerk( "specialty_lightweight" ) )
  2765. self.owner.moveSpeedScaler = lightWeightScalar();
  2766.  
  2767. self.owner.maxHealth = 100;
  2768.  
  2769. self.owner maps\mp\gametypes\_weapons::updateMoveSpeedScale();
  2770. self.owner maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer();
  2771.  
  2772. self.owner givePerk( "specialty_pistoldeath", false );
  2773. self.owner.beingRevived = false;
  2774.  
  2775. self delete();
  2776. return;
  2777. }
  2778.  
  2779. self makeUsable();
  2780. self updateUsableByTeam( team );
  2781. }
  2782. }
  2783.  
  2784.  
  2785.  
  2786. /*
  2787. =============
  2788. useHoldThink
  2789.  
  2790. Claims the use trigger for player and displays a use bar
  2791. Returns true if the player sucessfully fills the use bar
  2792. =============
  2793. */
  2794. useHoldThink( player )
  2795. {
  2796. reviveSpot = spawn( "script_origin", self.origin );
  2797. reviveSpot hide();
  2798. player playerLinkTo( reviveSpot );
  2799. player PlayerLinkedOffsetEnable();
  2800.  
  2801. player _disableWeapon();
  2802.  
  2803. self.curProgress = 0;
  2804. self.inUse = true;
  2805. self.useRate = 0;
  2806. self.useTime = 3000;
  2807.  
  2808. player thread personalUseBar( self );
  2809.  
  2810. result = useHoldThinkLoop( player );
  2811.  
  2812. if ( isDefined( player ) && isReallyAlive( player ) )
  2813. {
  2814. player Unlink();
  2815. player _enableWeapon();
  2816. }
  2817.  
  2818. if ( isDefined( result ) && result )
  2819. {
  2820. self.owner thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "revived", player );
  2821. self.owner.inlaststand = false;
  2822. return true;
  2823. }
  2824.  
  2825. self.inUse = false;
  2826. reviveSpot Delete();
  2827. return false;
  2828. }
  2829.  
  2830.  
  2831. personalUseBar( object )
  2832. {
  2833. useBar = self createPrimaryProgressBar();
  2834. useBarText = self createPrimaryProgressBarText();
  2835. useBarText setText( &"MPUI_REVIVING" );
  2836.  
  2837. objUseBar = object.owner createPrimaryProgressBar();
  2838. objUseBarText = object.owner createPrimaryProgressBarText();
  2839. objUseBarText setText( &"MPUI_BEING_REVIVED" );
  2840.  
  2841. lastRate = -1;
  2842. while ( isReallyAlive( self ) && isDefined( object ) && object.inUse && !level.gameEnded && isDefined( self ) )
  2843. {
  2844. if ( lastRate != object.useRate )
  2845. {
  2846. if( object.curProgress > object.useTime)
  2847. object.curProgress = object.useTime;
  2848.  
  2849. useBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate );
  2850. objUseBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate );
  2851.  
  2852. if ( !object.useRate )
  2853. {
  2854. useBar hideElem();
  2855. useBarText hideElem();
  2856.  
  2857. objUseBar hideElem();
  2858. objUseBarText hideElem();
  2859. }
  2860. else
  2861. {
  2862. useBar showElem();
  2863. useBarText showElem();
  2864.  
  2865. objUseBar showElem();
  2866. objUseBarText showElem();
  2867. }
  2868. }
  2869. lastRate = object.useRate;
  2870. wait ( 0.05 );
  2871. }
  2872.  
  2873. // when the players disconnect the hudElems are destroyed automatically
  2874. if ( isDefined( useBar ) )
  2875. useBar destroyElem();
  2876. if ( isDefined( useBarText ) )
  2877. useBarText destroyElem();
  2878.  
  2879. if ( isDefined( objUseBar ) )
  2880. objUseBar destroyElem();
  2881. if ( isDefined( objUseBarText ) )
  2882. objUseBarText destroyElem();
  2883. }
  2884.  
  2885.  
  2886. useHoldThinkLoop( player )
  2887. {
  2888. level endon ( "game_ended" );
  2889. self.owner endon( "death" );
  2890. self.owner endon( "disconnect" );
  2891.  
  2892. while( isReallyAlive( player ) && player useButtonPressed() && self.curProgress < self.useTime )
  2893. {
  2894. self.curProgress += (66 * self.useRate);
  2895. self.useRate = 1; /* * player.objectiveScaler;*/
  2896.  
  2897. if ( self.curProgress >= self.useTime )
  2898. {
  2899. self.inUse = false;
  2900.  
  2901. return isReallyAlive( player );
  2902. }
  2903.  
  2904. wait 0.05;
  2905. }
  2906.  
  2907. return false;
  2908. }
  2909.  
  2910.  
  2911. Callback_KillingBlow( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
  2912. {
  2913. if ( isDefined(self.lastDamageWasFromEnemy) && self.lastDamageWasFromEnemy && iDamage >= self.health && isDefined( self.combatHigh ) && self.combatHigh == "specialty_endgame" )
  2914. {
  2915. //self maps\mp\killstreaks\_killstreaks::setAdrenaline( 0 );
  2916. self givePerk( "specialty_endgame", false );
  2917. return false;
  2918. }
  2919.  
  2920. return true;
  2921. }
  2922.  
  2923.  
  2924. emitFallDamage( iDamage )
  2925. {
  2926. PhysicsExplosionSphere( self.origin, 64, 64, 1 );
  2927.  
  2928. // get the entities we landed on
  2929. damageEnts = [];
  2930. for ( testAngle = 0; testAngle < 360; testAngle += 30 )
  2931. {
  2932. xOffset = cos( testAngle ) * 16;
  2933. yOffset = sin( testAngle ) * 16;
  2934.  
  2935. traceData = bulletTrace( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), true, self );
  2936. //thread drawLine( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), 10.0 );
  2937.  
  2938. if ( isDefined( traceData["entity"] ) && isDefined( traceData["entity"].targetname ) && (traceData["entity"].targetname == "destructible_vehicle" || traceData["entity"].targetname == "destructible_toy") )
  2939. damageEnts[damageEnts.size] = traceData["entity"];
  2940. }
  2941.  
  2942. if ( damageEnts.size )
  2943. {
  2944. damageOwner = spawn( "script_origin", self.origin );
  2945. damageOwner hide();
  2946. damageOwner.type = "soft_landing";
  2947. damageOwner.destructibles = damageEnts;
  2948. radiusDamage( self.origin, 64, 100, 100, damageOwner );
  2949.  
  2950. wait ( 0.1 );
  2951. damageOwner delete();
  2952. }
  2953. }
  2954.  
  2955. drawLine( start, end, timeSlice )
  2956. {
  2957. drawTime = int(timeSlice * 15);
  2958. for( time = 0; time < drawTime; time++ )
  2959. {
  2960. line( start, end, (1,0,0),false, 1 );
  2961. wait ( 0.05 );
  2962. }
  2963. }
  2964.  
  2965. isFlankKill( victim, attacker )
  2966. {
  2967. victimForward = anglestoforward( victim.angles );
  2968. victimForward = ( victimForward[0], victimForward[1], 0 );
  2969. victimForward = VectorNormalize( victimForward );
  2970.  
  2971. attackDirection = victim.origin - attacker.origin;
  2972. attackDirection = ( attackDirection[0], attackDirection[1], 0 );
  2973. attackDirection = VectorNormalize( attackDirection );
  2974.  
  2975. dotProduct = VectorDot( victimForward, attackDirection );
  2976. if ( dotProduct > 0 ) // 0 = cos( 90 ), 180 degree arc total
  2977. return true;
  2978. else
  2979. return false;
  2980. }
  2981.  
  2982. _obituary( victim, attacker, sWeapon, sMeansOfDeath )
  2983. {
  2984. victimTeam = victim.team;
  2985.  
  2986. foreach ( player in level.players )
  2987. {
  2988. playerTeam = player.team;
  2989. if ( playerTeam == "spectator" )
  2990. player iPrintLn( &"MP_OBITUARY_NEUTRAL", attacker.name, victim.name );
  2991. else if ( playerTeam == victimTeam )
  2992. player iPrintLn( &"MP_OBITUARY_ENEMY", attacker.name, victim.name );
  2993. else
  2994. player iPrintLn( &"MP_OBITUARY_FRIENDLY", attacker.name, victim.name );
  2995. }
  2996. }
  2997.  
  2998.  
  2999. logPrintPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc )
  3000. {
  3001. // create a lot of redundant data for the log print
  3002. lpselfnum = self getEntityNumber();
  3003. lpselfname = self.name;
  3004. lpselfteam = self.team;
  3005. lpselfguid = self.guid;
  3006.  
  3007. if ( isPlayer( attacker ) )
  3008. {
  3009. lpattackGuid = attacker.guid;
  3010. lpattackname = attacker.name;
  3011. lpattackerteam = attacker.team;
  3012. lpattacknum = attacker getEntityNumber();
  3013. attackerString = attacker getXuid() + "(" + lpattackname + ")";
  3014. }
  3015. else
  3016. {
  3017. lpattackGuid = "";
  3018. lpattackname = "";
  3019. lpattackerteam = "world";
  3020. lpattacknum = -1;
  3021. attackerString = "none";
  3022. }
  3023.  
  3024. logPrint( "K;" + lpselfguid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackguid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );
  3025. }
  3026.  
  3027.  
  3028. destroyOnReviveEntDeath( reviveEnt )
  3029. {
  3030. reviveEnt waittill ( "death" );
  3031.  
  3032. self destroy();
  3033. }
  3034.  
  3035.  
  3036. gamemodeModifyPlayerDamage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc )
  3037. {
  3038. if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && isAlive( eAttacker ) )
  3039. {
  3040. if ( level.matchRules_damageMultiplier )
  3041. iDamage *= level.matchRules_damageMultiplier;
  3042.  
  3043. if ( level.matchRules_vampirism )
  3044. eAttacker.health = int( min( float( eAttacker.maxHealth ), float( eAttacker.health + 20 ) ) );
  3045. }
  3046.  
  3047. return iDamage;
  3048. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement