Advertisement
Guest User

Untitled

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