Advertisement
Guest User

Untitled

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