Advertisement
Guest User

Untitled

a guest
Sep 21st, 2010
178
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 67.72 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.  
  1056. if ( sMeansOfDeath == "mod_melee")
  1057. iDamage = 0;
  1058.  
  1059. if ( !isReallyAlive( victim ) )
  1060. return;
  1061.  
  1062. if ( isDefined( eAttacker ) && eAttacker.classname == "script_origin" && isDefined( eAttacker.type ) && eAttacker.type == "soft_landing" )
  1063. return;
  1064.  
  1065. if ( isDefined( level.hostMigrationTimer ) )
  1066. return;
  1067.  
  1068. if ( sMeansOfDeath == "MOD_FALLING" )
  1069. victim thread emitFallDamage( iDamage );
  1070.  
  1071. if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && iDamage != 1 )
  1072. {
  1073. iDamage *= getDvarFloat( "scr_explBulletMod" );
  1074. iDamage = int( iDamage );
  1075. }
  1076.  
  1077. if ( isDefined( eAttacker ) && eAttacker.classname == "worldspawn" )
  1078. eAttacker = undefined;
  1079.  
  1080. if ( isDefined( eAttacker ) && isDefined( eAttacker.gunner ) )
  1081. eAttacker = eAttacker.gunner;
  1082.  
  1083. attackerIsNPC = isDefined( eAttacker ) && !isDefined( eAttacker.gunner ) && (eAttacker.classname == "script_vehicle" || eAttacker.classname == "misc_turret" || eAttacker.classname == "script_model");
  1084. attackerIsHittingTeammate = level.teamBased && isDefined( eAttacker ) && ( victim != eAttacker ) && isDefined( eAttacker.team ) && ( victim.pers[ "team" ] == eAttacker.team );
  1085.  
  1086. stunFraction = 0.0;
  1087.  
  1088. if ( iDFlags & level.iDFLAGS_STUN )
  1089. {
  1090. stunFraction = 0.0;
  1091. //victim StunPlayer( 1.0 );
  1092. iDamage = 0.0;
  1093. }
  1094. else if ( sHitLoc == "shield" )
  1095. {
  1096. if ( attackerIsHittingTeammate && level.friendlyfire == 0 )
  1097. return;
  1098.  
  1099. if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" && !attackerIsHittingTeammate )
  1100. {
  1101. if ( isPlayer( eAttacker ) )
  1102. {
  1103. eAttacker.lastAttackedShieldPlayer = victim;
  1104. eAttacker.lastAttackedShieldTime = getTime();
  1105. }
  1106. victim notify ( "shield_blocked" );
  1107.  
  1108. // fix turret + shield challenge exploits
  1109. if ( sWeapon == "turret_minigun_mp" )
  1110. shieldDamage = 25;
  1111. else
  1112. shieldDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
  1113.  
  1114. victim.shieldDamage += shieldDamage;
  1115.  
  1116. // fix turret + shield challenge exploits
  1117. if ( sWeapon != "turret_minigun_mp" || cointoss() )
  1118. victim.shieldBulletHits++;
  1119.  
  1120. if ( victim.shieldBulletHits >= level.riotShieldXPBullets )
  1121. {
  1122. if ( self.recentShieldXP > 4 )
  1123. xpVal = int( 50 / self.recentShieldXP );
  1124. else
  1125. xpVal = 50;
  1126.  
  1127. printLn( xpVal );
  1128.  
  1129. victim thread maps\mp\gametypes\_rank::giveRankXP( "shield_damage", xpVal );
  1130. victim thread giveRecentShieldXP();
  1131.  
  1132. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_damage", victim.shieldDamage );
  1133.  
  1134. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_bullet_hits", victim.shieldBulletHits );
  1135.  
  1136. victim.shieldDamage = 0;
  1137. victim.shieldBulletHits = 0;
  1138. }
  1139. }
  1140.  
  1141. if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT )
  1142. {
  1143. if ( !attackerIsHittingTeammate )
  1144. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 );
  1145.  
  1146. sHitLoc = "none"; // code ignores any damage to a "shield" bodypart.
  1147. if ( !(iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_IMPACT_HUGE) )
  1148. iDamage *= 0.0;
  1149. }
  1150. else if ( iDFlags & level.iDFLAGS_SHIELD_EXPLOSIVE_SPLASH )
  1151. {
  1152. if ( isDefined( eInflictor ) && isDefined( eInflictor.stuckEnemyEntity ) && eInflictor.stuckEnemyEntity == victim ) //does enough damage to shield carrier to ensure death
  1153. iDamage = 101;
  1154.  
  1155. victim thread maps\mp\gametypes\_missions::genericChallenge( "shield_explosive_hits", 1 );
  1156. sHitLoc = "none"; // code ignores any damage to a "shield" bodypart.
  1157. }
  1158. else
  1159. {
  1160. return;
  1161. }
  1162. }
  1163. else if ( (smeansofdeath == "MOD_MELEE") && IsSubStr( sweapon, "riotshield" ) )
  1164. {
  1165. if ( !(attackerIsHittingTeammate && (level.friendlyfire == 0)) )
  1166. {
  1167. stunFraction = 0.0;
  1168. victim StunPlayer( 0.0 );
  1169. }
  1170. }
  1171.  
  1172. if ( !attackerIsHittingTeammate )
  1173. iDamage = maps\mp\perks\_perks::cac_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc );
  1174.  
  1175. if ( !iDamage )
  1176. return false;
  1177.  
  1178. victim.iDFlags = iDFlags;
  1179. victim.iDFlagsTime = getTime();
  1180.  
  1181. if ( game[ "state" ] == "postgame" )
  1182. return;
  1183. if ( victim.sessionteam == "spectator" )
  1184. return;
  1185. if ( isDefined( victim.canDoCombat ) && !victim.canDoCombat )
  1186. return;
  1187. if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat )
  1188. return;
  1189.  
  1190. // handle vehicles/turrets and friendly fire
  1191. if ( attackerIsNPC && attackerIsHittingTeammate )
  1192. {
  1193. if ( sMeansOfDeath == "MOD_CRUSH" )
  1194. {
  1195. victim _suicide();
  1196. return;
  1197. }
  1198.  
  1199. if ( !level.friendlyfire )
  1200. return;
  1201. }
  1202.  
  1203. prof_begin( "PlayerDamage flags/tweaks" );
  1204.  
  1205. // Don't do knockback if the damage direction was not specified
  1206. if ( !isDefined( vDir ) )
  1207. iDFlags |= level.iDFLAGS_NO_KNOCKBACK;
  1208.  
  1209. friendly = false;
  1210.  
  1211. if ( ( victim.health == victim.maxhealth && ( !isDefined( victim.lastStand ) || !victim.lastStand ) ) || !isDefined( victim.attackers ) && !isDefined( victim.lastStand ) )
  1212. {
  1213. victim.attackers = [];
  1214. victim.attackerData = [];
  1215. }
  1216.  
  1217. if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath, eAttacker ) )
  1218. sMeansOfDeath = "MOD_HEAD_SHOT";
  1219.  
  1220. if ( maps\mp\gametypes\_tweakables::getTweakableValue( "game", "onlyheadshots" ) )
  1221. {
  1222. if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" || sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" )
  1223. return;
  1224. else if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
  1225. iDamage = 150;
  1226. }
  1227.  
  1228. // explosive barrel/car detection
  1229. if ( sWeapon == "none" && isDefined( eInflictor ) )
  1230. {
  1231. if ( isDefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
  1232. sWeapon = "destructible_car";
  1233. }
  1234.  
  1235. prof_end( "PlayerDamage flags/tweaks" );
  1236.  
  1237. // check for completely getting out of the damage
  1238. if ( !(iDFlags & level.iDFLAGS_NO_PROTECTION) )
  1239. {
  1240. // items you own don't damage you in FFA
  1241. if ( !level.teamBased && attackerIsNPC && isDefined( eAttacker.owner ) && eAttacker.owner == victim )
  1242. {
  1243. prof_end( "PlayerDamage player" );
  1244.  
  1245. if ( sMeansOfDeath == "MOD_CRUSH" )
  1246. victim _suicide();
  1247.  
  1248. return;
  1249. }
  1250.  
  1251. if ( ( isSubStr( sMeansOfDeath, "MOD_GRENADE" ) || isSubStr( sMeansOfDeath, "MOD_EXPLOSIVE" ) || isSubStr( sMeansOfDeath, "MOD_PROJECTILE" ) ) && isDefined( eInflictor ) && isDefined( eAttacker ) )
  1252. {
  1253. // protect players from spawnkill grenades
  1254. if ( eInflictor.classname == "grenade" && ( victim.lastSpawnTime + 3500 ) > getTime() && isDefined( victim.lastSpawnPoint ) && distance( eInflictor.origin, victim.lastSpawnPoint.origin ) < 250 )
  1255. {
  1256. prof_end( "PlayerDamage player" );
  1257. return;
  1258. }
  1259.  
  1260. victim.explosiveInfo = [];
  1261. victim.explosiveInfo[ "damageTime" ] = getTime();
  1262. victim.explosiveInfo[ "damageId" ] = eInflictor getEntityNumber();
  1263. victim.explosiveInfo[ "returnToSender" ] = false;
  1264. victim.explosiveInfo[ "counterKill" ] = false;
  1265. victim.explosiveInfo[ "chainKill" ] = false;
  1266. victim.explosiveInfo[ "cookedKill" ] = false;
  1267. victim.explosiveInfo[ "throwbackKill" ] = false;
  1268. victim.explosiveInfo[ "suicideGrenadeKill" ] = false;
  1269. victim.explosiveInfo[ "weapon" ] = sWeapon;
  1270.  
  1271. isFrag = isSubStr( sWeapon, "frag_" );
  1272.  
  1273. if ( eAttacker != victim )
  1274. {
  1275. if ( ( isSubStr( sWeapon, "c4_" ) || isSubStr( sWeapon, "claymore_" ) ) && isDefined( eAttacker ) && isDefined( eInflictor.owner ) )
  1276. {
  1277. victim.explosiveInfo[ "returnToSender" ] = ( eInflictor.owner == victim );
  1278. victim.explosiveInfo[ "counterKill" ] = isDefined( eInflictor.wasDamaged );
  1279. victim.explosiveInfo[ "chainKill" ] = isDefined( eInflictor.wasChained );
  1280. victim.explosiveInfo[ "bulletPenetrationKill" ] = isDefined( eInflictor.wasDamagedFromBulletPenetration );
  1281. victim.explosiveInfo[ "cookedKill" ] = false;
  1282. }
  1283.  
  1284. if ( isDefined( eAttacker.lastGrenadeSuicideTime ) && eAttacker.lastGrenadeSuicideTime >= gettime() - 50 && isFrag )
  1285. victim.explosiveInfo[ "suicideGrenadeKill" ] = true;
  1286. }
  1287.  
  1288. if ( isFrag )
  1289. {
  1290. victim.explosiveInfo[ "cookedKill" ] = isDefined( eInflictor.isCooked );
  1291. victim.explosiveInfo[ "throwbackKill" ] = isDefined( eInflictor.threwBack );
  1292. }
  1293.  
  1294. victim.explosiveInfo[ "stickKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "enemy";
  1295. victim.explosiveInfo[ "stickFriendlyKill" ] = isDefined( eInflictor.isStuck ) && eInflictor.isStuck == "friendly";
  1296. }
  1297.  
  1298. if ( isPlayer( eAttacker ) )
  1299. eAttacker.pers[ "participation" ]++ ;
  1300.  
  1301. prevHealthRatio = victim.health / victim.maxhealth;
  1302.  
  1303. if ( attackerIsHittingTeammate )
  1304. {
  1305. if ( !matchMakingGame() && isPlayer(eAttacker) )
  1306. eAttacker incPlayerStat( "mostff", 1 );
  1307.  
  1308. prof_begin( "PlayerDamage player" );// profs automatically end when the function returns
  1309. if ( level.friendlyfire == 0 || ( !isPlayer(eAttacker) && level.friendlyfire != 1 ) )// no one takes damage
  1310. {
  1311. if ( sWeapon == "artillery_mp" || sWeapon == "stealth_bomb_mp" )
  1312. victim damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker );
  1313. return;
  1314. }
  1315. else if ( level.friendlyfire == 1 )// the friendly takes damage
  1316. {
  1317. if ( iDamage < 1 )
  1318. iDamage = 1;
  1319.  
  1320. victim.lastDamageWasFromEnemy = false;
  1321.  
  1322. victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1323. }
  1324. else if ( ( level.friendlyfire == 2 ) && isReallyAlive( eAttacker ) )// only the attacker takes damage
  1325. {
  1326. iDamage = int( iDamage * .5 );
  1327. if ( iDamage < 1 )
  1328. iDamage = 1;
  1329.  
  1330. eAttacker.lastDamageWasFromEnemy = false;
  1331.  
  1332. eAttacker.friendlydamage = true;
  1333. eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1334. eAttacker.friendlydamage = undefined;
  1335. }
  1336. else if ( level.friendlyfire == 3 && isReallyAlive( eAttacker ) )// both friendly and attacker take damage
  1337. {
  1338. iDamage = int( iDamage * .5 );
  1339. if ( iDamage < 1 )
  1340. iDamage = 1;
  1341.  
  1342. victim.lastDamageWasFromEnemy = false;
  1343. eAttacker.lastDamageWasFromEnemy = false;
  1344.  
  1345. victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1346. if ( isReallyAlive( eAttacker ) )// may have died due to friendly fire punishment
  1347. {
  1348. eAttacker.friendlydamage = true;
  1349. eAttacker finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1350. eAttacker.friendlydamage = undefined;
  1351. }
  1352. }
  1353.  
  1354. friendly = true;
  1355.  
  1356. }
  1357. else// not hitting teammate
  1358. {
  1359. prof_begin( "PlayerDamage world" );
  1360.  
  1361. if ( iDamage < 1 )
  1362. iDamage = 1;
  1363.  
  1364. if ( isDefined( eAttacker ) && isPlayer( eAttacker ) )
  1365. addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath );
  1366.  
  1367. if ( sMeansOfDeath == "MOD_EXPLOSIVE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" && iDamage < victim.health )
  1368. victim notify( "survived_explosion" );
  1369.  
  1370. if ( isdefined( eAttacker ) )
  1371. level.lastLegitimateAttacker = eAttacker;
  1372.  
  1373. if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) )
  1374. eAttacker thread maps\mp\gametypes\_weapons::checkHit( sWeapon, victim );
  1375.  
  1376. if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isDefined( sWeapon ) && eAttacker != victim )
  1377. {
  1378. eAttacker thread maps\mp\_events::damagedPlayer( self, iDamage, sWeapon );
  1379. victim.attackerPosition = eAttacker.origin;
  1380. }
  1381. else
  1382. {
  1383. victim.attackerPosition = undefined;
  1384. }
  1385.  
  1386. if ( issubstr( sMeansOfDeath, "MOD_GRENADE" ) && isDefined( eInflictor.isCooked ) )
  1387. victim.wasCooked = getTime();
  1388. else
  1389. victim.wasCooked = undefined;
  1390.  
  1391. victim.lastDamageWasFromEnemy = ( isDefined( eAttacker ) && ( eAttacker != victim ) );
  1392.  
  1393. if ( victim.lastDamageWasFromEnemy )
  1394. eAttacker.damagedPlayers[ victim.guid ] = getTime();
  1395.  
  1396. victim finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1397.  
  1398. if ( isDefined( level.ac130player ) && isDefined( eAttacker ) && ( level.ac130player == eAttacker ) )
  1399. level notify( "ai_pain", victim );
  1400.  
  1401. victim thread maps\mp\gametypes\_missions::playerDamaged( eInflictor, eAttacker, iDamage, sMeansOfDeath, sWeapon, sHitLoc );
  1402.  
  1403. prof_end( "PlayerDamage world" );
  1404.  
  1405. }
  1406.  
  1407. if ( attackerIsNPC && isDefined( eAttacker.gunner ) )
  1408. damager = eAttacker.gunner;
  1409. else
  1410. damager = eAttacker;
  1411.  
  1412. if ( isDefined( damager) && damager != victim && iDamage > 0 )
  1413. {
  1414. if ( iDFlags & level.iDFLAGS_STUN )
  1415. typeHit = "stun";
  1416. else if ( victim hasPerk( "specialty_armorvest", true ) || (isExplosiveDamage( sMeansOfDeath ) && victim _hasPerk( "_specialty_blastshield" )) )
  1417. typeHit = "hitBodyArmor";
  1418. else if ( victim _hasPerk( "specialty_combathigh") )
  1419. typeHit = "hitEndGame";
  1420. else
  1421. typeHit = "standard";
  1422.  
  1423. damager thread maps\mp\gametypes\_damagefeedback::updateDamageFeedback( typeHit );
  1424. }
  1425.  
  1426. victim.hasDoneCombat = true;
  1427. }
  1428.  
  1429. if ( isdefined( eAttacker ) && ( eAttacker != victim ) && !friendly )
  1430. level.useStartSpawns = false;
  1431.  
  1432.  
  1433. //=================
  1434. // Damage Logging
  1435. //=================
  1436.  
  1437. prof_begin( "PlayerDamage log" );
  1438.  
  1439. // why getEntityNumber() for victim and .clientid for attacker?
  1440. if ( getDvarInt( "g_debugDamage" ) )
  1441. println( "client:" + victim getEntityNumber() + " health:" + victim.health + " attacker:" + eAttacker.clientid + " inflictor is player:" + isPlayer( eInflictor ) + " damage:" + iDamage + " hitLoc:" + sHitLoc );
  1442.  
  1443. if ( victim.sessionstate != "dead" )
  1444. {
  1445. lpselfnum = victim getEntityNumber();
  1446. lpselfname = victim.name;
  1447. lpselfteam = victim.pers[ "team" ];
  1448. lpselfGuid = victim.guid;
  1449. lpattackerteam = "";
  1450.  
  1451. if ( isPlayer( eAttacker ) )
  1452. {
  1453. lpattacknum = eAttacker getEntityNumber();
  1454. lpattackGuid = eAttacker.guid;
  1455. lpattackname = eAttacker.name;
  1456. lpattackerteam = eAttacker.pers[ "team" ];
  1457. }
  1458. else
  1459. {
  1460. lpattacknum = -1;
  1461. lpattackGuid = "";
  1462. lpattackname = "";
  1463. lpattackerteam = "world";
  1464. }
  1465.  
  1466. logPrint( "D;" + lpselfGuid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );
  1467. }
  1468.  
  1469. HitlocDebug( eAttacker, victim, iDamage, sHitLoc, iDFlags );
  1470.  
  1471. /*if( isDefined( eAttacker ) && eAttacker != victim )
  1472. {
  1473. if ( isPlayer( eAttacker ) )
  1474. eAttacker incPlayerStat( "damagedone", iDamage );
  1475.  
  1476. victim incPlayerStat( "damagetaken", iDamage );
  1477. }*/
  1478.  
  1479. prof_end( "PlayerDamage log" );
  1480. }
  1481.  
  1482.  
  1483. addAttacker( victim, eAttacker, eInflictor, sWeapon, iDamage, vPoint, vDir, sHitLoc, psOffsetTime, sMeansOfDeath )
  1484. {
  1485. if ( !isDefined( victim.attackerData ) )
  1486. victim.attackerData = [];
  1487.  
  1488. if ( !isDefined( victim.attackerData[ eAttacker.guid ] ) )
  1489. {
  1490. victim.attackers[ eAttacker.guid ] = eAttacker;
  1491. // we keep an array of attackers by their client ID so we can easily tell
  1492. // if they're already one of the existing attackers in the above if().
  1493. // we store in this array data that is useful for other things, like challenges
  1494. victim.attackerData[ eAttacker.guid ] = SpawnStruct();
  1495. victim.attackerData[ eAttacker.guid ].damage = 0;
  1496. victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker;
  1497. victim.attackerData[ eAttacker.guid ].firstTimeDamaged = getTime();
  1498. }
  1499. if ( maps\mp\gametypes\_weapons::isPrimaryWeapon( sWeapon ) && ! maps\mp\gametypes\_weapons::isSideArm( sWeapon ) )
  1500. victim.attackerData[ eAttacker.guid ].isPrimary = true;
  1501.  
  1502. victim.attackerData[ eAttacker.guid ].damage += iDamage;
  1503. victim.attackerData[ eAttacker.guid ].weapon = sWeapon;
  1504. victim.attackerData[ eAttacker.guid ].vPoint = vPoint;
  1505. victim.attackerData[ eAttacker.guid ].vDir = vDir;
  1506. victim.attackerData[ eAttacker.guid ].sHitLoc = sHitLoc;
  1507. victim.attackerData[ eAttacker.guid ].psOffsetTime = psOffsetTime;
  1508. victim.attackerData[ eAttacker.guid ].sMeansOfDeath = sMeansOfDeath;
  1509. victim.attackerData[ eAttacker.guid ].attackerEnt = eAttacker;
  1510. victim.attackerData[ eAttacker.guid ].lasttimeDamaged = getTime();
  1511.  
  1512. if ( isDefined( eInflictor ) && !isPlayer( eInflictor ) && isDefined( eInflictor.primaryWeapon ) )
  1513. victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eInflictor.primaryWeapon;
  1514. else if ( isDefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker getCurrentPrimaryWeapon() != "none" )
  1515. victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = eAttacker getCurrentPrimaryWeapon();
  1516. else
  1517. victim.attackerData[ eAttacker.guid ].sPrimaryWeapon = undefined;
  1518. }
  1519.  
  1520. resetAttackerList()
  1521. {
  1522. self endon( "disconnect" );
  1523. self endon( "death" );
  1524. level endon( "game_ended" );
  1525.  
  1526. //wait is to offset premature calling in _healthOverlay
  1527. wait( 1.75 );
  1528. self.attackers = [];
  1529. self.attackerData = [];
  1530. }
  1531.  
  1532.  
  1533. Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
  1534. {
  1535. Callback_PlayerDamage_internal( eInflictor, eAttacker, self, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime );
  1536. }
  1537.  
  1538.  
  1539. finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction )
  1540. {
  1541. if ( (self isUsingRemote() ) && (iDamage >= self.health) && !(iDFlags & level.iDFLAGS_STUN) )
  1542. {
  1543. if ( !isDefined( vDir ) )
  1544. vDir = ( 0,0,0 );
  1545.  
  1546. if ( !isDefined( eAttacker ) && !isDefined( eInflictor ) )
  1547. {
  1548. eAttacker = self;
  1549. eInflictor = eAttacker;
  1550. }
  1551.  
  1552. assert( isDefined( eAttacker ) );
  1553. assert( isDefined( eInflictor ) );
  1554.  
  1555. PlayerKilled_internal( eInflictor, eAttacker, self, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, 0, true );
  1556. }
  1557. else
  1558. {
  1559. if ( !self Callback_KillingBlow( eInflictor, eAttacker, iDamage - (iDamage * stunFraction), iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime ) )
  1560. return;
  1561.  
  1562. self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime, stunFraction );
  1563. }
  1564.  
  1565. if ( sMeansOfDeath == "MOD_EXPLOSIVE_BULLET" )
  1566. self shellShock( "damage_mp", getDvarFloat( "scr_csmode" ) );
  1567.  
  1568. self damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker );
  1569. }
  1570.  
  1571.  
  1572. Callback_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
  1573. {
  1574.  
  1575. lastStandParams = spawnStruct();
  1576. lastStandParams.eInflictor = eInflictor;
  1577. lastStandParams.attacker = attacker;
  1578. lastStandParams.iDamage = iDamage;
  1579. lastStandParams.attackerPosition = attacker.origin;
  1580. if ( attacker == self )
  1581. lastStandParams.sMeansOfDeath = "MOD_SUICIDE";
  1582. else
  1583. lastStandParams.sMeansOfDeath = sMeansOfDeath;
  1584.  
  1585. lastStandParams.sWeapon = sWeapon;
  1586. if ( isDefined( attacker ) && isPlayer( attacker ) && attacker getCurrentPrimaryWeapon() != "none" )
  1587. lastStandParams.sPrimaryWeapon = attacker getCurrentPrimaryWeapon();
  1588. else
  1589. lastStandParams.sPrimaryWeapon = undefined;
  1590. lastStandParams.vDir = vDir;
  1591. lastStandParams.sHitLoc = sHitLoc;
  1592. lastStandParams.lastStandStartTime = getTime();
  1593.  
  1594. mayDoLastStand = mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc );
  1595.  
  1596. //if ( mayDoLastStand )
  1597. // mayDoLastStand = !self checkForceBleedOut();
  1598.  
  1599. if ( isDefined( self.endGame ) )
  1600. mayDoLastStand = false;
  1601.  
  1602. if ( level.teamBased && isDefined( attacker.team ) && attacker.team == self.team )
  1603. mayDoLastStand = false;
  1604.  
  1605. /#
  1606. if ( getdvar( "scr_forcelaststand" ) == "1" )
  1607. mayDoLastStand = true;
  1608. #/
  1609.  
  1610. if ( !mayDoLastStand )
  1611. {
  1612. self.lastStandParams = lastStandParams;
  1613. self.useLastStandParams = true;
  1614. self _suicide();
  1615. return;
  1616. }
  1617.  
  1618. self.inLastStand = true;
  1619.  
  1620. notifyData = spawnStruct();
  1621. if ( self _hasPerk( "specialty_finalstand" ) )
  1622. {
  1623. notifyData.titleText = game[ "strings" ][ "final_stand" ];
  1624. notifyData.iconName = "specialty_finalstand";
  1625. }
  1626. else
  1627. {
  1628. notifyData.titleText = game[ "strings" ][ "last_stand" ];
  1629. notifyData.iconName = "specialty_pistoldeath";
  1630. }
  1631. notifyData.glowColor = ( 1, 0, 0 );
  1632. notifyData.sound = "mp_last_stand";
  1633. notifyData.duration = 2.0;
  1634.  
  1635. self.health = 1;
  1636.  
  1637. self thread maps\mp\gametypes\_hud_message::notifyMessage( notifyData );
  1638.  
  1639. grenadeTypePrimary = "frag_grenade_mp";
  1640.  
  1641. if ( isDefined( level.ac130player ) && isDefined( attacker ) && level.ac130player == attacker )
  1642. level notify( "ai_crawling", self );
  1643.  
  1644. if ( self _hasPerk( "specialty_finalstand" ) )
  1645. {
  1646. self.lastStandParams = lastStandParams;
  1647. self.inFinalStand = true;
  1648.  
  1649. weaponList = self GetWeaponsListExclusives();
  1650. foreach ( weapon in weaponList )
  1651. self takeWeapon( weapon );
  1652.  
  1653. self _disableUsability();
  1654.  
  1655. self thread enableLastStandWeapons();
  1656. self thread lastStandTimer( 20, true );
  1657. }
  1658. /*
  1659. else if ( self _hasPerk( "specialty_c4death" ) )
  1660. {
  1661. self.lastStandParams = lastStandParams;
  1662.  
  1663. self takeAllWeapons();
  1664. self giveWeapon( "c4Death_mp", 0, false );
  1665. self switchToWeapon( "c4Death_mp" );
  1666. self _disableUsability();
  1667. self.inC4Death = true;
  1668.  
  1669. //self thread dieAfterTime( 7 );
  1670. self thread lastStandTimer( 10, false );
  1671. self thread detonateOnUse();
  1672. //self thread detonateOnDeath();
  1673. }
  1674. */
  1675. else if ( level.dieHardMode )
  1676. {
  1677. self.lastStandParams = lastStandParams;
  1678. self thread enableLastStandWeapons();
  1679. self thread lastStandTimer( 20, false );
  1680. self _disableUsability();
  1681. }
  1682. else // normal last stand
  1683. {
  1684. self.lastStandParams = lastStandParams;
  1685.  
  1686. pistolWeapon = undefined;
  1687.  
  1688. weaponsList = self GetWeaponsListPrimaries();
  1689. foreach ( weapon in weaponsList )
  1690. {
  1691. if ( maps\mp\gametypes\_weapons::isSideArm( weapon ) )
  1692. pistolWeapon = weapon;
  1693. }
  1694.  
  1695. if ( !isDefined( pistolWeapon ) )
  1696. {
  1697. pistolWeapon = "beretta_mp";
  1698. self _giveWeapon( pistolWeapon );
  1699. }
  1700.  
  1701. self giveMaxAmmo( pistolWeapon );
  1702. self DisableWeaponSwitch();
  1703. self _disableUsability();
  1704.  
  1705. if ( !self _hasPerk("specialty_laststandoffhand") )
  1706. self DisableOffhandWeapons();
  1707.  
  1708. self switchToWeapon( pistolWeapon );
  1709.  
  1710. self thread lastStandTimer( 10, false );
  1711. }
  1712. }
  1713.  
  1714. dieAfterTime( time )
  1715. {
  1716. self endon( "death" );
  1717. self endon( "disconnect" );
  1718. self endon( "joined_team" );
  1719. level endon( "game_ended" );
  1720.  
  1721. wait ( time );
  1722. self.useLastStandParams = true;
  1723. self _suicide();
  1724. }
  1725.  
  1726. detonateOnUse()
  1727. {
  1728. self endon( "death" );
  1729. self endon( "disconnect" );
  1730. self endon( "joined_team" );
  1731. level endon( "game_ended" );
  1732.  
  1733. self waittill( "detonate" );
  1734. self.useLastStandParams = true;
  1735. self c4DeathDetonate();
  1736. }
  1737.  
  1738. detonateOnDeath()
  1739. {
  1740. self endon( "detonate" );
  1741. self endon( "disconnect" );
  1742. self endon( "joined_team" );
  1743. level endon( "game_ended" );
  1744.  
  1745. self waittill( "death" );
  1746. self c4DeathDetonate();
  1747. }
  1748.  
  1749. c4DeathDetonate()
  1750. {
  1751. self playSound( "detpack_explo_default" );
  1752. self.c4DeathEffect = playFX( level.c4Death, self.origin );
  1753. RadiusDamage( self.origin, 400, 100, 100, self );
  1754.  
  1755. if ( isAlive( self ) )
  1756. self _suicide();
  1757. }
  1758.  
  1759. enableLastStandWeapons()
  1760. {
  1761. self endon( "death" );
  1762. self endon( "disconnect" );
  1763. level endon( "game_ended" );
  1764.  
  1765. self freezeControlsWrapper( true );
  1766. wait .30;
  1767.  
  1768. self freezeControlsWrapper( false );
  1769. }
  1770.  
  1771. lastStandTimer( delay, isFinalStand )
  1772. {
  1773. self endon( "death" );
  1774. self endon( "disconnect" );
  1775. self endon( "revive");
  1776. level endon( "game_ended" );
  1777.  
  1778. level notify ( "player_last_stand" );
  1779.  
  1780. self thread lastStandWaittillDeath();
  1781.  
  1782. self.lastStand = true;
  1783.  
  1784. if ( !isFinalStand && !level.dieHardMode && ( !isDefined( self.inC4Death ) || !self.inC4Death ) )
  1785. {
  1786. self thread lastStandAllowSuicide();
  1787. self setLowerMessage( "last_stand", &"PLATFORM_COWARDS_WAY_OUT" );
  1788. self thread lastStandKeepOverlay();
  1789. }
  1790.  
  1791. if ( level.dieHardMode == 1 && level.dieHardMode != 2 )
  1792. {
  1793. reviveEnt = spawn( "script_model", self.origin );
  1794. reviveEnt setModel( "tag_origin" );
  1795. reviveEnt setCursorHint( "HINT_NOICON" );
  1796. reviveEnt setHintString( &"PLATFORM_REVIVE" );
  1797.  
  1798. reviveEnt reviveSetup( self );
  1799. reviveEnt endon ( "death" );
  1800.  
  1801. reviveIcon = newTeamHudElem( self.team );
  1802. reviveIcon setShader( "waypoint_revive", 8, 8 );
  1803. reviveIcon setWaypoint( true, true );
  1804. reviveIcon SetTargetEnt( self );
  1805. reviveIcon thread destroyOnReviveEntDeath( reviveEnt );
  1806.  
  1807. reviveIcon.color = (0.33, 0.75, 0.24);
  1808. self playDeathSound();
  1809.  
  1810. if ( isFinalStand )
  1811. {
  1812. wait( delay );
  1813.  
  1814. if ( self.inFinalStand )
  1815. self thread lastStandBleedOut( isFinalStand, reviveEnt );
  1816. }
  1817.  
  1818. return;
  1819. }
  1820. else if( level.dieHardMode == 2 )
  1821. {
  1822. self thread lastStandKeepOverlay();
  1823. reviveEnt = spawn( "script_model", self.origin );
  1824. reviveEnt setModel( "tag_origin" );
  1825. reviveEnt setCursorHint( "HINT_NOICON" );
  1826. reviveEnt setHintString( &"PLATFORM_REVIVE" );
  1827.  
  1828. reviveEnt reviveSetup( self );
  1829. reviveEnt endon ( "death" );
  1830.  
  1831. reviveIcon = newTeamHudElem( self.team );
  1832. reviveIcon setShader( "waypoint_revive", 8, 8 );
  1833. reviveIcon setWaypoint( true, true );
  1834. reviveIcon SetTargetEnt( self );
  1835. reviveIcon thread destroyOnReviveEntDeath( reviveEnt );
  1836.  
  1837. reviveIcon.color = (0.33, 0.75, 0.24);
  1838. self playDeathSound();
  1839.  
  1840. if ( isFinalStand )
  1841. {
  1842. wait( delay );
  1843.  
  1844. if ( self.inFinalStand )
  1845. self thread lastStandBleedOut( isFinalStand, reviveEnt );
  1846. }
  1847.  
  1848. wait delay / 3;
  1849. reviveIcon.color = (1.0, 0.64, 0.0);
  1850.  
  1851. while ( reviveEnt.inUse )
  1852. wait ( 0.05 );
  1853.  
  1854. self playDeathSound();
  1855. wait delay / 3;
  1856. reviveIcon.color = (1.0, 0.0, 0.0);
  1857.  
  1858. while ( reviveEnt.inUse )
  1859. wait ( 0.05 );
  1860.  
  1861. self playDeathSound();
  1862. wait delay / 3;
  1863.  
  1864. while ( reviveEnt.inUse )
  1865. wait ( 0.05 );
  1866.  
  1867. wait( 0.05 );
  1868. self thread lastStandBleedOut( isFinalStand );
  1869. return;
  1870. }
  1871.  
  1872. wait( delay );
  1873. self thread lastStandBleedout( isFinalStand );
  1874.  
  1875. }
  1876.  
  1877. maxHealthOverlay( maxHealth, refresh )
  1878. {
  1879. self endon( "stop_maxHealthOverlay" );
  1880. self endon( "revive" );
  1881. self endon( "death" );
  1882.  
  1883. for( ;; )
  1884. {
  1885. self.health -= 1;
  1886. self.maxHealth = maxHealth;
  1887. wait( .05 );
  1888. self.maxHealth = 50;
  1889. self.health += 1;
  1890.  
  1891. wait ( .50 );
  1892. }
  1893. }
  1894.  
  1895. lastStandBleedOut( reviveOnBleedOut, reviveEnt )
  1896. {
  1897. if ( reviveOnBleedOut )
  1898. {
  1899. self.lastStand = undefined;
  1900. self.inFinalStand = false;
  1901. self clearLowerMessage( "last_stand" );
  1902. maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer();
  1903.  
  1904. if( isDefined( reviveEnt ) )
  1905. reviveEnt Delete();
  1906. }
  1907. else
  1908. {
  1909. self.useLastStandParams = true;
  1910. self.beingRevived = false;
  1911. self _suicide();
  1912. }
  1913. }
  1914.  
  1915.  
  1916. lastStandAllowSuicide()
  1917. {
  1918. self endon( "death" );
  1919. self endon( "disconnect" );
  1920. self endon( "game_ended" );
  1921. self endon( "revive");
  1922.  
  1923. while ( 1 )
  1924. {
  1925. if ( self useButtonPressed() )
  1926. {
  1927. pressStartTime = gettime();
  1928. while ( self useButtonPressed() )
  1929. {
  1930. wait .05;
  1931. if ( gettime() - pressStartTime > 700 )
  1932. break;
  1933. }
  1934. if ( gettime() - pressStartTime > 700 )
  1935. break;
  1936. }
  1937. wait .05;
  1938. }
  1939.  
  1940. self thread lastStandBleedOut( false );
  1941. }
  1942.  
  1943. lastStandKeepOverlay()
  1944. {
  1945. level endon( "game_ended" );
  1946. self endon( "death" );
  1947. self endon( "disconnect" );
  1948. self endon( "revive" );
  1949.  
  1950. // keep the health overlay going by making code think the player is getting damaged
  1951. while ( !level.gameEnded )
  1952. {
  1953. self.health = 2;
  1954. wait .05;
  1955. self.health = 1;
  1956. wait .5;
  1957. }
  1958.  
  1959. self.health = self.maxhealth;
  1960. }
  1961.  
  1962.  
  1963. lastStandWaittillDeath()
  1964. {
  1965. self endon( "disconnect" );
  1966. self endon( "revive" );
  1967. level endon( "game_ended" );
  1968. self waittill( "death" );
  1969.  
  1970. self clearLowerMessage( "last_stand" );
  1971. self.lastStand = undefined;
  1972. }
  1973.  
  1974.  
  1975. mayDoLastStand( sWeapon, sMeansOfDeath, sHitLoc )
  1976. {
  1977. if ( sMeansOfDeath == "MOD_TRIGGER_HURT" )
  1978. return false;
  1979.  
  1980. if ( sMeansOfDeath != "MOD_PISTOL_BULLET" && sMeansOfDeath != "MOD_RIFLE_BULLET" && sMeansOfDeath != "MOD_FALLING" && sMeansOfDeath != "MOD_EXPLOSIVE_BULLET" )
  1981. return false;
  1982.  
  1983. if ( sMeansOfDeath == "MOD_IMPACT" && sWeapon == "throwingknife_mp" )
  1984. return false;
  1985.  
  1986. if ( sMeansOfDeath == "MOD_IMPACT" && ( sWeapon == "m79_mp" || isSubStr(sWeapon, "gl_") ) )
  1987. return false;
  1988.  
  1989. if ( isHeadShot( sWeapon, sHitLoc, sMeansOfDeath ) )
  1990. return false;
  1991.  
  1992. if ( self isUsingRemote() )
  1993. return false;
  1994.  
  1995. return true;
  1996. }
  1997.  
  1998.  
  1999. ensureLastStandParamsValidity()
  2000. {
  2001. // attacker may have become undefined if the player that killed me has disconnected
  2002. if ( !isDefined( self.lastStandParams.attacker ) )
  2003. self.lastStandParams.attacker = self;
  2004. }
  2005.  
  2006. getHitLocHeight( sHitLoc )
  2007. {
  2008. switch( sHitLoc )
  2009. {
  2010. case "helmet":
  2011. case "head":
  2012. case "neck":
  2013. return 60;
  2014. case "torso_upper":
  2015. case "right_arm_upper":
  2016. case "left_arm_upper":
  2017. case "right_arm_lower":
  2018. case "left_arm_lower":
  2019. case "right_hand":
  2020. case "left_hand":
  2021. case "gun":
  2022. return 48;
  2023. case "torso_lower":
  2024. return 40;
  2025. case "right_leg_upper":
  2026. case "left_leg_upper":
  2027. return 32;
  2028. case "right_leg_lower":
  2029. case "left_leg_lower":
  2030. return 10;
  2031. case "right_foot":
  2032. case "left_foot":
  2033. return 5;
  2034. }
  2035. return 48;
  2036. }
  2037.  
  2038. delayStartRagdoll( ent, sHitLoc, vDir, sWeapon, eInflictor, sMeansOfDeath )
  2039. {
  2040. if ( isDefined( ent ) )
  2041. {
  2042. deathAnim = ent getCorpseAnim();
  2043. if ( animhasnotetrack( deathAnim, "ignore_ragdoll" ) )
  2044. return;
  2045. }
  2046.  
  2047. wait( 0.2 );
  2048.  
  2049. if ( !isDefined( ent ) )
  2050. return;
  2051.  
  2052. if ( ent isRagDoll() )
  2053. return;
  2054.  
  2055. deathAnim = ent getcorpseanim();
  2056.  
  2057. startFrac = 0.35;
  2058.  
  2059. if ( animhasnotetrack( deathAnim, "start_ragdoll" ) )
  2060. {
  2061. times = getnotetracktimes( deathAnim, "start_ragdoll" );
  2062. if ( isDefined( times ) )
  2063. startFrac = times[ 0 ];
  2064. }
  2065.  
  2066. waitTime = startFrac * getanimlength( deathAnim );
  2067. wait( waitTime );
  2068.  
  2069. if ( isDefined( ent ) )
  2070. {
  2071. ent startragdoll( 1 );
  2072. }
  2073. }
  2074.  
  2075.  
  2076. getMostKilledBy()
  2077. {
  2078. mostKilledBy = "";
  2079. killCount = 0;
  2080.  
  2081. killedByNames = getArrayKeys( self.killedBy );
  2082.  
  2083. for ( index = 0; index < killedByNames.size; index++ )
  2084. {
  2085. killedByName = killedByNames[ index ];
  2086. if ( self.killedBy[ killedByName ] <= killCount )
  2087. continue;
  2088.  
  2089. killCount = self.killedBy[ killedByName ];
  2090. mostKilleBy = killedByName;
  2091. }
  2092.  
  2093. return mostKilledBy;
  2094. }
  2095.  
  2096.  
  2097. getMostKilled()
  2098. {
  2099. mostKilled = "";
  2100. killCount = 0;
  2101.  
  2102. killedNames = getArrayKeys( self.killedPlayers );
  2103.  
  2104. for ( index = 0; index < killedNames.size; index++ )
  2105. {
  2106. killedName = killedNames[ index ];
  2107. if ( self.killedPlayers[ killedName ] <= killCount )
  2108. continue;
  2109.  
  2110. killCount = self.killedPlayers[ killedName ];
  2111. mostKilled = killedName;
  2112. }
  2113.  
  2114. return mostKilled;
  2115. }
  2116.  
  2117.  
  2118. damageShellshockAndRumble( eInflictor, sWeapon, sMeansOfDeath, iDamage, iDFlags, eAttacker )
  2119. {
  2120. self thread maps\mp\gametypes\_weapons::onWeaponDamage( eInflictor, sWeapon, sMeansOfDeath, iDamage, eAttacker );
  2121. self PlayRumbleOnEntity( "damage_heavy" );
  2122. }
  2123.  
  2124.  
  2125. reviveSetup( owner )
  2126. {
  2127. team = owner.team;
  2128.  
  2129. self linkTo( owner, "tag_origin" );
  2130.  
  2131. self.owner = owner;
  2132. self.inUse = false;
  2133. self makeUsable();
  2134. self updateUsableByTeam( team );
  2135. self thread trackTeamChanges( team );
  2136.  
  2137. self thread reviveTriggerThink( team );
  2138.  
  2139. self thread deleteOnReviveOrDeathOrDisconnect();
  2140. }
  2141.  
  2142.  
  2143. deleteOnReviveOrDeathOrDisconnect()
  2144. {
  2145. self endon ( "death" );
  2146.  
  2147. self.owner waittill_any ( "death", "disconnect" );
  2148.  
  2149. self delete();
  2150. }
  2151.  
  2152.  
  2153. updateUsableByTeam( team )
  2154. {
  2155. foreach (player in level.players)
  2156. {
  2157. if ( team == player.team && player != self.owner )
  2158. self enablePlayerUse( player );
  2159. else
  2160. self disablePlayerUse( player );
  2161. }
  2162. }
  2163.  
  2164.  
  2165. trackTeamChanges( team )
  2166. {
  2167. self endon ( "death" );
  2168.  
  2169. while ( true )
  2170. {
  2171. level waittill ( "joined_team" );
  2172.  
  2173. self updateUsableByTeam( team );
  2174. }
  2175. }
  2176.  
  2177.  
  2178. trackLastStandChanges( team )
  2179. {
  2180. self endon ( "death" );
  2181.  
  2182. while ( true )
  2183. {
  2184. level waittill ( "player_last_stand" );
  2185.  
  2186. self updateUsableByTeam( team );
  2187. }
  2188. }
  2189.  
  2190.  
  2191. reviveTriggerThink( team )
  2192. {
  2193. self endon ( "death" );
  2194. level endon ( "game_ended" );
  2195.  
  2196. for ( ;; )
  2197. {
  2198. self waittill ( "trigger", player );
  2199. self.owner.beingRevived = true;
  2200.  
  2201. if ( isDefined(player.beingRevived) && player.beingRevived )
  2202. {
  2203. self.owner.beingRevived = false;
  2204. continue;
  2205. }
  2206.  
  2207. self makeUnUsable();
  2208. self.owner freezeControlsWrapper( true );
  2209.  
  2210. revived = self useHoldThink( player );
  2211. self.owner.beingRevived = false;
  2212.  
  2213. if ( !isAlive( self.owner ) )
  2214. {
  2215. self delete();
  2216. return;
  2217. }
  2218.  
  2219. self.owner freezeControlsWrapper( false );
  2220.  
  2221. if ( revived )
  2222. {
  2223. player thread maps\mp\gametypes\_hud_message::SplashNotifyDelayed( "reviver", 200 );
  2224. player thread maps\mp\gametypes\_rank::giveRankXP( "reviver", 200 );
  2225.  
  2226. self.owner.lastStand = undefined;
  2227. self.owner clearLowerMessage( "last_stand" );
  2228.  
  2229. if ( self.owner _hasPerk( "specialty_lightweight" ) )
  2230. self.owner.moveSpeedScaler = 1.07;
  2231. else
  2232. self.owner.moveSpeedScaler = 1;
  2233.  
  2234. self.owner.maxHealth = 100;
  2235.  
  2236. self.owner maps\mp\gametypes\_weapons::updateMoveSpeedScale( "primary" );
  2237. self.owner maps\mp\gametypes\_playerlogic::lastStandRespawnPlayer();
  2238.  
  2239. self.owner setPerk( "specialty_pistoldeath", true );
  2240. self.owner.beingRevived = false;
  2241.  
  2242. self delete();
  2243. return;
  2244. }
  2245.  
  2246. self makeUsable();
  2247. self updateUsableByTeam( team );
  2248. }
  2249. }
  2250.  
  2251.  
  2252.  
  2253. /*
  2254. =============
  2255. useHoldThink
  2256.  
  2257. Claims the use trigger for player and displays a use bar
  2258. Returns true if the player sucessfully fills the use bar
  2259. =============
  2260. */
  2261. useHoldThink( player )
  2262. {
  2263. reviveSpot = spawn( "script_origin", self.origin );
  2264. reviveSpot hide();
  2265. player playerLinkTo( reviveSpot );
  2266. player PlayerLinkedOffsetEnable();
  2267.  
  2268. player _disableWeapon();
  2269.  
  2270. self.curProgress = 0;
  2271. self.inUse = true;
  2272. self.useRate = 0;
  2273. self.useTime = 3000;
  2274.  
  2275. player thread personalUseBar( self );
  2276.  
  2277. result = useHoldThinkLoop( player );
  2278.  
  2279. if ( isDefined( player ) && isReallyAlive( player ) )
  2280. {
  2281. player Unlink();
  2282. player _enableWeapon();
  2283. }
  2284.  
  2285. if ( isDefined( result ) && result )
  2286. {
  2287. self.owner thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "revived", player );
  2288. self.owner.inlaststand = false;
  2289. return true;
  2290. }
  2291.  
  2292. self.inUse = false;
  2293. reviveSpot Delete();
  2294. return false;
  2295. }
  2296.  
  2297.  
  2298. personalUseBar( object )
  2299. {
  2300. useBar = self createPrimaryProgressBar();
  2301. useBarText = self createPrimaryProgressBarText();
  2302. useBarText setText( &"MPUI_REVIVING" );
  2303.  
  2304. objUseBar = object.owner createPrimaryProgressBar();
  2305. objUseBarText = object.owner createPrimaryProgressBarText();
  2306. objUseBarText setText( &"MPUI_BEING_REVIVED" );
  2307.  
  2308. lastRate = -1;
  2309. while ( isReallyAlive( self ) && isDefined( object ) && object.inUse && !level.gameEnded && isDefined( self ) )
  2310. {
  2311. if ( lastRate != object.useRate )
  2312. {
  2313. if( object.curProgress > object.useTime)
  2314. object.curProgress = object.useTime;
  2315.  
  2316. useBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate );
  2317. objUseBar updateBar( object.curProgress / object.useTime, (1000 / object.useTime) * object.useRate );
  2318.  
  2319. if ( !object.useRate )
  2320. {
  2321. useBar hideElem();
  2322. useBarText hideElem();
  2323.  
  2324. objUseBar hideElem();
  2325. objUseBarText hideElem();
  2326. }
  2327. else
  2328. {
  2329. useBar showElem();
  2330. useBarText showElem();
  2331.  
  2332. objUseBar showElem();
  2333. objUseBarText showElem();
  2334. }
  2335. }
  2336. lastRate = object.useRate;
  2337. wait ( 0.05 );
  2338. }
  2339.  
  2340. // when the players disconnect the hudElems are destroyed automatically
  2341. if ( isDefined( useBar ) )
  2342. useBar destroyElem();
  2343. if ( isDefined( useBarText ) )
  2344. useBarText destroyElem();
  2345.  
  2346. if ( isDefined( objUseBar ) )
  2347. objUseBar destroyElem();
  2348. if ( isDefined( objUseBarText ) )
  2349. objUseBarText destroyElem();
  2350. }
  2351.  
  2352.  
  2353. useHoldThinkLoop( player )
  2354. {
  2355. level endon ( "game_ended" );
  2356. self.owner endon( "death" );
  2357. self.owner endon( "disconnect" );
  2358.  
  2359. while( isReallyAlive( player ) && player useButtonPressed() && self.curProgress < self.useTime )
  2360. {
  2361. self.curProgress += (50 * self.useRate);
  2362. self.useRate = 1; /* * player.objectiveScaler;*/
  2363.  
  2364. if ( self.curProgress >= self.useTime )
  2365. {
  2366. self.inUse = false;
  2367.  
  2368. return isReallyAlive( player );
  2369. }
  2370.  
  2371. wait 0.05;
  2372. }
  2373.  
  2374. return false;
  2375. }
  2376.  
  2377.  
  2378. Callback_KillingBlow( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, sWeapon, vPoint, vDir, sHitLoc, psOffsetTime )
  2379. {
  2380. if ( isDefined(self.lastDamageWasFromEnemy) && self.lastDamageWasFromEnemy && iDamage >= self.health && isDefined( self.combatHigh ) && self.combatHigh == "specialty_endgame" )
  2381. {
  2382. self setAdrenaline( 0 );
  2383. self _setPerk( "specialty_endgame" );
  2384. return false;
  2385. }
  2386.  
  2387. return true;
  2388. }
  2389.  
  2390.  
  2391. emitFallDamage( iDamage )
  2392. {
  2393. PhysicsExplosionSphere( self.origin, 64, 64, 1 );
  2394.  
  2395. // get the entities we landed on
  2396. damageEnts = [];
  2397. for ( testAngle = 0; testAngle < 360; testAngle += 30 )
  2398. {
  2399. xOffset = cos( testAngle ) * 16;
  2400. yOffset = sin( testAngle ) * 16;
  2401.  
  2402. traceData = bulletTrace( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), true, self );
  2403. //thread drawLine( self.origin + (xOffset, yOffset, 4), self.origin + (xOffset,yOffset,-6), 10.0 );
  2404.  
  2405. if ( isDefined( traceData["entity"] ) && isDefined( traceData["entity"].targetname ) && (traceData["entity"].targetname == "destructible_vehicle" || traceData["entity"].targetname == "destructible_toy") )
  2406. damageEnts[damageEnts.size] = traceData["entity"];
  2407. }
  2408.  
  2409. if ( damageEnts.size )
  2410. {
  2411. damageOwner = spawn( "script_origin", self.origin );
  2412. damageOwner hide();
  2413. damageOwner.type = "soft_landing";
  2414. damageOwner.destructibles = damageEnts;
  2415. radiusDamage( self.origin, 64, 100, 100, damageOwner );
  2416.  
  2417. wait ( 0.1 );
  2418. damageOwner delete();
  2419. }
  2420. }
  2421.  
  2422. drawLine( start, end, timeSlice )
  2423. {
  2424. drawTime = int(timeSlice * 20);
  2425. for( time = 0; time < drawTime; time++ )
  2426. {
  2427. line( start, end, (1,0,0),false, 1 );
  2428. wait ( 0.05 );
  2429. }
  2430. }
  2431.  
  2432. isFlankKill( victim, attacker )
  2433. {
  2434. victimForward = anglestoforward( victim.angles );
  2435. victimForward = ( victimForward[0], victimForward[1], 0 );
  2436. victimForward = VectorNormalize( victimForward );
  2437.  
  2438. attackDirection = victim.origin - attacker.origin;
  2439. attackDirection = ( attackDirection[0], attackDirection[1], 0 );
  2440. attackDirection = VectorNormalize( attackDirection );
  2441.  
  2442. dotProduct = VectorDot( victimForward, attackDirection );
  2443. if ( dotProduct > 0 ) // 0 = cos( 90 ), 180 degree arc total
  2444. return true;
  2445. else
  2446. return false;
  2447. }
  2448.  
  2449. _obituary( victim, attacker, sWeapon, sMeansOfDeath )
  2450. {
  2451. victimTeam = victim.team;
  2452.  
  2453. foreach ( player in level.players )
  2454. {
  2455. playerTeam = player.team;
  2456. if ( playerTeam == "spectator" )
  2457. player iPrintLn( &"MP_OBITUARY_NEUTRAL", attacker.name, victim.name );
  2458. else if ( playerTeam == victimTeam )
  2459. player iPrintLn( &"MP_OBITUARY_ENEMY", attacker.name, victim.name );
  2460. else
  2461. player iPrintLn( &"MP_OBITUARY_FRIENDLY", attacker.name, victim.name );
  2462. }
  2463. }
  2464.  
  2465.  
  2466. logPrintPlayerDeath( lifeId, attacker, iDamage, sMeansOfDeath, sWeapon, sPrimaryWeapon, sHitLoc )
  2467. {
  2468. // create a lot of redundant data for the log print
  2469. lpselfnum = self getEntityNumber();
  2470. lpselfname = self.name;
  2471. lpselfteam = self.team;
  2472. lpselfguid = self.guid;
  2473.  
  2474. if ( isPlayer( attacker ) )
  2475. {
  2476. lpattackGuid = attacker.guid;
  2477. lpattackname = attacker.name;
  2478. lpattackerteam = attacker.team;
  2479. lpattacknum = attacker getEntityNumber();
  2480. attackerString = attacker getXuid() + "(" + lpattackname + ")";
  2481. }
  2482. else
  2483. {
  2484. lpattackGuid = "";
  2485. lpattackname = "";
  2486. lpattackerteam = "world";
  2487. lpattacknum = -1;
  2488. attackerString = "none";
  2489. }
  2490.  
  2491. logPrint( "K;" + lpselfguid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackguid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + sWeapon + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );
  2492. }
  2493.  
  2494.  
  2495. destroyOnReviveEntDeath( reviveEnt )
  2496. {
  2497. reviveEnt waittill ( "death" );
  2498.  
  2499. self destroy();
  2500. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement