‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_globallogic_player.gsc
Go to the documentation of this file.
1 #using scripts\shared\abilities\_ability_player;
2 #using scripts\shared\abilities\_ability_power;
3 #using scripts\shared\abilities\_ability_util;
4 #using scripts\shared\callbacks_shared;
5 #using scripts\shared\challenges_shared;
6 #using scripts\shared\clientfield_shared;
7 #using scripts\shared\damagefeedback_shared;
8 #using scripts\shared\demo_shared;
9 #using scripts\shared\flag_shared;
10 #using scripts\shared\hostmigration_shared;
11 #using scripts\shared\hud_message_shared;
12 #using scripts\shared\hud_util_shared;
13 #using scripts\shared\killstreaks_shared;
14 #using scripts\shared\math_shared;
15 #using scripts\shared\medals_shared;
16 #using scripts\shared\persistence_shared;
17 #using scripts\shared\player_shared;
18 #using scripts\shared\rank_shared;
19 #using scripts\shared\scoreevents_shared;
20 #using scripts\shared\tweakables_shared;
21 #using scripts\shared\util_shared;
22 #using scripts\shared\weapons_shared;
23 #using scripts\shared\weapons\_weapon_utils;
24 #using scripts\shared\weapons\_weapons;
25 #using scripts\shared\ai\systems\gib;
26 
27 #insert scripts\shared\shared.gsh;
28 
29 #using scripts\mp\gametypes\_battlechatter;
30 #using scripts\mp\gametypes\_deathicons;
31 #using scripts\mp\gametypes\_globallogic;
32 #using scripts\mp\gametypes\_globallogic_audio;
33 #using scripts\mp\gametypes\_globallogic_score;
34 #using scripts\mp\gametypes\_globallogic_spawn;
35 #using scripts\mp\gametypes\_globallogic_ui;
36 #using scripts\mp\gametypes\_globallogic_utils;
37 #using scripts\mp\gametypes\_globallogic_vehicle;
38 #using scripts\mp\gametypes\_hostmigration;
39 #using scripts\mp\gametypes\_hud_message;
40 #using scripts\mp\gametypes\_killcam;
41 #using scripts\mp\gametypes\_loadout;
42 #using scripts\mp\gametypes\_spawning;
43 #using scripts\mp\gametypes\_spawnlogic;
44 #using scripts\mp\gametypes\_spectating;
45 #using scripts\mp\gametypes\_weapons;
46 
47 #using scripts\mp\_armor;
48 #using scripts\mp\_behavior_tracker;
49 #using scripts\shared\_burnplayer;
50 #using scripts\mp\_challenges;
51 #using scripts\mp\_contracts;
52 #using scripts\mp\_gamerep;
53 #using scripts\mp\_laststand;
54 #using scripts\mp\_teamops;
55 #using scripts\mp\_util;
56 #using scripts\mp\_vehicle;
57 #using scripts\mp\killstreaks\_killstreaks;
58 #using scripts\mp\teams\_teams;
59 
60 #insert scripts\shared\abilities\_ability_util.gsh;
61 #insert scripts\mp\_contracts.gsh;
62 
63 #define TAUNT_TYPE_FIRST_PLACE 0
64 
65 #define GESTURE_TYPE_GOOD_GAME 0
66 #define GESTURE_TYPE_THREATEN 1
67 #define GESTURE_TYPE_BOAST 2
68 #define GESTURE_TYPE_MAX 7
69 
70 #namespace globallogic_player;
71 
73 {
74  // for cod caster update the top scorers
75  if ( !level.rankedMatch && !level.teambased )
76  {
77  level thread ‪update_ffa_top_scorers();
78  }
79 }
80 
82 {
84 
85  self closeInGameMenu();
86 
88 
89  if( !SessionModeIsZombiesGame() )
90  {
91  currentWeapon = self GetCurrentWeapon();
92  if ( ‪killstreaks::is_killstreak_weapon( currentWeapon ) && !currentWeapon.isCarriedKillstreak )
93  self takeWeapon( currentWeapon );
94  }
95 }
96 
97 function ‪ArrayToString( inputArray )
98 {
99  targetString = "";
100  for (i=0; i < inputArray.size; i++)
101  {
102  targetString += inputArray[i];
103  if (i != inputArray.size-1)
104  targetString += ",";
105  }
106  return targetString;
107 }
108 
109 
111 {
112  lpselfnum = player getEntityNumber();
113  lpXuid = player getxuid(true);
114 
115  weeklyAContractId = 0;
116  weeklyAContractTarget = 0;
117  weeklyAContractCurrent = 0;
118  weeklyAContractCompleted = 0;
119 
120  weeklyBContractId = 0;
121  weeklyBContractTarget = 0;
122  weeklyBContractCurrent = 0;
123  weeklyBContractCompleted = 0;
124 
125  dailyContractId = 0;
126  dailyContractTarget = 0;
127  dailyContractCurrent = 0;
128  dailyContractCompleted = 0;
129 
130  specialContractId = 0;
131  specialContractTarget = 0;
132  specialContractCurent = 0;
133  specialContractCompleted = 0;
134 
135  if ( player ‪util::is_bot() )
136  {
137  currXP = 0;
138  prevXP = 0;
139  }
140  else
141  {
142  currXP = player ‪rank::getRankXpStat();
143  prevXP = player.pers["rankxp"];
144 
146  {
147  specialContractId = 1; // this is a one-off contract. Use any non-zero value to indicate that it is populated.
148  specialContractTarget = GetDvarInt( "weapon_contract_target_value", 100 );
149  specialContractCurent = player GetDStat( "weaponContractData", "currentValue" );
150  if ( ‪VAL( player GetDStat( "weaponContractData", "completeTimestamp" ), 0 ) != 0 )
151  {
152  specialContractCompleted = 1;
153  }
154  }
155 
157  {
158  contractId = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_WEEKLY_SLOT_A, "index" );
159  if ( player ‪contracts::is_contract_active( contractId ) )
160  {
161  weeklyAContractId = contractId;
162  weeklyAContractTarget = player.pers[ "contracts" ][ weeklyAContractId ].target_value;
163  weeklyAContractCurrent = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_WEEKLY_SLOT_A, "progress" );
164  weeklyAContractCompleted = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_WEEKLY_SLOT_A, "award_given" );
165  }
166 
167  contractId = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_WEEKLY_SLOT_B, "index" );
168  if ( player ‪contracts::is_contract_active( contractId ) )
169  {
170  weeklyBContractId = contractId;
171  weeklyBContractTarget = player.pers["contracts" ][ weeklyBContractId ].target_value;
172  weeklyBContractCurrent = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_WEEKLY_SLOT_B, "progress" );
173  weeklyBContractCompleted = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_WEEKLY_SLOT_B, "award_given" );
174  }
175 
176  contractId = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_DAILY_SLOT, "index" );
177  if ( player ‪contracts::is_contract_active( contractId ) )
178  {
179  dailyContractId = contractId;
180  dailyContractTarget = player.pers[ "contracts" ][ dailyContractId ].target_value;
181  dailyContractCurrent = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_DAILY_SLOT, "progress" );
182  dailyContractCompleted = player ‪contracts::get_contract_stat( ‪MP_CONTRACT_DAILY_SLOT, "award_given" );
183  }
184  }
185  }
186 
187  if ( !isdefined( prevXP ) )
188  {
189  // most likely the player never fully connected in the first place
190  // it is possible to specify a default value for prevXP,
191  // however, the call to RecordComScoreEvent() will SRE as most of player.pers[] is missing
192  return;
193  }
194 
195  resultStr = ‪result;
196  if ( isDefined(player.team) && ‪result == player.team )
197  resultStr ="win";
198  else if ( ‪result == "allies" || ‪result == "axis" )
199  resultStr = "lose";
200 
201  xpEarned = currXP - prevXP;
202 
203  perkStr = ‪ArrayToString( player GetPerks() );
204 
205  primaryWeaponName = "";
206  primaryWeaponAttachStr="";
207  secondaryWeaponName = "";
208  secondaryWeaponAttachStr="";
209  grenadePrimaryName = "";
210  grenadeSecondaryName = "";
211 
212 
213 
214  if (isdefined( player.primaryLoadoutWeapon ))
215  {
216  primaryWeaponName = player.primaryLoadoutWeapon.name;
217  primaryWeaponAttachStr = ‪ArrayToString( GetArrayKeys(player.primaryLoadoutWeapon.attachments) );
218  }
219  if (isdefined( player.secondaryLoadoutWeapon ))
220  {
221  secondaryWeaponName = player.secondaryLoadoutWeapon.name;
222  secondaryWeaponAttachStr = ‪ArrayToString( GetArrayKeys(player.secondaryLoadoutWeapon.attachments) );
223  }
224 
225  if (isdefined( player.grenadeTypePrimary ))
226  grenadePrimaryName = player.grenadeTypePrimary.name;
227  if (isdefined( player.grenadeTypeSecondary ))
228  grenadeSecondaryName = player.grenadeTypeSecondary.name;
229 
230  killStreakStr = ‪ArrayToString( player.killstreak );
231 
232  gameLength = game["timepassed"] / 1000;
233  timePlayed = player ‪globallogic::getTotalTimePlayed( gameLength );
234 
235  totalKills = 0;
236  totalHits = 0;
237  totalDeaths = 0;
238  totalWins = 0;
239  totalXP = 0;
240 
241  if ( level.gametype != "fr" )
242  {
243  totalKills = player GetDStat( "playerstatslist", "kills", "statValue" );
244  totalHits = player GetDStat( "playerstatslist", "hits", "statValue" );
245  totalDeaths = player GetDStat( "playerstatslist", "deaths", "statValue" );
246  totalWins = player GetDStat( "playerstatslist", "wins", "statValue" );
247  totalXP = player GetDStat( "playerstatslist", "rankxp", "statValue" );
248  }
249 
250  killCount = 0;
251  hitCount = 0;
252 
253  if( level.mpCustomMatch )
254  {
255  killCount = player.kills;
256  hitCount = player.shotshit;
257  }
258  else
259  {
260  if ( isdefined( player.startKills ) )
261  killCount = totalKills - player.startKills;
262 
263  if ( isdefined( player.startHits ) )
264  hitCount = totalHits - player.startHits;
265  }
266 
267  bestScore = "0";
268  if ( isdefined( player.pers["lastHighestScore"] ) && player.score > player.pers["lastHighestScore"] )
269  bestScore = "1";
270 
271  bestKills = "0";
272  if ( isdefined( player.pers["lastHighestKills"] ) && killCount > player.pers["lastHighestKills"] )
273  bestKills = "1";
274 
275  totalMatchShots = 0;
276  if ( isdefined( player.totalMatchShots) )
277  totalMatchShots = player.totalMatchShots;
278 
279  deaths = player.deaths;
280  if (deaths == 0)
281  deaths = 1;
282  kdRatio = player.kills*1000/deaths;
283  bestKDRatio = "0";
284  if ( isdefined( player.pers["lastHighestKDRatio"] ) && kdRatio > player.pers["lastHighestKDRatio"] )
285  bestKDRatio = "1";
286 
287  showcaseWeapon = player GetPlayerShowcaseWeapon();
288 
289  RecordComScoreEvent( "end_match",
290  "match_id", getDemoFileID(),
291  "game_variant", "mp",
292  "game_mode", level.gametype,
293  "private_match", SessionModeIsPrivate(),
294  "esports_flag", level.leagueMatch,
295  "ranked_play_flag", level.arenaMatch,
296  "league_team_id", player getLeagueTeamID(),
297  "game_map", GetDvarString( "mapname" ),
298  "player_xuid", player getxuid(true),
299  "player_ip", player getipaddress(),
300  "match_kills", killCount,
301  "match_deaths", player.deaths,
302  "match_xp", xpEarned,
303  "match_score", player.score,
304  "match_streak", player.pers["best_kill_streak"],
305  "match_captures", player.pers["captures"],
306  "match_defends", player.pers["defends"],
307  "match_headshots", player.pers["headshots"],
308  "match_longshots", player.pers["longshots"],
309  "match_objtime", player.pers["objtime"],
310  "match_plants", player.pers["plants"],
311  "match_defuses", player.pers["defuses"],
312  "match_throws", player.pers["throws"],
313  "match_carries", player.pers["carries"],
314  "match_returns", player.pers["returns"],
315  "prestige_max", player.pers["plevel"],
316  "level_max", player.pers["rank"],
317  "match_result", resultStr,
318  "match_duration", timePlayed,
319  "match_shots", totalMatchShots,
320  "match_hits", hitCount,
321  "player_gender", player GetPlayerGenderType( CurrentSessionMode() ),
322  "specialist_kills", player.heroweaponKillCount,
323  "specialist_used", player GetMpDialogName(),
324  "season_pass_owned", player HasSeasonPass(0),
325  "loadout_perks", perkStr,
326  "loadout_lethal", grenadePrimaryName,
327  "loadout_tactical", grenadeSecondaryName,
328  "loadout_scorestreaks", killStreakStr,
329  "loadout_primary_weapon", primaryWeaponName,
330  "loadout_secondary_weapon", secondaryWeaponName,
331  "dlc_owned", player GetDLCAvailable(),
332  "loadout_primary_attachments", primaryWeaponAttachStr,
333  "loadout_secondary_attachments",secondaryWeaponAttachStr,
334  "best_score", bestScore,
335  "best_kills", bestKills,
336  "best_kd", bestKDRatio,
337  "total_kills", totalKills,
338  "total_deaths", totalDeaths,
339  "total_wins", totalWins,
340  "total_xp", totalXP,
341  "daily_contract_id", dailyContractId,
342  "daily_contract_target", dailyContractTarget,
343  "daily_contract_current", dailyContractCurrent,
344  "daily_contract_completed", dailyContractCompleted,
345  "weeklyA_contract_id", weeklyAContractId,
346  "weeklyA_contract_target", weeklyAContractTarget,
347  "weeklyA_contract_current", weeklyAContractCurrent,
348  "weeklyA_contract_completed", weeklyAContractCompleted,
349  "weeklyB_contract_id", weeklyBContractId,
350  "weeklyB_contract_target", weeklyBContractTarget,
351  "weeklyB_contract_current", weeklyBContractCurrent,
352  "weeklyB_contract_completed", weeklyBContractCompleted,
353  "special_contract_id ", specialContractId,
354  "special_contract_target", specialContractTarget,
355  "special_contract_curent", specialContractCurent,
356  "special_contract_completed", specialContractCompleted,
357  "specialist_power", player.heroabilityname,
358  "specialist_head", player GetCharacterHelmetModel(),
359  "specialist_body", player GetCharacterBodyModel(),
360  "specialist_taunt", player GetPlayerSelectedTauntName( ‪TAUNT_TYPE_FIRST_PLACE ),
361  "specialist_goodgame", player GetPlayerSelectedGestureName( ‪GESTURE_TYPE_GOOD_GAME ),
362  "specialist_threaten", player GetPlayerSelectedGestureName( ‪GESTURE_TYPE_THREATEN ),
363  "specialist_boast", player GetPlayerSelectedGestureName( ‪GESTURE_TYPE_BOAST ),
364  "specialist_showcase", showcaseWeapon.weapon.name
365  );
366 }
367 
369 {
370  self endon ( "death" );
371  self endon ( "disconnect" );
372  waitTime = 1;
373  minimumMoveDistance = 16;
374 
375  //Ignore data immediatly after spawn
376  wait 4;
377 
378  prevpos = self.origin;
379  positionPTM = self.origin;
380  while( 1 )
381  {
382  wait waitTime;
383 
384  if (self ‪util::isUsingRemote())
385  {
386  self waittill ("stopped_using_remote");
387  prevpos = self.origin;
388  positionPTM = self.origin;
389  continue;
390  }
391 
392  distance = distance( self.origin, prevpos );
393  self.pers["total_distance_travelled"] += distance;
394  self.pers["movement_Update_Count"]++;
395  prevpos = self.origin;
396 
397  if ((self.pers["movement_Update_Count"] % 5) == 0)
398  {
399  distanceMoving = distance(self.origin, positionPTM);
400  positionPTM = self.origin;
401  if ( distanceMoving > minimumMoveDistance )
402  {
403  self.pers["num_speeds_when_moving_entries"]++;
404  self.pers["total_speeds_when_moving"] += ( distanceMoving / waitTime );
405  self.pers["time_played_moving"] += waitTime;
406  }
407  }
408 
409 
410  }
411 }
412 
414 {
415  // safe to assume fields on self exist?
416  if( !isDefined( self.lastSwimmingStartTime) || !isDefined( self.lastWallRunStartTime) || !isDefined( self.lastSlideStartTime) || !isDefined( self.lastDoubleJumpStartTime) ||
417  !isDefined( self.timeSpentSwimmingInLife) || !isDefined( self.timeSpentWallRunningInLife) || !isDefined( self.numberOfDoubleJumpsInLife) || !isDefined( self.numberOfSlidesInLife) )
418  {
419  /#
420  println( "record_special_move_data_for_life - fields on self not defined!");
421  #/
422  return;
423  }
424 
425  if( isDefined(killer) )
426  {
427  if( !isDefined( killer.lastSwimmingStartTime) || !isDefined( killer.lastWallRunStartTime) || !isDefined( killer.lastSlideStartTime) || !isDefined( killer.lastDoubleJumpStartTime) )
428  {
429  /#
430  println( "record_special_move_data_for_life - fields one killer not defined!");
431  #/
432  return;
433  }
434  matchRecordLogSpecialMoveDataForLife( self, self.lastSwimmingStartTime, self.lastWallRunStartTime, self.lastSlideStartTime, self.lastDoubleJumpStartTime,
435  self.timeSpentSwimmingInLife, self.timeSpentWallRunningInLife, self.numberOfDoubleJumpsInLife, self.numberOfSlidesInLife,
436  killer, killer.lastSwimmingStartTime, killer.lastWallRunStartTime, killer.lastSlideStartTime, killer.lastDoubleJumpStartTime );
437  }
438  else
439  {
440  matchRecordLogSpecialMoveDataForLife( self, self.lastSwimmingStartTime, self.lastWallRunStartTime, self.lastSlideStartTime, self.lastDoubleJumpStartTime,
441  self.timeSpentSwimmingInLife, self.timeSpentWallRunningInLife, self.numberOfDoubleJumpsInLife, self.numberOfSlidesInLife );
442  }
443 
444 }
445 
447 {
448  self endon ( "disconnect" );
449 
450  // make sure no other stray threads running on this dude
451  self notify("stop_player_monitor_wall_run");
452  self endon("stop_player_monitor_wall_run");
453 
454  self.lastWallRunStartTime = 0;
455  self.timeSpentWallRunningInLife = 0;
456  while ( true )
457  {
458  notification = self ‪util::waittill_any_return( "wallrun_begin", "death", "disconnect", "stop_player_monitor_wall_run" );
459  if( notification == "death" )
460  break; // end thread
461 
462  self.lastWallRunStartTime = getTime();
463 
464  notification = self ‪util::waittill_any_return( "wallrun_end", "death", "disconnect", "stop_player_monitor_wall_run" );
465 
466  self.timeSpentWallRunningInLife += (getTime() - self.lastWallRunStartTime);
467 
468  if( notification == "death" )
469  break; // end thread
470 
471  }
472 }
473 
475 {
476  self endon ( "disconnect" );
477 
478  // make sure no other stray threads running on this dude
479  self notify("stop_player_monitor_swimming");
480  self endon("stop_player_monitor_swimming");
481 
482  self.lastSwimmingStartTime = 0;
483  self.timeSpentSwimmingInLife = 0;
484  while ( true )
485  {
486  notification = self ‪util::waittill_any_return( "swimming_begin", "death", "disconnect", "stop_player_monitor_swimming" );
487  if( notification == "death" )
488  break; // end thread
489 
490  self.lastSwimmingStartTime = getTime();
491 
492  notification = self ‪util::waittill_any_return( "swimming_end", "death", "disconnect", "stop_player_monitor_swimming" );
493 
494  self.timeSpentSwimmingInLife += (getTime() - self.lastSwimmingStartTime);
495 
496  if( notification == "death" )
497  break; // end thread
498 
499  }
500 }
501 
503 {
504  self endon ( "disconnect" );
505 
506  // make sure no other stray threads running on this dude
507  self notify("stop_player_monitor_slide");
508  self endon("stop_player_monitor_slide");
509 
510  self.lastSlideStartTime = 0;
511  self.numberOfSlidesInLife = 0;
512  while ( true )
513  {
514  notification = self ‪util::waittill_any_return( "slide_begin", "death", "disconnect", "stop_player_monitor_slide" );
515  if( notification == "death" )
516  break; // end thread
517 
518  self.lastSlideStartTime = getTime();
519  self.numberOfSlidesInLife++;
520 
521  notification = self ‪util::waittill_any_return( "slide_end", "death", "disconnect", "stop_player_monitor_slide" );
522 
523  if( notification == "death" )
524  break; // end thread
525  }
526 }
527 
529 {
530  self endon ( "disconnect" );
531 
532  // make sure no other stray threads running on this dude
533  self notify("stop_player_monitor_doublejump");
534  self endon("stop_player_monitor_doublejump");
535 
536  self.lastDoubleJumpStartTime = 0;
537  self.numberOfDoubleJumpsInLife = 0;
538  while ( true )
539  {
540  notification = self ‪util::waittill_any_return( "doublejump_begin", "death", "disconnect", "stop_player_monitor_doublejump" );
541  if( notification == "death" )
542  break; // end thread
543 
544  self.lastDoubleJumpStartTime = getTime();
545  self.numberOfDoubleJumpsInLife++;
546 
547  notification = self ‪util::waittill_any_return( "doublejump_end", "death", "disconnect", "stop_player_monitor_doublejump" );
548 
549  if( notification == "death" )
550  break; // end thread
551  }
552 }
553 
554 
556 {
557  self endon ( "disconnect" );
558 
559  self notify( "player_monitor_inactivity" );
560  self endon( "player_monitor_inactivity" );
561 
562  wait 10;
563 
564  while( true )
565  {
566  if ( isdefined( self ) )
567  {
568  if ( self isRemoteControlling() || self ‪util::isUsingRemote() )
569  {
570  self ResetInactivityTimer();
571  }
572  }
573  wait 5;
574  }
575 }
576 
578 {
579  thread ‪notifyConnecting();
580 
581  self.statusicon = "hud_status_connecting";
582  self waittill( "begin" );
583 
584  if( isdefined( level.reset_clientdvars ) )
585  self [[level.reset_clientdvars]]();
586 
587  waittillframeend;
588  self.statusicon = "";
589 
590  self.guid = self getGuid();
591 
592  self.killstreak = [];
593 
594  self.leaderDialogQueue = [];
595  self.killstreakDialogQueue = [];
596 
597  profilelog_begintiming( 4, "ship" );
598 
599  level notify( "connected", self );
600  ‪callback::callback( #"on_player_connect" );
601 
602  if ( self IsHost() )
603  self thread ‪globallogic::listenForGameEnd();
604 
605  // only print that we connected if we haven't connected in a previous round
606  if( !level.splitscreen && !isdefined( self.pers["score"] ) )
607  {
608  iPrintLn(&"MP_CONNECTED", self);
609  }
610 
611  if( !isdefined( self.pers["score"] ) )
612  {
615  if ( GameModeIsMode( ‪GAMEMODE_WAGER_MATCH ) && !( self IsHost() ) )
616  self ‪persistence::set_after_action_report_stat( "wagerMatchFailed", 1 );
617  else
618  self ‪persistence::set_after_action_report_stat( "wagerMatchFailed", 0 );
619  }
620 
621  // track match and hosting stats once per match
622  if( ( level.rankedMatch || level.wagerMatch || level.leagueMatch ) && !isdefined( self.pers["matchesPlayedStatsTracked"] ) )
623  {
624  gameMode = ‪util::GetCurrentGameMode();
625  self ‪globallogic::IncrementMatchCompletionStat( gameMode, "played", "started" );
626 
627  if ( !isdefined( self.pers["matchesHostedStatsTracked"] ) && self IsLocalToHost() )
628  {
629  self ‪globallogic::IncrementMatchCompletionStat( gameMode, "hosted", "started" );
630  self.pers["matchesHostedStatsTracked"] = true;
631  }
632 
633  self.pers["matchesPlayedStatsTracked"] = true;
634  self thread ‪persistence::upload_stats_soon();
635  }
636 
638 
639  lpselfnum = self getEntityNumber();
640  lpGuid = self getGuid();
641  lpXuid = self getxuid(true);
642  /#logPrint("J;" + lpGuid + ";" + lpselfnum + ";" + self.‪name + "\n");#/
643 
644  // needed for cross-referencing into player breadcrumb buffer
645  // will get out of sync with self.clientId with disconnects/connects
646  recordPlayerStats( self, "codeClientNum", lpselfnum);
647 
648  if( !SessionModeIsZombiesGame() ) // it will be set after intro screen is faded out for zombie
649  {
650  self setClientUIVisibilityFlag( "hud_visible", 1 );
651  self setClientUIVisibilityFlag( "weapon_hud_visible", 1 );
652  }
653 
654  self SetClientPlayerSprintTime( level.playerSprintTime );
655  self SetClientNumLives( level.numLives );
656 
657  //makeDvarServerInfo( "cg_drawTalk", 1 );
658 
659  if ( level.hardcoreMode )
660  {
661  self SetClientDrawTalk( 3 );
662  }
663 
664  if( SessionModeIsZombiesGame() )
665  {
666  // initial zombies stats
667  self [[level.player_stats_init]]();
668  }
669  else
670  {
671 
672  self ‪globallogic_score::initPersStat( "score" );
673  if ( level.resetPlayerScoreEveryRound )
674  {
675  self.pers["score"] = 0;
676  }
677  self.score = self.pers["score"];
678 
679  self ‪globallogic_score::initPersStat( "pointstowin" );
680  if ( level.scoreRoundWinBased )
681  {
682  self.pers["pointstowin"] = 0;
683  }
684  self.pointstowin = self.pers["pointstowin"];
685 
686  self ‪globallogic_score::initPersStat( "momentum", false );
687  self.momentum = self ‪globallogic_score::getPersStat( "momentum" );
688 
689  self ‪globallogic_score::initPersStat( "suicides" );
690  self.suicides = self ‪globallogic_score::getPersStat( "suicides" );
691 
692  self ‪globallogic_score::initPersStat( "headshots" );
693  self.headshots = self ‪globallogic_score::getPersStat( "headshots" );
694 
695  self ‪globallogic_score::initPersStat( "challenges" );
696  self.challenges = self ‪globallogic_score::getPersStat( "challenges" );
697 
698  self ‪globallogic_score::initPersStat( "kills" );
699  self.kills = self ‪globallogic_score::getPersStat( "kills" );
700 
701  self ‪globallogic_score::initPersStat( "deaths" );
702  self.deaths = self ‪globallogic_score::getPersStat( "deaths" );
703 
704  self ‪globallogic_score::initPersStat( "assists" );
705  self.assists = self ‪globallogic_score::getPersStat( "assists" );
706 
707  self ‪globallogic_score::initPersStat( "defends", false );
708  self.defends = self ‪globallogic_score::getPersStat( "defends" );
709 
710  self ‪globallogic_score::initPersStat( "offends", false );
711  self.offends = self ‪globallogic_score::getPersStat( "offends" );
712 
713  self ‪globallogic_score::initPersStat( "plants", false );
714  self.plants = self ‪globallogic_score::getPersStat( "plants" );
715 
716  self ‪globallogic_score::initPersStat( "defuses", false );
717  self.defuses = self ‪globallogic_score::getPersStat( "defuses" );
718 
719  self ‪globallogic_score::initPersStat( "returns", false );
720  self.returns = self ‪globallogic_score::getPersStat( "returns" );
721 
722  self ‪globallogic_score::initPersStat( "captures", false );
723  self.captures = self ‪globallogic_score::getPersStat( "captures" );
724 
725  self ‪globallogic_score::initPersStat( "objtime", false );
726  self.objtime = self ‪globallogic_score::getPersStat( "objtime" );
727 
728  self ‪globallogic_score::initPersStat( "carries", false );
729  self.carries = self ‪globallogic_score::getPersStat( "carries" );
730 
731  self ‪globallogic_score::initPersStat( "throws", false );
732  self.throws = self ‪globallogic_score::getPersStat( "throws" );
733 
734  self ‪globallogic_score::initPersStat( "destructions", false );
735  self.destructions = self ‪globallogic_score::getPersStat( "destructions" );
736 
737  self ‪globallogic_score::initPersStat( "disables", false );
738  self.disables = self ‪globallogic_score::getPersStat( "disables" );
739 
740  self ‪globallogic_score::initPersStat( "escorts", false );
741  self.escorts = self ‪globallogic_score::getPersStat( "escorts" );
742 
743 
744  self ‪globallogic_score::initPersStat( "sbtimeplayed", false );
745  self.sbtimeplayed = self ‪globallogic_score::getPersStat( "sbtimeplayed" );
746 
747  self ‪globallogic_score::initPersStat( "backstabs", false );
748  self.backstabs = self ‪globallogic_score::getPersStat( "backstabs" );
749 
750  self ‪globallogic_score::initPersStat( "longshots", false );
751  self.longshots = self ‪globallogic_score::getPersStat( "longshots" );
752 
753  self ‪globallogic_score::initPersStat( "survived", false );
754  self.survived = self ‪globallogic_score::getPersStat( "survived" );
755 
756  self ‪globallogic_score::initPersStat( "stabs", false );
757  self.stabs = self ‪globallogic_score::getPersStat( "stabs" );
758 
759  self ‪globallogic_score::initPersStat( "tomahawks", false );
760  self.tomahawks = self ‪globallogic_score::getPersStat( "tomahawks" );
761 
762  self ‪globallogic_score::initPersStat( "humiliated", false );
763  self.humiliated = self ‪globallogic_score::getPersStat( "humiliated" );
764 
765  self ‪globallogic_score::initPersStat( "x2score", false );
766  self.x2score = self ‪globallogic_score::getPersStat( "x2score" );
767 
768  self ‪globallogic_score::initPersStat( "agrkills", false );
769  self.x2score = self ‪globallogic_score::getPersStat( "agrkills" );
770 
771  self ‪globallogic_score::initPersStat( "hacks", false );
772  self.x2score = self ‪globallogic_score::getPersStat( "hacks" );
773 
774  self ‪globallogic_score::initPersStat( "killsconfirmed", false );
775  self.killsconfirmed = self ‪globallogic_score::getPersStat( "killsconfirmed" );
776 
777  self ‪globallogic_score::initPersStat( "killsdenied", false );
778  self.killsdenied = self ‪globallogic_score::getPersStat( "killsdenied" );
779 
780  self ‪globallogic_score::initPersStat( "rescues", false );
781  self.rescues = self ‪globallogic_score::getPersStat( "rescues" );
782 
783  self ‪globallogic_score::initPersStat( "shotsfired", false );
784  self.shotsfired = self ‪globallogic_score::getPersStat( "shotsfired" );
785 
786  self ‪globallogic_score::initPersStat( "shotshit", false );
787  self.shotshit = self ‪globallogic_score::getPersStat( "shotshit" );
788 
789  self ‪globallogic_score::initPersStat( "shotsmissed", false );
790  self.shotsmissed = self ‪globallogic_score::getPersStat( "shotsmissed" );
791 
792  self ‪globallogic_score::initPersStat( "cleandeposits", false );
793  self.cleandeposits = self ‪globallogic_score::getPersStat( "cleandeposits" );
794 
795  self ‪globallogic_score::initPersStat( "cleandenies", false );
796  self.cleandenies = self ‪globallogic_score::getPersStat( "cleandenies" );
797 
798  self ‪globallogic_score::initPersStat( "victory", false );
799  self.victory = self ‪globallogic_score::getPersStat( "victory" );
800 
801  self ‪globallogic_score::initPersStat( "sessionbans", false );
802  self.sessionbans = self ‪globallogic_score::getPersStat( "sessionbans" );
803  self ‪globallogic_score::initPersStat( "gametypeban", false );
804  self ‪globallogic_score::initPersStat( "time_played_total", false );
805  self ‪globallogic_score::initPersStat( "time_played_alive", false );
806 
807  self ‪globallogic_score::initPersStat( "teamkills", false );
808  self ‪globallogic_score::initPersStat( "teamkills_nostats", false );
809 
810  // used by match recorder for analyzing play styles
811  self ‪globallogic_score::initPersStat( "kill_distances", false );
812  self ‪globallogic_score::initPersStat( "num_kill_distance_entries", false );
813  self ‪globallogic_score::initPersStat( "time_played_moving", false );
814  self ‪globallogic_score::initPersStat( "total_speeds_when_moving", false );
815  self ‪globallogic_score::initPersStat( "num_speeds_when_moving_entries", false );
816  self ‪globallogic_score::initPersStat( "total_distance_travelled", false );
817  self ‪globallogic_score::initPersStat( "movement_Update_Count", false );
818 
819  self.teamKillPunish = false;
820  if ( level.minimumAllowedTeamKills >= 0 && self.pers["teamkills_nostats"] > level.minimumAllowedTeamKills )
821  self thread ‪reduceTeamKillsOverTime();
822 
824  }
825 
826  self.killedPlayersCurrent = [];
827 
828  if ( !isdefined( self.pers["totalTimePlayed"] ) )
829  {
830  self setEnterTime( getTime() );
831  self.pers["totalTimePlayed"] = 0;
832  }
833 
834  if ( !isdefined( self.pers["totalMatchBonus"] ) )
835  {
836  self.pers["totalMatchBonus"] = 0;
837  }
838 
839  if( !isdefined( self.pers["best_kill_streak"] ) )
840  {
841  self.pers["killed_players"] = [];
842  self.pers["killed_by"] = [];
843  self.pers["nemesis_tracking"] = [];
844  self.pers["artillery_kills"] = 0;
845  self.pers["dog_kills"] = 0;
846  self.pers["nemesis_name"] = "";
847  self.pers["nemesis_rank"] = 0;
848  self.pers["nemesis_rankIcon"] = 0;
849  self.pers["nemesis_xp"] = 0;
850  self.pers["nemesis_xuid"] = "";
851  self.pers["killed_players_with_specialist"] = [];
852 
853  /*self.killstreakKills["artillery"] = 0;
854  self.killstreakKills["dogs"] = 0;
855  self.killstreaksUsed["radar"] = 0;
856  self.killstreaksUsed["artillery"] = 0;
857  self.killstreaksUsed["dogs"] = 0;*/
858  self.pers["best_kill_streak"] = 0;
859  }
860 
861 // Adding Music tracking per player CDC
862  if( !isdefined( self.pers["music"] ) )
863  {
864  self.pers["music"] = spawnstruct();
865  self.pers["music"].spawn = false;
866  self.pers["music"].inque = false;
867  self.pers["music"].currentState = "SILENT";
868  self.pers["music"].previousState = "SILENT";
869  self.pers["music"].nextstate = "UNDERSCORE";
870  self.pers["music"].returnState = "UNDERSCORE";
871 
872  }
873 
874  if ( self.team != "spectator" )
875  {
876  self thread ‪globallogic_audio::set_music_on_player( "spawnPreLoop" );
877  }
878 
879  if ( !isdefined( self.pers["cur_kill_streak"] ) )
880  {
881  self.pers["cur_kill_streak"] = 0;
882  }
883 
884  if ( !isdefined( self.pers["cur_total_kill_streak"] ) )
885  {
886  self.pers["cur_total_kill_streak"] = 0;
887  self setplayercurrentstreak( 0 );
888  }
889 
890  if ( !isdefined( self.pers["totalKillstreakCount"] ) )
891  self.pers["totalKillstreakCount"] = 0;
892 
893  //Keep track of how many killstreaks have been earned in the current streak
894  if ( !isdefined( self.pers["killstreaksEarnedThisKillstreak"] ) )
895  self.pers["killstreaksEarnedThisKillstreak"] = 0;
896 
897  if ( isdefined( level.usingScoreStreaks ) && level.usingScoreStreaks && !isdefined( self.pers["killstreak_quantity"] ) )
898  self.pers["killstreak_quantity"] = [];
899 
900  if ( isdefined( level.usingScoreStreaks ) && level.usingScoreStreaks && !isdefined( self.pers["held_killstreak_ammo_count"] ) )
901  self.pers["held_killstreak_ammo_count"] = [];
902 
903  if ( IsDefined( level.usingScoreStreaks ) && level.usingScoreStreaks && !IsDefined( self.pers["held_killstreak_clip_count"] ) )
904  self.pers["held_killstreak_clip_count"] = [];
905 
906  if( !isDefined( self.pers["changed_class"] ) )
907  self.pers["changed_class"] = false;
908 
909  if( !isDefined( self.pers["lastroundscore"] ) )
910  self.pers["lastroundscore"] = 0;
911 
912  self.lastKillTime = 0;
913 
914  self.cur_death_streak = 0;
915  self disabledeathstreak();
916  self.death_streak = 0;
917  self.kill_streak = 0;
918  self.gametype_kill_streak = 0;
919  self.spawnQueueIndex = -1;
920  self.deathTime = 0;
921 
922  self.aliveTimes = [];
923  for( index = 0; index < level.aliveTimeMaxCount; index++ )
924  {
925  self.aliveTimes[index] = 0;
926  }
927 
928  self.aliveTimeCurrentIndex = 0;
929 
930  if ( level.onlineGame && !‪IS_TRUE( level.freerun ) )
931  {
932  self.death_streak = self getDStat( "HighestStats", "death_streak" );
933  self.kill_streak = self getDStat( "HighestStats", "kill_streak" );
934  self.gametype_kill_streak = self ‪persistence::stat_get_with_gametype( "kill_streak" );
935  }
936 
937  self.lastGrenadeSuicideTime = -1;
938 
939  self.teamkillsThisRound = 0;
940 
941  if ( !isdefined( level.livesDoNotReset ) || !level.livesDoNotReset || !isdefined( self.pers["lives"] ) )
942  {
943  self.pers["lives"] = level.numLives;
944  }
945 
946  // multi round FFA games in custom game mode should maintain team in-between rounds
947  if ( !level.teamBased )
948  {
949  self.pers["team"] = undefined;
950  }
951 
952  self.hasSpawned = false;
953  self.waitingToSpawn = false;
954  self.wantSafeSpawn = false;
955  self.deathCount = 0;
956 
957  self.wasAliveAtMatchStart = false;
958 
959  level.players[level.players.size] = self;
960 
961  if( level.splitscreen )
962  SetDvar( "splitscreen_playerNum", level.players.size );
963 
964  if ( game["state"] == "postgame" )
965  {
966  self.pers["needteam"] = 1;
967  self.pers["team"] = "spectator";
968  self.team = self.sessionteam;
969 
970  self setClientUIVisibilityFlag( "hud_visible", 0 );
971 
972  self [[level.spawnIntermission]]();
973  self closeInGameMenu();
974  profilelog_endtiming( 4, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
975  return;
976  }
977 
978  // don't count losses for CTF and S&D and War at each round.
979  if ( ( level.rankedMatch || level.wagerMatch || level.leagueMatch ) && !isdefined( self.pers["lossAlreadyReported"] ) )
980  {
981  if ( level.leagueMatch )
982  {
983  self recordLeaguePreLoser();
984  }
985 
987 
988  self.pers["lossAlreadyReported"] = true;
989  }
990  if ((level.rankedMatch || level.leagueMatch) && !isDefined( self.pers["lateJoin"] ) )
991  {
992  if (game["state"] == "playing" && !level.inPrematchPeriod )
993  {
994  self.pers["lateJoin"] = true;
995  }
996  else
997  {
998  self.pers["lateJoin"] = false;
999  }
1000  }
1001 
1002  // don't redo winstreak save to pers array for each round of round based games.
1003  if ( !isdefined( self.pers["winstreakAlreadyCleared"] ) )
1004  {
1006  self.pers["winstreakAlreadyCleared"] = true;
1007  }
1008 
1009  if( self istestclient() )
1010  {
1011  self.pers[ "isBot" ] = true;
1012  recordPlayerStats( self, "isBot", true);
1013  }
1014 
1015  if ( level.rankedMatch || level.leagueMatch )
1016  {
1017  self ‪persistence::set_after_action_report_stat( "demoFileID", "0" );
1018  }
1019 
1020  level endon( "game_ended" );
1021 
1022  if ( isdefined( level.hostMigrationTimer ) )
1024 
1025  if ( isdefined( self.pers["team"] ) )
1026  self.team = self.pers["team"];
1027 
1028  if ( isdefined( self.pers["class"] ) )
1029  self.curClass = self.pers["class"];
1030 
1031  if ( !isdefined( self.pers["team"] ) || isdefined( self.pers["needteam"] ) )
1032  {
1033  // Don't set .sessionteam until we've gotten the assigned team from code,
1034  // because it overrides the assigned team.
1035  self.pers["needteam"] = undefined;
1036  self.pers["team"] = "spectator";
1037  self.team = "spectator";
1038  self.sessionstate = "dead";
1039 
1041 
1042  [[level.spawnSpectator]]();
1043 
1044  [[level.autoassign]]( false );
1045  if ( level.rankedMatch || level.leagueMatch )
1046  {
1048  }
1049 
1050  if ( self.pers["team"] == "spectator" )
1051  {
1052  self.sessionteam = "spectator";
1053  self thread ‪spectate_player_watcher();
1054  }
1055 
1056  if ( level.teamBased )
1057  {
1058  // set team and spectate permissions so the map shows waypoint info on connect
1059  self.sessionteam = self.pers["team"];
1060  if ( !isAlive( self ) )
1061  self.statusicon = "hud_status_dead";
1062  self thread ‪spectating::set_permissions();
1063  }
1064  }
1065  else if ( self.pers["team"] == "spectator" )
1066  {
1067  self SetClientScriptMainMenu( game[ "menu_start_menu" ] );
1068  [[level.spawnSpectator]]();
1069  self.sessionteam = "spectator";
1070  self.sessionstate = "spectator";
1071  self thread ‪spectate_player_watcher();
1072  }
1073  else
1074  {
1075  self.sessionteam = self.pers["team"];
1076  self.sessionstate = "dead";
1077 
1079 
1080  [[level.spawnSpectator]]();
1081 
1082  if ( ‪globallogic_utils::isValidClass( self.pers["class"] ) )
1083  {
1084  self thread [[level.spawnClient]]();
1085  }
1086  else
1087  {
1089  }
1090 
1091  self thread ‪spectating::set_permissions();
1092  }
1093 
1094  if ( self.sessionteam != "spectator" )
1095  {
1096  self thread ‪spawning::onSpawnPlayer(true);
1097  }
1098 
1099  if ( level.forceRadar == 1 ) // radar always sweeping
1100  {
1101  self.pers["hasRadar"] = true;
1102  self.hasSpyplane = true;
1103 
1104  if ( level.teambased )
1105  {
1106  level.activeUAVs[self.team]++;
1107  }
1108  else
1109  {
1110  level.activeUAVs[self getEntityNumber()]++;
1111  }
1112 
1113  level.activePlayerUAVs[self getEntityNumber()]++;
1114  }
1115 
1116  if ( level.forceRadar == 2 ) // radar constant
1117  {
1118  self setClientUIVisibilityFlag( "g_compassShowEnemies", level.forceRadar );
1119  }
1120  else
1121  {
1122  self SetClientUIVisibilityFlag( "g_compassShowEnemies", 0 );
1123  }
1124 
1125  profilelog_endtiming( 4, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
1126 
1127  if ( isdefined( self.pers["isBot"] ) )
1128  return;
1129 
1131 
1132  //T7 - moved from load_shared to make sure this doesn't get set on CP until level.players is ready
1133  num_con = getnumconnectedplayers();
1134  num_exp = getnumexpectedplayers();
1135  /#println( "all_players_connected(): getnumconnectedplayers=", num_con, "getnumexpectedplayers=", num_exp );#/
1136 
1137  if(num_con == num_exp && (num_exp != 0))
1138  {
1139  level ‪flag::set( "all_players_connected" );
1140  SetDvar( "all_players_are_connected", "1" );
1141  }
1142 
1144 }
1145 
1147 {
1148  if( isdefined( level.disableStatTracking ) && level.disableStatTracking == true )
1149  {
1150  return;
1151  }
1152 
1153  startKills = self GetDStat( "playerstatslist", "kills", "statValue" );
1154  startDeaths = self GetDStat( "playerstatslist", "deaths", "statValue" );
1155  startWins = self GetDStat( "playerstatslist", "wins", "statValue" );
1156  startLosses = self GetDStat( "playerstatslist", "losses", "statValue" );
1157  startHits = self GetDStat( "playerstatslist", "hits", "statValue" );
1158  startMisses = self GetDStat( "playerstatslist", "misses", "statValue" );
1159  startTimePlayedTotal = self GetDStat( "playerstatslist", "time_played_total", "statValue" );
1160  startScore = self GetDStat( "playerstatslist", "score", "statValue" );
1161  startPrestige = self GetDStat( "playerstatslist", "plevel", "statValue" );
1162  startUnlockPoints = self GetDStat( "unlocks", 0);
1163 
1164  ties = self GetDStat( "playerstatslist", "ties", "statValue" );
1165  startGamesPlayed = startWins + startLosses + ties;
1166 
1167  self.startKills = startKills;
1168  self.startHits = startHits;
1169  self.totalMatchShots = 0;
1170 
1171  recordPlayerStats( self, "startKills", startKills );
1172  recordPlayerStats( self, "startDeaths", startDeaths );
1173  recordPlayerStats( self, "startWins", startWins );
1174  recordPlayerStats( self, "startLosses", startLosses );
1175  recordPlayerStats( self, "startHits", startHits );
1176  recordPlayerStats( self, "startMisses", startMisses );
1177  recordPlayerStats( self, "startTimePlayedTotal", startTimePlayedTotal );
1178  recordPlayerStats( self, "startScore", startScore );
1179  recordPlayerStats( self, "startPrestige", startPrestige );
1180  recordPlayerStats( self, "startUnlockPoints", startUnlockPoints );
1181  recordPlayerStats( self, "startGamesPlayed", startGamesPlayed );
1182 
1183  // temp commenting out; the getdstat calls here fail
1184  lootXPBeforeMatch = self GetDStat( "AfterActionReportStats", "lootXPBeforeMatch" );
1185  cryptoKeysBeforeMatch = self GetDStat( "AfterActionReportStats", "cryptoKeysBeforeMatch" );
1186  recordPlayerStats( self, "lootXPBeforeMatch", lootXPBeforeMatch );
1187  recordPlayerStats( self, "cryptoKeysBeforeMatch", cryptoKeysBeforeMatch );
1188 
1189 }
1190 
1192 {
1193  if( isdefined( level.disableStatTracking ) && level.disableStatTracking == true )
1194  {
1195  return;
1196  }
1197 
1198  endKills = self GetDStat( "playerstatslist", "kills", "statValue" );
1199  endDeaths = self GetDStat( "playerstatslist", "deaths", "statValue" );
1200  endWins = self GetDStat( "playerstatslist", "wins", "statValue" );
1201  endLosses = self GetDStat( "playerstatslist", "losses", "statValue" );
1202  endHits = self GetDStat( "playerstatslist", "hits", "statValue" );
1203  endMisses = self GetDStat( "playerstatslist", "misses", "statValue" );
1204  endTimePlayedTotal = self GetDStat( "playerstatslist", "time_played_total", "statValue" );
1205  endScore = self GetDStat( "playerstatslist", "score", "statValue" );
1206  endPrestige = self GetDStat( "playerstatslist", "plevel", "statValue" );
1207  endUnlockPoints = self GetDStat( "unlocks", 0);
1208 
1209  ties = self GetDStat( "playerstatslist", "ties", "statValue" );
1210  endGamesPlayed = endWins + endLosses + ties;
1211 
1212  // note: xp_end - already exists - written in code - reads RANKXP
1213 
1214  recordPlayerStats( self, "endKills", endKills );
1215  recordPlayerStats( self, "endDeaths", endDeaths );
1216  recordPlayerStats( self, "endWins", endWins );
1217  recordPlayerStats( self, "endLosses", endLosses );
1218  recordPlayerStats( self, "endHits", endHits );
1219  recordPlayerStats( self, "endMisses", endMisses );
1220  recordPlayerStats( self, "endTimePlayedTotal", endTimePlayedTotal );
1221  recordPlayerStats( self, "endScore", endScore );
1222  recordPlayerStats( self, "endPrestige", endPrestige );
1223  recordPlayerStats( self, "endUnlockPoints", endUnlockPoints );
1224  recordPlayerStats( self, "endGamesPlayed", endGamesPlayed );
1225 
1226 }
1227 
1229 {
1230  if( isdefined( level.disableStatTracking ) && level.disableStatTracking == true )
1231  {
1232  return;
1233  }
1234 
1235  // common either for match end or on disconnect
1236  recordPlayerStats( self, "UTCEndTimeSeconds", getUTC() );
1237  if( isdefined( self.weaponPickupsCount ) )
1238  {
1239  recordPlayerStats( self, "weaponPickupsCount", self.weaponPickupsCount );
1240  }
1241  if( isdefined( self.killcamsSkipped) )
1242  {
1243  recordPlayerStats( self, "totalKillcamsSkipped", self.killcamsSkipped );
1244  }
1245  if( isdefined( self.matchBonus) )
1246  {
1247  recordPlayerStats( self, "matchXp", self.matchBonus );
1248  }
1249  if( isdefined( self.killsdenied ) )
1250  {
1251  recordPlayerStats( self, "killsDenied", self.killsdenied );
1252  }
1253  if( isdefined( self.killsconfirmed ) )
1254  {
1255  recordPlayerStats( self, "killsConfirmed", self.killsconfirmed );
1256  }
1257  if( self IsSplitscreen() )
1258  {
1259  recordPlayerStats( self, "isSplitscreen", true );
1260  }
1261  if( self.objtime )
1262  {
1263  recordPlayerStats( self, "objectiveTime", self.objtime );
1264  }
1265  if( self.escorts )
1266  {
1267  recordPlayerStats( self, "escortTime", self.escorts );
1268  }
1269 }
1270 
1272 {
1273  self endon( "disconnect" );
1274 
1275  // Setup the perks hud elem for the spectator if its not yet initalized
1276  // We have to do it here, since the perk hudelem is generally initalized only on spawn, and the spectator will not able able to
1277  // look at the perk loadout of some player.
1278  if ( !level.splitscreen && !level.hardcoreMode && GetDvarint( "scr_showperksonspawn" ) == 1 && game["state"] != "postgame" && !isdefined( self.perkHudelem ) )
1279  {
1280  if ( level.perksEnabled == 1 )
1281  {
1282  self ‪hud::showPerks( );
1283  }
1284  }
1285 
1286  self.watchingActiveClient = true;
1287  self.waitingForPlayersText = undefined;
1288 
1289  while ( 1 )
1290  {
1291  if ( self.pers["team"] != "spectator" || level.gameEnded )
1292  {
1294  if ( !‪IS_TRUE( level.inPrematchPeriod ) )
1295  {
1296  self FreezeControls( false );
1297  }
1298  self.watchingActiveClient = false;
1299  break;
1300  }
1301  else
1302  {
1303  count = 0;
1304  for ( i = 0; i < level.players.size; i++ )
1305  {
1306  if ( level.players[i].team != "spectator" )
1307  {
1308  count++;
1309  break;
1310  }
1311  }
1312 
1313  if ( count > 0 )
1314  {
1315  if ( !self.watchingActiveClient )
1316  {
1318  self FreezeControls( false );
1319 
1320  // Make sure that the player spawned notify happens when we start watching a player.
1321  self LUINotifyEvent( &"player_spawned", 0 );
1322  }
1323 
1324  self.watchingActiveClient = true;
1325  }
1326  else
1327  {
1328  if ( self.watchingActiveClient )
1329  {
1330  [[level.onSpawnSpectator]]();
1331  self FreezeControls( true );
1333  }
1334 
1335  self.watchingActiveClient = false;
1336  }
1337 
1338  wait( 0.5 );
1339  }
1340  }
1341 }
1342 
1344 {
1345 /# println( "Player " + self.‪name + " finished migrating at time " + gettime() ); #/
1346 
1347  if ( isdefined( self.connected ) && self.connected )
1348  {
1350  }
1351 
1352  level.hostMigrationReturnedPlayerCount++;
1353  if ( level.hostMigrationReturnedPlayerCount >= level.players.size * 2 / 3 )
1354  {
1355  /# println( "2/3 of players have finished migrating" ); #/
1356  level notify( "hostmigration_enoughplayers" );
1357  }
1358 }
1359 
1361 {
1362  profilelog_begintiming( 5, "ship" );
1363 
1364  if ( game["state"] != "postgame" && !level.gameEnded )
1365  {
1366  gameLength = game["timepassed"];
1367  self ‪globallogic::bbPlayerMatchEnd( gameLength, "MP_PLAYER_DISCONNECT", 0 );
1368 
1369  if( ‪util::isRoundBased() )
1370  {
1371  recordPlayerStats( self, "playerQuitRoundNumber", game["roundsplayed"] + 1 );
1372  }
1373 
1374  if( level.teambased )
1375  {
1376  ourTeam = self.team; // only expecting: "allies" or "axis"
1377  if( ourTeam == "allies" || ourTeam == "axis" )
1378  {
1379  theirTeam = "";
1380  if( ourTeam == "allies" )
1381  {
1382  theirTeam = "axis";
1383  }
1384  else if( ourTeam == "axis" )
1385  {
1386  theirTeam = "allies";
1387  }
1388  recordPlayerStats( self, "playerQuitTeamScore", getTeamScore( ourTeam ) );
1389  recordPlayerStats( self, "playerQuitOpposingTeamScore", getTeamScore( theirTeam ) );
1390  }
1391  }
1392 
1393  ‪recordEndGameComScoreEventForPlayer( self, "disconnect" );
1394 
1395  }
1396 
1398 
1399  ArrayRemoveValue( level.players, self );
1400 
1401  if ( level.splitscreen )
1402  {
1403  players = level.players;
1404 
1405  if ( players.size <= 1 )
1406  level thread ‪globallogic::forceEnd();
1407 
1408  // passing number of players to menus in splitscreen to display leave or end game option
1409  SetDvar( "splitscreen_playerNum", players.size );
1410  }
1411 
1412  if ( isdefined( self.score ) && isdefined( self.pers["team"] ) )
1413  {
1414  /#print( "team: score " + self.pers["team"] + ":" + self.score );#/
1415  level.dropTeam += 1;
1416  }
1417 
1418  [[level.onPlayerDisconnect]]();
1419 
1420  lpselfnum = self getEntityNumber();
1421  lpGuid = self getGuid();
1422  /#logPrint("Q;" + lpGuid + ";" + lpselfnum + ";" + self.‪name + "\n");#/
1423 
1425  self ‪record_special_move_data_for_life( undefined );
1426 
1428 
1430 
1431  for ( entry = 0; entry < level.players.size; entry++ )
1432  {
1433  if ( level.players[entry] == self )
1434  {
1435  while ( entry < level.players.size-1 )
1436  {
1437  level.players[entry] = level.players[entry+1];
1438  entry++;
1439  }
1440  level.players[entry] = undefined;
1441  break;
1442  }
1443  }
1444  for ( entry = 0; entry < level.players.size; entry++ )
1445  {
1446  if ( isdefined( level.players[entry].pers["killed_players"][self.name] ) )
1447  level.players[entry].pers["killed_players"][self.name] = undefined;
1448 
1449  if ( isdefined( level.players[entry].pers["killed_players_with_specialist"][self.name] ) )
1450  level.players[entry].pers["killed_players_with_specialist"][self.name] = undefined;
1451 
1452  if ( isdefined( level.players[entry].killedPlayersCurrent[self.name] ) )
1453  level.players[entry].killedPlayersCurrent[self.name] = undefined;
1454 
1455  if ( isdefined( level.players[entry].pers["killed_by"][self.name] ) )
1456  level.players[entry].pers["killed_by"][self.name] = undefined;
1457 
1458  if ( isdefined( level.players[entry].pers["nemesis_tracking"][self.name] ) )
1459  level.players[entry].pers["nemesis_tracking"][self.name] = undefined;
1460 
1461  // player that disconnected was our nemesis
1462  if ( level.players[entry].pers["nemesis_name"] == self.name )
1463  {
1464  level.players[entry] ‪chooseNextBestNemesis();
1465  }
1466  }
1467 
1468  if ( level.gameEnded )
1470 
1471  level thread ‪globallogic::updateTeamStatus();
1472  level thread ‪globallogic::updateAllAliveTimes();
1473 
1474  profilelog_endtiming( 5, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
1475 }
1476 
1477 function ‪Callback_PlayerMelee( eAttacker, iDamage, weapon, vOrigin, vDir, boneIndex, shieldHit, fromBehind )
1478 {
1479  hit = true;
1480 
1481  if ( level.teamBased && self.team == eAttacker.team )
1482  {
1483  if ( level.friendlyfire == 0 ) // no one takes damage
1484  {
1485  hit = false;
1486  }
1487  }
1488 
1489  self finishMeleeHit( eAttacker, weapon, vOrigin, vDir, boneIndex, shieldHit, hit, fromBehind );
1490 }
1491 
1493 {
1494  nemesisArray = self.pers["nemesis_tracking"];
1495  nemesisArrayKeys = getArrayKeys( nemesisArray );
1496  nemesisAmount = 0;
1497  nemesisName = "";
1498 
1499  if ( nemesisArrayKeys.size > 0 )
1500  {
1501  for ( i = 0; i < nemesisArrayKeys.size; i++ )
1502  {
1503  nemesisArrayKey = nemesisArrayKeys[i];
1504  if ( nemesisArray[nemesisArrayKey] > nemesisAmount )
1505  {
1506  nemesisName = nemesisArrayKey;
1507  nemesisAmount = nemesisArray[nemesisArrayKey];
1508  }
1509 
1510  }
1511  }
1512 
1513  self.pers["nemesis_name"] = nemesisName;
1514 
1515  if ( nemesisName != "" )
1516  {
1517  playerIndex = 0;
1518  for( ; playerIndex < level.players.size; playerIndex++ )
1519  {
1520  if ( level.players[playerIndex].name == nemesisName )
1521  {
1522  nemesisPlayer = level.players[playerIndex];
1523  self.pers["nemesis_rank"] = nemesisPlayer.pers["rank"];
1524  self.pers["nemesis_rankIcon"] = nemesisPlayer.pers["rankxp"];
1525  self.pers["nemesis_xp"] = nemesisPlayer.pers["prestige"];
1526  self.pers["nemesis_xuid"] = nemesisPlayer GetXUID();
1527  break;
1528  }
1529  }
1530  }
1531  else
1532  {
1533  self.pers["nemesis_xuid"] = "";
1534  }
1535 }
1536 
1537 function ‪custom_gamemodes_modified_damage( victim, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor, sHitLoc )
1538 {
1539  // regular public matches should early out
1540  if ( level.onlinegame && !SessionModeIsPrivate() )
1541  {
1542  return iDamage;
1543  }
1544 
1545  if( isdefined( eAttacker) && isdefined( eAttacker.damageModifier ) )
1546  {
1547  iDamage *= eAttacker.damageModifier;
1548  }
1549  if ( ( sMeansOfDeath == "MOD_PISTOL_BULLET" ) || ( sMeansOfDeath == "MOD_RIFLE_BULLET" ) )
1550  {
1551  iDamage = int( iDamage * level.bulletDamageScalar );
1552  }
1553 
1554  return iDamage;
1555 }
1556 
1557 function ‪figure_out_attacker( eAttacker )
1558 {
1559  if ( isdefined(eAttacker) )
1560  {
1561  if( isai(eAttacker) && isdefined( eAttacker.script_owner ) )
1562  {
1563  team = self.team;
1564 
1565  if ( eAttacker.script_owner.team != team )
1566  eAttacker = eAttacker.script_owner;
1567  }
1568 
1569  if( eAttacker.classname == "script_vehicle" && isdefined( eAttacker.owner ) )
1570  eAttacker = eAttacker.owner;
1571  else if( eAttacker.classname == "auto_turret" && isdefined( eAttacker.owner ) )
1572  eAttacker = eAttacker.owner;
1573  else if( eAttacker.classname == "actor_spawner_bo3_robot_grunt_assault_mp" && isdefined( eAttacker.owner ) )
1574  eAttacker = eAttacker.owner;
1575  }
1576 
1577  return eAttacker;
1578 }
1579 
1580 function ‪player_damage_figure_out_weapon( weapon, eInflictor )
1581 {
1582  // explosive barrel/car detection
1583  if ( weapon == level.weaponNone && isdefined( eInflictor ) )
1584  {
1585  if ( isdefined( eInflictor.targetname ) && eInflictor.targetname == "explodable_barrel" )
1586  {
1587  weapon = GetWeapon( "explodable_barrel" );
1588  }
1589  else if ( isdefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
1590  {
1591  weapon = GetWeapon( "destructible_car" );
1592  }
1593  else if( isdefined( eInflictor.scriptvehicletype ) )
1594  {
1595  veh_weapon = GetWeapon( eInflictor.scriptvehicletype );
1596  if( isdefined( veh_weapon ) )
1597  {
1598  weapon = veh_weapon;
1599  }
1600  }
1601  }
1602 
1603  if ( isdefined( eInflictor ) && isdefined( eInflictor.script_noteworthy ) )
1604  {
1605  if ( IsDefined( level.overrideWeaponFunc ) )
1606  {
1607  weapon = [[level.overrideWeaponFunc]]( weapon, eInflictor.script_noteworthy );
1608  }
1609  }
1610 
1611  return weapon;
1612 }
1613 
1615 {
1616  if ( level.hardcoreMode && level.friendlyfire > 0 && isdefined( victim ) && victim.is_capturing_own_supply_drop === true )
1617  {
1618  return 2; // FF 2 = reflect; design wants reflect friendly fire whenever a player is capturing their own supply drop
1619  }
1620 
1621  if ( ‪killstreaks::is_ricochet_protected( victim ) )
1622  {
1623  return 2;
1624  }
1625 
1626  // note, keep, non-gametype specific friendly fire logic above this line
1627 
1628  if ( isdefined( level.figure_out_gametype_friendly_fire ) )
1629  {
1630  return [[ level.figure_out_gametype_friendly_fire ]]( victim );
1631  }
1632 
1633  return level.friendlyfire;
1634 }
1635 
1636 function ‪isPlayerImmuneToKillstreak( eAttacker, weapon )
1637 {
1638  if ( level.hardcoreMode )
1639  return false;
1640 
1641  if ( !isdefined( eAttacker ) )
1642  return false;
1643 
1644  if ( self != eAttacker )
1645  return false;
1646 
1647  return weapon.doNotDamageOwner;
1648 }
1649 
1650 
1651 function ‪should_do_player_damage( eAttacker, weapon, sMeansOfDeath, iDFlags )
1652 {
1653  if ( game["state"] == "postgame" )
1654  return false;
1655 
1656  if ( self.sessionteam == "spectator" )
1657  return false;
1658 
1659  if ( isdefined( self.canDoCombat ) && !self.canDoCombat )
1660  return false;
1661 
1662  if ( isdefined( eAttacker ) && isPlayer( eAttacker ) && isdefined( eAttacker.canDoCombat ) && !eAttacker.canDoCombat )
1663  return false;
1664 
1665  if ( isdefined( level.hostMigrationTimer ) )
1666  return false;
1667 
1668  if ( level.onlyHeadShots )
1669  {
1670  if ( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" )
1671  return false;
1672  }
1673 
1674  // Make all vehicle drivers invulnerable to bullets
1675  if ( self ‪vehicle::player_is_occupant_invulnerable( sMeansOfDeath ) )
1676  return false;
1677 
1678  if ( weapon.isSupplyDropWeapon && !weapon.isGrenadeWeapon && ( smeansofdeath != "MOD_TRIGGER_HURT" ) )
1679  return false;
1680 
1681  if ( self.scene_takedamage === false )
1682  return false;
1683 
1684  // prevent spawn kill wall bangs
1685  if ( (iDFlags & ‪IDFLAGS_PENETRATION) && self ‪player::is_spawn_protected() )
1686  return false;
1687 
1688 return true;
1689 }
1690 
1691 function ‪apply_damage_to_armor( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, sHitLoc, friendlyFire, ignore_round_start_friendly_fire )
1692 {
1693  victim = self;
1694 
1695  if ( friendlyFire && !‪player_damage_does_friendly_fire_damage_victim( ignore_round_start_friendly_fire ) )
1696  return iDamage;
1697 
1698  // Handle armor damage
1699  if( IsDefined( victim.lightArmorHP ) )
1700  {
1701  if ( weapon.ignoresLightArmor && sMeansOfDeath != "MOD_MELEE" )
1702  {
1703  return iDamage;
1704  }
1705  else if ( weapon.meleeIgnoresLightArmor && sMeansOfDeath == "MOD_MELEE" )
1706  {
1707  return iDamage;
1708  }
1709  // anything stuck to the player does health damage
1710  else if( IsDefined( eInflictor ) && IsDefined( eInflictor.stuckToPlayer ) && eInflictor.stuckToPlayer == victim )
1711  {
1712  iDamage = victim.health;
1713  }
1714  else
1715  {
1716  // Handle Armor Damage
1717  // no armor damage in case of falling, melee, fmj or head shots
1718  if ( sMeansOfDeath != "MOD_FALLING"
1719  && !‪weapon_utils::isMeleeMOD( sMeansOfDeath )
1720  && !‪globallogic_utils::isHeadShot( weapon, sHitLoc, sMeansOfDeath, eAttacker )
1721  )
1722  {
1723  victim ‪armor::setLightArmorHP( victim.lightArmorHP - ( iDamage ) );
1724 
1725  iDamage = 0;
1726  if ( victim.lightArmorHP <= 0 )
1727  {
1728  // since the light armor is gone, adjust the damage to be the excess damage that happens after the light armor hp is reduced
1729  iDamage = abs( victim.lightArmorHP );
1731  }
1732  }
1733  }
1734  }
1735 
1736  return iDamage;
1737 }
1738 
1740 {
1741  // Make sure at least one point of damage is done & give back 1 health because of this if you have power armor
1742  if ( iDamage < 1 )
1743  {
1744  if( ( self ‪ability_util::gadget_power_armor_on() ) && isDefined( self.maxHealth ) && ( self.health < self.maxHealth ) )
1745  {
1746  self.health += 1;
1747  }
1748  iDamage = 1;
1749  }
1750 
1751  return int(iDamage);
1752 }
1753 
1755 {
1756  friendlyfire = [[ level.figure_out_friendly_fire ]]( self );
1757 
1758  // half damage
1759  if ( friendlyfire == 2 || friendlyfire == 3 )
1760  {
1761  iDamage = int(iDamage * .5);
1762  }
1763 
1764  return iDamage;
1765 }
1766 
1767 function ‪modify_player_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
1768 {
1769  if ( isdefined( self.overridePlayerDamage ) )
1770  {
1771  iDamage = self [[self.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
1772  }
1773  else if ( isdefined( level.overridePlayerDamage ) )
1774  {
1775  iDamage = self [[level.overridePlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
1776  }
1777 
1778  assert(isdefined(iDamage), "You must return a value from a damage override function.");
1779 
1780  if ( isdefined( eAttacker ) )
1781  {
1782  iDamage = ‪loadout::cac_modified_damage( self, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor, sHitLoc );
1783 
1784  if( isdefined( eAttacker.pickup_damage_scale ) && eAttacker.pickup_damage_scale_time > GetTime() )
1785  {
1786  iDamage = iDamage * eAttacker.pickup_damage_scale;
1787  }
1788  }
1789  iDamage = ‪custom_gamemodes_modified_damage( self, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor, sHitLoc );
1790 
1791  if ( level.onPlayerDamage != &‪globallogic::blank )
1792  {
1793  modifiedDamage = [[level.onPlayerDamage]]( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime );
1794 
1795  if ( isdefined( modifiedDamage ) )
1796  {
1797  if ( modifiedDamage <= 0 )
1798  return;
1799 
1800  iDamage = modifiedDamage;
1801  }
1802  }
1803 
1804  if ( level.onlyHeadShots )
1805  {
1806  if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
1807  iDamage = 150;
1808  }
1809 
1810  if ( weapon.damageAlwaysKillsPlayer )
1811  {
1812  iDamage = self.maxHealth + 1;
1813  }
1814 
1815  if ( sHitLoc == "riotshield" )
1816  {
1817  if ( iDFlags & ‪IDFLAGS_SHIELD_EXPLOSIVE_IMPACT )
1818  {
1819  if ( !(iDFlags & ‪IDFLAGS_SHIELD_EXPLOSIVE_IMPACT_HUGE) )
1820  {
1821  iDamage *= 0.0;
1822  }
1823  }
1824  else if ( iDFlags & ‪IDFLAGS_SHIELD_EXPLOSIVE_SPLASH )
1825  {
1826  if ( isdefined( eInflictor ) && isdefined( eInflictor.stuckToPlayer ) && eInflictor.stuckToPlayer == self )
1827  {
1828  //does enough damage to shield carrier to ensure death
1829  iDamage = self.maxhealth + 1;
1830  }
1831  }
1832  }
1833 
1834  return int(iDamage);
1835 }
1836 
1837 function ‪modify_player_damage_meansofdeath( eInflictor, eAttacker, sMeansOfDeath, weapon, sHitLoc )
1838 {
1839  if ( ‪globallogic_utils::isHeadShot( weapon, sHitLoc, sMeansOfDeath, eInflictor ) && isPlayer(eAttacker) && !weapon_utils::ismeleemod( sMeansOfDeath ) )
1840  {
1841  sMeansOfDeath = "MOD_HEAD_SHOT";
1842  }
1843 
1844  if ( isdefined( eInflictor ) && isdefined( eInflictor.script_noteworthy ) )
1845  {
1846  if ( eInflictor.script_noteworthy == "ragdoll_now" )
1847  {
1848  sMeansOfDeath = "MOD_FALLING";
1849  }
1850  }
1851 
1852  return sMeansOfDeath;
1853 }
1854 
1855 function ‪player_damage_update_attacker( eInflictor, eAttacker, sMeansOfDeath )
1856 {
1857  if ( isdefined( eInflictor ) && isPlayer( eAttacker ) && eAttacker == eInflictor )
1858  {
1859  if ( sMeansOfDeath == "MOD_HEAD_SHOT" || sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" )
1860  {
1861  //if ( isPlayer( eAttacker ) ) already tested for above
1862  {
1863  eAttacker.hits++;
1864  }
1865  }
1866  }
1867 
1868  if ( isPlayer( eAttacker ) )
1869  eAttacker.pers["participation"]++;
1870 }
1871 
1872 function ‪player_is_spawn_protected_from_explosive( eInflictor, weapon, sMeansOfDeath )
1873 {
1874  if ( !self ‪player::is_spawn_protected() )
1875  return false;
1876 
1877  // if we are using this as a impact damage only projectile then no protection
1878  // we should probably add a bool to the weapon to indicate that it spawn protects
1879  if ( weapon.explosionradius == 0 )
1880  return false;
1881 
1882  distSqr = ( ( isdefined( eInflictor ) && isdefined( self.lastSpawnPoint ) ) ? DistanceSquared( eInflictor.origin, self.lastSpawnPoint.origin ) : 0 );
1883 
1884  // protect players from spawnkill grenades, tabun and incendiary
1885  if ( distSqr < ‪SQR( 250 ) )
1886  {
1887  if ( sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" )
1888  {
1889  return true;
1890  }
1891 
1892  if ( sMeansOfDeath == "MOD_PROJECTILE" || sMeansOfDeath == "MOD_PROJECTILE_SPLASH" )
1893  {
1894  return true;
1895  }
1896 
1897  if ( sMeansOfDeath == "MOD_EXPLOSIVE" )
1898  {
1899  return true;
1900  }
1901  }
1902 
1903  if ( ‪killstreaks::is_killstreak_weapon( weapon ) )
1904  {
1905  return true;
1906  }
1907 
1908  return false;
1909 }
1910 
1911 function ‪player_damage_update_explosive_info( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
1912 {
1914 
1915  if ( ‪is_explosive_damage )
1916  {
1917  // protect players from spawnkill grenades, tabun, incendiaries, and scorestreaks
1918  if ( self ‪player_is_spawn_protected_from_explosive( eInflictor, weapon, sMeansOfDeath ) )
1919  {
1920  return false;
1921  }
1922 
1923  // protect players from their own non-player controlled killstreaks
1924  if ( self ‪isPlayerImmuneToKillstreak( eAttacker, weapon ) )
1925  {
1926  return false;
1927  }
1928  }
1929 
1930  if ( isdefined( eInflictor ) && ( sMeansOfDeath == "MOD_GAS" || ‪is_explosive_damage ) )
1931  {
1932  self.explosiveInfo = [];
1933  self.explosiveInfo["damageTime"] = getTime();
1934  self.explosiveInfo["damageId"] = eInflictor getEntityNumber();
1935  self.explosiveInfo["originalOwnerKill"] = false;
1936  self.explosiveInfo["bulletPenetrationKill"] = false;
1937  self.explosiveInfo["chainKill"] = false;
1938  self.explosiveInfo["damageExplosiveKill"] = false;
1939  self.explosiveInfo["chainKill"] = false;
1940  self.explosiveInfo["cookedKill"] = false;
1941  self.explosiveInfo["weapon"] = weapon;
1942  self.explosiveInfo["originalowner"] = eInflictor.originalowner;
1943 
1944  isFrag = ( weapon.rootweapon.name == "frag_grenade" );
1945 
1946  if ( isdefined( eAttacker ) && eAttacker != self )
1947  {
1948  if ( isdefined( eAttacker ) && isdefined( eInflictor.owner ) && (weapon.name == "satchel_charge" || weapon.name == "claymore" || weapon.name == "bouncingbetty") )
1949  {
1950  self.explosiveInfo["originalOwnerKill"] = (eInflictor.owner == self);
1951  self.explosiveInfo["damageExplosiveKill"] = isdefined( eInflictor.wasDamaged );
1952  self.explosiveInfo["chainKill"] = isdefined( eInflictor.wasChained );
1953  self.explosiveInfo["wasJustPlanted"] = isdefined( eInflictor.wasJustPlanted );
1954  self.explosiveInfo["bulletPenetrationKill"] = isdefined( eInflictor.wasDamagedFromBulletPenetration );
1955  self.explosiveInfo["cookedKill"] = false;
1956  }
1957  if ( isdefined( eInflictor ) && isdefined( eInflictor.stuckToPlayer ) && weapon.projExplosionType == "grenade" )
1958  {
1959  self.explosiveInfo["stuckToPlayer"] = eInflictor.stuckToPlayer;
1960  }
1961  if ( weapon.doStun )
1962  {
1963  self.lastStunnedBy = eAttacker;
1964  self.lastStunnedTime = self.iDFlagsTime;
1965  }
1966  if ( isdefined( eAttacker.lastGrenadeSuicideTime ) && eAttacker.lastGrenadeSuicideTime >= gettime() - 50 && isFrag )
1967  {
1968  self.explosiveInfo["suicideGrenadeKill"] = true;
1969  }
1970  else
1971  {
1972  self.explosiveInfo["suicideGrenadeKill"] = false;
1973  }
1974  }
1975 
1976  if ( isFrag )
1977  {
1978  self.explosiveInfo["cookedKill"] = isdefined( eInflictor.isCooked );
1979  self.explosiveInfo["throwbackKill"] = isdefined( eInflictor.threwBack );
1980  }
1981 
1982  if( isdefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker != self )
1983  {
1984  self ‪globallogic_score::setInflictorStat( eInflictor, eAttacker, weapon );
1985  }
1986  }
1987 
1988  if( sMeansOfDeath == "MOD_IMPACT" && isdefined( eAttacker ) && isPlayer( eAttacker ) && eAttacker != self )
1989  {
1990  if ( weapon != level.weaponBallisticKnife )
1991  {
1992  self ‪globallogic_score::setInflictorStat( eInflictor, eAttacker, weapon );
1993  }
1994 
1995  if ( weapon.rootweapon.name == "hatchet" && isdefined( eInflictor ) )
1996  {
1997  self.explosiveInfo["projectile_bounced"] = isdefined( eInflictor.bounced );
1998  }
1999  }
2000 
2001  return true;
2002 }
2003 
2005 {
2006  //check for friendly fire at the begining of the match. apply the damage to the attacker only
2007  if( level.friendlyFireDelay && level.friendlyFireDelayTime >= ( ( ( gettime() - level.startTime ) - level.discardTime ) / 1000 ) )
2008  {
2009  return true;
2010  }
2011 
2012  return false;
2013 }
2014 
2015 function ‪player_damage_does_friendly_fire_damage_attacker( eAttacker, ignore_round_start_friendly_fire )
2016 {
2017  if ( !IsAlive( eAttacker ) )
2018  return false;
2019 
2020  friendlyfire = [[ level.figure_out_friendly_fire ]]( self );
2021 
2022  if ( friendlyfire == 1 ) // the friendly takes damage
2023  {
2024  //check for friendly fire at the begining of the match. apply the damage to the attacker only
2025  if ( ‪player_damage_is_friendly_fire_at_round_start() && ( ignore_round_start_friendly_fire == false ) )
2026  {
2027  return true;
2028  }
2029  }
2030 
2031  if ( friendlyfire == 2 ) // only the attacker takes damage
2032  {
2033  return true;
2034  }
2035 
2036  if ( friendlyfire == 3 ) // both friendly and attacker take damage
2037  {
2038  return true;
2039  }
2040 
2041  return false;
2042 }
2043 
2044 function ‪player_damage_does_friendly_fire_damage_victim( ignore_round_start_friendly_fire )
2045 {
2046  friendlyfire = [[ level.figure_out_friendly_fire ]]( self );
2047 
2048  if ( friendlyfire == 1 ) // the friendly takes damage
2049  {
2050  //check for friendly fire at the begining of the match. apply the damage to the attacker only
2051  if ( ‪player_damage_is_friendly_fire_at_round_start() && ( ignore_round_start_friendly_fire == false ) )
2052  {
2053  return false;
2054  }
2055 
2056  return true;
2057  }
2058 
2059  if ( friendlyfire == 3 ) // both friendly and attacker take damage
2060  {
2061  return true;
2062  }
2063 
2064  return false;
2065 }
2066 
2067 function ‪player_damage_riotshield_hit( eAttacker, iDamage, sMeansOfDeath, weapon, attackerIsHittingTeammate)
2068 {
2069  if (( sMeansOfDeath == "MOD_PISTOL_BULLET" || sMeansOfDeath == "MOD_RIFLE_BULLET" ) &&
2070  ( !‪killstreaks::is_killstreak_weapon( weapon )) &&
2071  ( !attackerIsHittingTeammate ) )
2072  {
2073  if ( self.hasRiotShieldEquipped )
2074  {
2075  if ( isPlayer( eAttacker ))
2076  {
2077  eAttacker.lastAttackedShieldPlayer = self;
2078  eAttacker.lastAttackedShieldTime = getTime();
2079  }
2080 
2081  previous_shield_damage = self.shieldDamageBlocked;
2082  self.shieldDamageBlocked += iDamage;
2083 
2084  if (( self.shieldDamageBlocked % 400 /*riotshield_damage_score_threshold*/ ) < ( previous_shield_damage % 400 /*riotshield_damage_score_threshold*/ ))
2085  {
2086  score_event = "shield_blocked_damage";
2087 
2088  if (( self.shieldDamageBlocked > 2000 /*riotshield_damage_score_max*/ ))
2089  {
2090  score_event = "shield_blocked_damage_reduced";
2091  }
2092 
2093  if ( isdefined( level.scoreInfo[ score_event ]["value"] ) )
2094  {
2095  // need to get the actual riot shield weapon here
2096  self AddWeaponStat( level.weaponRiotshield, "score_from_blocked_damage", level.scoreInfo[ score_event ]["value"] );
2097  }
2098 
2099  ‪scoreevents::processScoreEvent( score_event, self );
2100  }
2101  }
2102  }
2103 
2104 }
2105 
2106 function ‪does_player_completely_avoid_damage(iDFlags, sHitLoc, weapon, friendlyFire, attackerIsHittingSelf, sMeansOfDeath )
2107 {
2108  if( iDFlags & ‪IDFLAGS_NO_PROTECTION )
2109  return true;
2110 
2111  if ( friendlyFire && level.friendlyfire == 0 )
2112  return true;
2113 
2114  if ( sHitLoc == "riotshield" )
2115  {
2117  return true;
2118  }
2119 
2120 
2121  if( weapon.isEmp && sMeansOfDeath == "MOD_GRENADE_SPLASH" )
2122  {
2123  if( self hasperk("specialty_immuneemp") )
2124  return true;
2125  }
2126 
2127 
2128  return false;
2129 }
2130 
2131 function ‪player_damage_log( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex )
2132 {
2133  if(self.sessionstate != "dead")
2134  {
2135  lpselfnum = self getEntityNumber();
2136  lpselfname = self.name;
2137  lpselfteam = self.team;
2138  lpselfGuid = self getGuid();
2139  lpattackerteam = "";
2140  lpattackerorigin = ( 0, 0, 0 );
2141 
2142  if(isPlayer(eAttacker))
2143  {
2144  lpattacknum = eAttacker getEntityNumber();
2145  lpattackGuid = eAttacker getGuid();
2146  lpattackname = eAttacker.name;
2147  lpattackerteam = eAttacker.team;
2148  lpattackerorigin = eAttacker.origin;
2149  isusingheropower = 0;
2150 
2151  if ( eAttacker ‪ability_player::is_using_any_gadget() )
2152  isusingheropower = 1;
2153 
2154  }
2155  else
2156  {
2157  lpattacknum = -1;
2158  lpattackGuid = "";
2159  lpattackname = "";
2160  lpattackerteam = "world";
2161  }
2162  /#logPrint("D;" + lpselfGuid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackGuid + ";" + lpattacknum + ";" + lpattackerteam + ";" + lpattackname + ";" + weapon.name + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n");#/
2163  }
2164 }
2165 
2166 function ‪should_allow_postgame_damage( sMeansOfDeath )
2167 {
2168  if ( sMeansOfDeath == "MOD_TRIGGER_HURT" || sMeansOfDeath == "MOD_CRUSH" )
2169  return true;
2170 
2171  return false;
2172 }
2173 
2174 function ‪do_post_game_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
2175 {
2176  if ( game["state"] != "postgame" )
2177  return;
2178 
2179  if ( !‪should_allow_postgame_damage( sMeansOfDeath ) )
2180  return;
2181 
2182  // just pass it along
2183  self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, "MOD_POST_GAME", weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
2184 }
2185 
2186 function ‪Callback_PlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
2187 {
2188  profilelog_begintiming( 6, "ship" );
2189 
2190  ‪do_post_game_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
2191 
2192  if ( sMeansOfDeath == "MOD_CRUSH" && isdefined( eInflictor ) && ( eInflictor.deal_no_crush_damage === true ) )
2193  {
2194  return;
2195  }
2196 
2197  if ( isdefined( eInflictor ) && eInflictor.killstreakType === "siegebot" )
2198  {
2199  if ( eInflictor.team === "neutral" )
2200  return;
2201  }
2202 
2203  self.iDFlags = iDFlags;
2204  self.iDFlagsTime = getTime();
2205 
2206  // determine if we should treat owner damage as friendly fire
2207  if ( !IsPlayer( eAttacker ) && isdefined( eAttacker ) && eAttacker.owner === self )
2208  {
2209  treat_self_damage_as_friendly_fire = eAttacker.treat_owner_damage_as_friendly_fire;
2210  }
2211 
2212  // determine if we should ignore_round_start_friendly_fire
2213  ignore_round_start_friendly_fire = ( isdefined( eInflictor ) && ( sMeansOfDeath == "MOD_CRUSH" ) || sMeansOfDeath == "MOD_HIT_BY_OBJECT" );
2214 
2215  eAttacker = ‪figure_out_attacker( eAttacker );
2216 
2217  // no damage from people who have dropped into laststand
2218  if ( IsPlayer( eAttacker ) && ‪IS_TRUE( eAttacker.laststand ) )
2219  {
2220  return;
2221  }
2222 
2223  sMeansOfDeath = ‪modify_player_damage_meansofdeath( eInflictor, eAttacker, sMeansOfDeath, weapon, sHitLoc );
2224 
2225  if ( !(self ‪should_do_player_damage( eAttacker, weapon, sMeansOfDeath, iDFlags )) )
2226  return;
2227 
2228  ‪player_damage_update_attacker( eInflictor, eAttacker, sMeansOfDeath );
2229 
2230  weapon = ‪player_damage_figure_out_weapon( weapon, eInflictor );
2231 
2232  // Don't do knockback if the damage direction was not specified
2233  if( !isdefined( vDir ) )
2234  iDFlags |= ‪IDFLAGS_NO_KNOCKBACK;
2235 
2236  attackerIsHittingTeammate = isPlayer( eAttacker ) && ( self ‪util::IsEnemyPlayer( eAttacker ) == false );
2237  attackerIsHittingSelf = IsPlayer( eAttacker ) && (self == eAttacker);
2238 
2239  friendlyFire = ( ( attackerIsHittingSelf && treat_self_damage_as_friendly_fire === true ) // some killstreaks treak owner damage as friendly-fire
2240  || ( level.teamBased && !attackerIsHittingSelf && attackerIsHittingTeammate ) ); // teammates are always friendly-fire, but self is handled above
2241 
2242  iDamage = ‪modify_player_damage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
2243  if ( friendlyFire )
2244  {
2245  iDamage = ‪modify_player_damage_friendlyfire( iDamage );
2246  }
2247 
2248  if( ‪IS_TRUE( self.power_armor_took_damage ) )
2249  {
2250  iDFlags |= ‪IDFLAGS_POWER_ARMOR;
2251  }
2252 
2253  if ( sHitLoc == "riotshield" )
2254  {
2255  // do we want all of the damage modifiers that get applied for the player to get applied to this damage?
2256  // or friendly fire?
2257  ‪player_damage_riotshield_hit( eAttacker, iDamage, sMeansOfDeath, weapon, attackerIsHittingTeammate);
2258  }
2259 
2260  // check for completely getting out of the damage
2261  if ( self ‪does_player_completely_avoid_damage(iDFlags, sHitLoc, weapon, friendlyFire, attackerIsHittingSelf, sMeansOfDeath ) )
2262  {
2263  return;
2264  }
2265 
2266  // do we want this called pre or post damage application?
2267  self ‪callback::callback( #"on_player_damage" );
2268 
2269  armor = self ‪armor::getArmor();
2270 
2271  iDamage = ‪apply_damage_to_armor( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, sHitLoc, friendlyFire, ignore_round_start_friendly_fire );
2272  iDamage = ‪make_sure_damage_is_not_zero( iDamage );
2273 
2274  armor_damaged = (armor != self ‪armor::getArmor());
2275 
2276  // this must be below the damage modification functions as they use this to determine riotshield hits
2277  if ( sHitLoc == "riotshield" )
2278  {
2279  sHitLoc = "none"; // code ignores any damage to a "shield" bodypart.
2280  }
2281 
2282  if ( !‪player_damage_update_explosive_info( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex ) )
2283  return;
2284 
2285  prevHealthRatio = self.health / self.maxhealth;
2286 
2287  if ( friendlyFire )
2288  {
2289  if ( ‪player_damage_does_friendly_fire_damage_victim( ignore_round_start_friendly_fire ) )
2290  {
2291  self.lastDamageWasFromEnemy = false;
2292 
2293  self ‪finishPlayerDamageWrapper(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal);
2294  }
2295  else if ( weapon.forceDamageShellshockAndRumble )
2296  {
2297  self ‪damageShellshockAndRumble( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
2298  }
2299 
2300  if ( ‪player_damage_does_friendly_fire_damage_attacker( eAttacker, ignore_round_start_friendly_fire ) )
2301  {
2302  eAttacker.lastDamageWasFromEnemy = false;
2303 
2304  eAttacker.friendlydamage = true;
2305  eAttacker ‪finishPlayerDamageWrapper(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal);
2306  eAttacker.friendlydamage = undefined;
2307  }
2308  }
2309  else
2310  {
2311  ‪behaviorTracker::UpdatePlayerDamage( eAttacker, self, iDamage );
2312 
2313  self.lastAttackWeapon = weapon;
2314 
2315  ‪giveAttackerAndInflictorOwnerAssist( eAttacker, eInflictor, iDamage, sMeansOfDeath, weapon );
2316 
2317  if ( isdefined( eAttacker ) )
2318  level.lastLegitimateAttacker = eAttacker;
2319 
2320  if ( ( sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_GRENADE_SPLASH" ) && isdefined( eInflictor ) && isdefined( eInflictor.isCooked ) )
2321  self.wasCooked = getTime();
2322  else
2323  self.wasCooked = undefined;
2324 
2325  self.lastDamageWasFromEnemy = (isdefined( eAttacker ) && (eAttacker != self));
2326 
2327  if ( self.lastDamageWasFromEnemy )
2328  {
2329  if ( isplayer( eAttacker ) )
2330  {
2331  if ( isdefined ( eAttacker.damagedPlayers[ self.clientId ] ) == false )
2332  eAttacker.damagedPlayers[ self.clientId ] = spawnstruct();
2333 
2334  eAttacker.damagedPlayers[ self.clientId ].time = getTime();
2335  eAttacker.damagedPlayers[ self.clientId ].entity = self;
2336  }
2337  }
2338 
2339  if( isPlayer( eAttacker ) && isDefined(weapon.gadget_type) && weapon.gadget_type == ‪GADGET_TYPE_HERO_WEAPON )
2340  {
2341  if( isDefined(eAttacker.heroweaponHits) )
2342  {
2343  eAttacker.heroweaponHits++;
2344  }
2345  }
2346 
2347  self ‪finishPlayerDamageWrapper(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal);
2348  }
2349 
2350  if ( isdefined( eAttacker ) && !attackerIsHittingSelf )
2351  {
2352  if ( ‪damagefeedback::doDamageFeedback( weapon, eInflictor, iDamage, sMeansOfDeath ) )
2353  {
2354  // the perk feedback should be shown only if the enemy is damaged and not killed.
2355  if ( iDamage > 0 && self.health > 0 )
2356  {
2357  perkFeedback = ‪doPerkFeedBack( self, weapon, sMeansOfDeath, eInflictor, armor_damaged );
2358  }
2359 
2360  eAttacker thread ‪damagefeedback::update( sMeansOfDeath, eInflictor, perkFeedback, weapon, self, psOffsetTime, sHitLoc );
2361  }
2362  }
2363 
2364  if( !isdefined(eAttacker) || !friendlyFire || ‪IS_TRUE( level.hardcoreMode ) )
2365  {
2366  self ‪battlechatter::pain_vox( sMeansOfDeath );
2367  }
2368 
2369  self.hasDoneCombat = true;
2370 
2371  if( weapon.isEmp && sMeansOfDeath == "MOD_GRENADE_SPLASH" )
2372  {
2373  if( !self hasperk("specialty_immuneemp") )
2374  {
2375  self notify( "emp_grenaded", eAttacker, vPoint );
2376  }
2377  }
2378 
2379  if ( isdefined( eAttacker ) && eAttacker != self && !friendlyFire )
2380  level.useStartSpawns = false;
2381 
2382  ‪player_damage_log( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex );
2383 
2384  profilelog_endtiming( 6, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
2385 }
2386 
2388 {
2389  self.attackers = [];
2390  self.attackerData = [];
2391  self.attackerDamage = [];
2392  self.firstTimeDamaged = 0;
2393 }
2394 
2396 {
2397  self.attackersThisSpawn = [];
2398 }
2399 
2400 function ‪doPerkFeedBack( player, weapon, sMeansOfDeath, eInflictor, armor_damaged )
2401 {
2402  perkFeedback = undefined;
2404  hasFlakJacket = ( player HasPerk( "specialty_flakjacket" ) );
2407 
2409  {
2410  perkFeedback = "tacticalMask";
2411  }
2412  else if ( player HasPerk( "specialty_fireproof" ) && ‪loadout::isFireDamage( weapon, sMeansOfDeath ) )
2413  {
2414  perkFeedback = "flakjacket";
2415  }
2416  else if ( ‪isExplosiveDamage && hasFlakJacket && !weapon.ignoresFlakJacket && ( !‪isAIKillstreakDamage( weapon, eInflictor ) ) )
2417  {
2418  perkFeedback = "flakjacket";
2419  }
2420  else if ( armor_damaged )
2421  {
2422  perkFeedback = "armor";
2423  }
2424 
2425  return perkFeedback;
2426 }
2427 
2428 function ‪isAIKillstreakDamage( weapon, eInflictor )
2429 {
2430  if ( weapon.isAIKillstreakDamage )
2431  {
2432  if ( weapon.name != "ai_tank_drone_rocket" || isdefined( eInflictor.firedByAI ) )
2433  {
2434  return true;
2435  }
2436  }
2437 
2438  return false;
2439 }
2440 
2441 function ‪finishPlayerDamageWrapper( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal )
2442 {
2443  if( !level.console && iDFlags & ‪IDFLAGS_PENETRATION && isplayer ( eAttacker ) )
2444  {
2445  /#
2446  println("penetrated:" + self getEntityNumber() + " health:" + self.health + " attacker:" + eAttacker.clientid + " inflictor is player:" + isPlayer(eInflictor) + " damage:" + iDamage + " hitLoc:" + sHitLoc);
2447  #/
2448  eAttacker AddPlayerStat( "penetration_shots", 1 );
2449  }
2450 
2451  if ( GetDvarString( "scr_csmode" ) != "" )
2452  self shellShock( "damage_mp", 0.2 );
2453 
2454  self ‪damageShellshockAndRumble( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
2455 
2456  self ‪ability_power::power_loss_event_took_damage( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
2457 
2458  if( isPlayer( eAttacker) )
2459  {
2460  self.lastShotBy = eAttacker.clientid;
2461  }
2462 
2463  if ( sMeansOfDeath == "MOD_BURNED" )
2464  {
2465  self ‪burnplayer::TakingBurnDamage( eAttacker, weapon, sMeansOfDeath );
2466  }
2467 
2468  self.gadget_was_active_last_damage = self GadgetIsActive( 0 );
2469 
2470  self finishPlayerDamage( eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal );
2471 }
2472 
2473 function ‪allowedAssistWeapon( weapon )
2474 {
2475  if ( !‪killstreaks::is_killstreak_weapon( weapon ) )
2476  return true;
2477 
2479  return true;
2480 
2481  return false;
2482 }
2483 
2484 function ‪PlayerKilled_Killstreaks( attacker, weapon )
2485 {
2486  if( !isdefined( self.switching_teams ) )
2487  {
2488  // if team killed we reset kill streak, but dont count death and death streak
2489  if ( isPlayer( attacker ) && level.teamBased && ( attacker != self ) && ( self.team == attacker.team ) )
2490  {
2491 
2492  self.pers["cur_kill_streak"] = 0;
2493  self.pers["cur_total_kill_streak"] = 0;
2494  self.pers["totalKillstreakCount"] = 0;
2495  self.pers["killstreaksEarnedThisKillstreak"] = 0;
2496  self setplayercurrentstreak( 0 );
2497  }
2498  else
2499  {
2500  self ‪globallogic_score::incPersStat( "deaths", 1, true, true );
2501  self.deaths = self ‪globallogic_score::getPersStat( "deaths" );
2502  self UpdateStatRatio( "kdratio", "kills", "deaths" );
2503 
2504  if( self.pers["cur_kill_streak"] > self.pers["best_kill_streak"] )
2505  self.pers["best_kill_streak"] = self.pers["cur_kill_streak"];
2506 
2507  // need to keep the current killstreak to see if this was a buzzkill later
2508  self.pers["kill_streak_before_death"] = self.pers["cur_kill_streak"];
2509 
2510 
2511  self.pers["cur_kill_streak"] = 0;
2512  self.pers["cur_total_kill_streak"] = 0;
2513  self.pers["totalKillstreakCount"] = 0;
2514  self.pers["killstreaksEarnedThisKillstreak"] = 0;
2515  self setplayercurrentstreak( 0 );
2516 
2517  self.cur_death_streak++;
2518 
2519  if ( self.cur_death_streak > self.death_streak )
2520  {
2521  if ( level.rankedMatch && !level.disableStatTracking )
2522  {
2523  self setDStat( "HighestStats", "death_streak", self.cur_death_streak );
2524  }
2525  self.death_streak = self.cur_death_streak;
2526  }
2527 
2528  if( self.cur_death_streak >= GetDvarint( "perk_deathStreakCountRequired" ) )
2529  {
2530  self enabledeathstreak();
2531  }
2532  }
2533  }
2534  else
2535  {
2536  self.pers["totalKillstreakCount"] = 0;
2537  self.pers["killstreaksEarnedThisKillstreak"] = 0;
2538  }
2539 
2540  if ( !SessionModeIsZombiesGame() && ‪killstreaks::is_killstreak_weapon( weapon ) )
2541  {
2542  level.globalKillstreaksDeathsFrom++;
2543  }
2544 }
2545 
2546 function ‪PlayerKilled_WeaponStats( attacker, weapon, sMeansOfDeath, wasInLastStand, lastWeaponBeforeDroppingIntoLastStand, inflictor )
2547 {
2548  // Don't increment weapon stats for team kills or deaths
2549  if ( isPlayer( attacker ) && attacker != self && ( !level.teamBased || ( level.teamBased && self.team != attacker.team ) ) )
2550  {
2551  attackerWeaponPickedUp = false;
2552  if( isdefined( attacker.pickedUpWeapons ) && isdefined( attacker.pickedUpWeapons[weapon] ) )
2553  {
2554  attackerWeaponPickedUp = true;
2555  }
2556  self AddWeaponStat( weapon, "deaths", 1, self.class_num, attackerWeaponPickedUp, undefined, self.primaryLoadoutGunSmithVariantIndex, self.secondaryLoadoutGunSmithVariantIndex );
2557 
2558  if ( wasInLastStand && isdefined( lastWeaponBeforeDroppingIntoLastStand ) )
2559  victim_weapon = lastWeaponBeforeDroppingIntoLastStand;
2560  else
2561  victim_weapon = self.lastdroppableweapon;
2562 
2563  if ( isdefined( victim_weapon ) )
2564  {
2565  victimWeaponPickedUp = false;
2566  if( isdefined( self.pickedUpWeapons ) && isdefined( self.pickedUpWeapons[victim_weapon] ) )
2567  {
2568  victimWeaponPickedUp = true;
2569  }
2570  self AddWeaponStat( victim_weapon, "deathsDuringUse", 1, self.class_num, victimWeaponPickedUp, undefined, self.primaryLoadoutGunSmithVariantIndex, self.secondaryLoadoutGunSmithVariantIndex );
2571  }
2572 
2573 
2574  recordWeaponStatKills = true;
2575  if ( ( attacker.isThief === true ) && isdefined( weapon ) && ( weapon.isHeroWeapon === true ) )
2576  {
2577  recordWeaponStatKills = false; // Blackjack's Rogue kills are tracked as specialiststats[9].stats.kills_weapon
2578  }
2579 
2580  if ( sMeansOfDeath != "MOD_FALLING" && recordWeaponStatKills )
2581  {
2582  if ( weapon.name == "explosive_bolt" && IsDefined( inflictor ) && IsDefined( inflictor.ownerWeaponAtLaunch ) && inflictor.ownerAdsAtLaunch )
2583  {
2584  inflictorOwnerWeaponAtLaunchPickedUp = false;
2585  if( isdefined( attacker.pickedUpWeapons ) && isdefined( attacker.pickedUpWeapons[inflictor.ownerWeaponAtLaunch] ) )
2586  {
2587  inflictorOwnerWeaponAtLaunchPickedUp = true; // ever the case?
2588  }
2589  attacker AddWeaponStat( inflictor.ownerWeaponAtLaunch, "kills", 1, attacker.class_num, inflictorOwnerWeaponAtLaunchPickedUp, true, attacker.primaryLoadoutGunSmithVariantIndex, attacker.secondaryLoadoutGunSmithVariantIndex );
2590  }
2591  else
2592  {
2593  attacker AddWeaponStat( weapon, "kills", 1, attacker.class_num, attackerWeaponPickedUp, undefined, attacker.primaryLoadoutGunSmithVariantIndex, attacker.secondaryLoadoutGunSmithVariantIndex );
2594  }
2595  }
2596 
2597  if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
2598  {
2599  attacker AddWeaponStat( weapon, "headshots", 1, attacker.class_num, attackerWeaponPickedUp, undefined, attacker.primaryLoadoutGunSmithVariantIndex, attacker.secondaryLoadoutGunSmithVariantIndex );
2600  }
2601 
2602  if ( sMeansOfDeath == "MOD_PROJECTILE" || ( ( sMeansOfDeath == "MOD_GRENADE" || sMeansOfDeath == "MOD_IMPACT" ) && weapon.rootWeapon.statIndex == level.weaponLauncherEx41.statIndex ) )
2603  {
2604  attacker AddWeaponStat( weapon, "direct_hit_kills", 1 );
2605  }
2606 
2607  victimIsRoulette = ( self.isRoulette === true );
2608  if ( self ‪ability_player::gadget_CheckHeroAbilityKill( attacker ) && !victimIsRoulette )
2609  {
2610  attacker AddWeaponStat( attacker.heroAbility, "kills_while_active", 1 );
2611  }
2612  }
2613 }
2614 
2615 function ‪PlayerKilled_Obituary( attacker, eInflictor, weapon, sMeansOfDeath )
2616 {
2617  if ( !isplayer( attacker ) || ( self ‪util::IsEnemyPlayer( attacker ) == false ) || ( isdefined ( weapon ) && ‪killstreaks::is_killstreak_weapon( weapon ) ) )
2618  {
2619  level notify( "reset_obituary_count" );
2620  level.lastObituaryPlayerCount = 0;
2621  level.lastObituaryPlayer = undefined;
2622  }
2623  else
2624  {
2625  if ( isdefined( level.lastObituaryPlayer ) && level.lastObituaryPlayer == attacker )
2626  {
2627  level.lastObituaryPlayerCount++;
2628  }
2629  else
2630  {
2631  level notify( "reset_obituary_count" );
2632  level.lastObituaryPlayer = attacker;
2633  level.lastObituaryPlayerCount = 1;
2634  }
2635 
2637 
2638  if ( level.lastObituaryPlayerCount >= 4 )
2639  {
2640  level notify( "reset_obituary_count" );
2641  level.lastObituaryPlayerCount = 0;
2642  level.lastObituaryPlayer = undefined;
2643  self thread ‪scoreevents::uninterruptedObitFeedKills( attacker, weapon );
2644  }
2645  }
2646 
2647  if ( !isplayer( attacker ) || ( isdefined( weapon ) && !‪killstreaks::is_killstreak_weapon( weapon ) ) )
2648  {
2649  ‪behaviorTracker::UpdatePlayerKilled( attacker, self );
2650  }
2651 
2652  overrideEntityCamera = ‪killstreaks::should_override_entity_camera_in_demo( attacker, weapon );
2653 
2654  if( isdefined( eInflictor ) && ( eInflictor.archetype === "robot" ) )
2655  {
2656  if( sMeansOfDeath == "MOD_HIT_BY_OBJECT" )
2657  weapon = GetWeapon( "combat_robot_marker" );
2658  sMeansOfDeath = "MOD_RIFLE_BULLET";
2659  }
2660  // send out an obituary message to all clients about the kill
2661  if( level.teamBased && isdefined( attacker.pers ) && self.team == attacker.team && sMeansOfDeath == "MOD_GRENADE" && level.friendlyfire == 0 )
2662  {
2663  obituary(self, self, weapon, sMeansOfDeath);
2664  ‪demo::bookmark( "kill", gettime(), self, self, 0, eInflictor, overrideEntityCamera );
2665  }
2666  else
2667  {
2668  obituary(self, attacker, weapon, sMeansOfDeath);
2669  ‪demo::bookmark( "kill", gettime(), attacker, self, 0, eInflictor, overrideEntityCamera );
2670  }
2671 }
2672 
2673 function ‪PlayerKilled_Suicide( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc )
2674 {
2675  awardAssists = false;
2676  self.suicide = false;
2677 
2678  // switching teams
2679  if ( isdefined( self.switching_teams ) )
2680  {
2681 
2682  if ( !level.teamBased && ( isdefined( level.teams[ self.leaving_team ] ) && isdefined( level.teams[ self.joining_team ] ) && level.teams[ self.leaving_team ] != level.teams[ self.joining_team ] ) )
2683  {
2684  playerCounts = self ‪teams::count_players();
2685  playerCounts[self.leaving_team]--;
2686  playerCounts[self.joining_team]++;
2687 
2688  if( (playerCounts[self.joining_team] - playerCounts[self.leaving_team]) > 1 )
2689  {
2690  ‪scoreevents::processScoreEvent( "suicide", self );
2691  self thread ‪rank::giveRankXP( "suicide" );
2692  self ‪globallogic_score::incPersStat( "suicides", 1 );
2693  self.suicides = self ‪globallogic_score::getPersStat( "suicides" );
2694  self.suicide = true;
2695  }
2696  }
2697  }
2698  else
2699  {
2700  ‪scoreevents::processScoreEvent( "suicide", self );
2701  self ‪globallogic_score::incPersStat( "suicides", 1 );
2702  self.suicides = self ‪globallogic_score::getPersStat( "suicides" );
2703 
2704  if ( sMeansOfDeath == "MOD_SUICIDE" && sHitLoc == "none" && self.throwingGrenade )
2705  {
2706  self.lastGrenadeSuicideTime = gettime();
2707  }
2708 
2709  if ( level.maxSuicidesBeforeKick > 0 && level.maxSuicidesBeforeKick <= self.suicides )
2710  {
2711  // should change "teamKillKicked" to just kicked for the next game
2712  self notify( "teamKillKicked" );
2713  self ‪SuicideKick();
2714  }
2715 
2716  //Check for player death related battlechatter
2717  thread ‪battlechatter::on_player_suicide_or_team_kill( self, "suicide" ); //Play suicide battlechatter
2718 
2719  //check if assist points should be awarded
2720  awardAssists = true;
2721  self.suicide = true;
2722  }
2723 
2724  if( isdefined( self.friendlydamage ) )
2725  {
2726  self iPrintLn(&"MP_FRIENDLY_FIRE_WILL_NOT");
2727  if ( level.teamKillPointLoss )
2728  {
2729  scoreSub = self [[level.getTeamKillScore]]( eInflictor, attacker, sMeansOfDeath, weapon);
2730 
2731  score = ‪globallogic_score::_getPlayerScore( attacker ) - scoreSub;
2732 
2733  if ( score < 0 )
2734  score = 0;
2735 
2736  ‪globallogic_score::_setPlayerScore( attacker, score );
2737  }
2738  }
2739 
2740  return awardAssists;
2741 }
2742 
2743 function ‪PlayerKilled_TeamKill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc )
2744 {
2745  ‪scoreevents::processScoreEvent( "team_kill", attacker );
2746 
2747  self.teamKilled = true;
2748 
2749  if ( !‪IgnoreTeamKills( weapon, sMeansOfDeath, eInflictor ) )
2750  {
2751  teamkill_penalty = self [[level.getTeamKillPenalty]]( eInflictor, attacker, sMeansOfDeath, weapon);
2752 
2753  attacker ‪globallogic_score::incPersStat( "teamkills_nostats", teamkill_penalty, false );
2754  attacker ‪globallogic_score::incPersStat( "teamkills", 1 ); //save team kills to player stats
2755  attacker.teamkillsThisRound++;
2756 
2757  if ( level.teamKillPointLoss )
2758  {
2759  scoreSub = self [[level.getTeamKillScore]]( eInflictor, attacker, sMeansOfDeath, weapon);
2760 
2761  score = ‪globallogic_score::_getPlayerScore( attacker ) - scoreSub;
2762 
2763  if ( score < 0 )
2764  {
2765  score = 0;
2766  }
2767 
2768  ‪globallogic_score::_setPlayerScore( attacker, score );
2769  }
2770 
2771  if ( ‪globallogic_utils::getTimePassed() < 5000 )
2772  teamKillDelay = 1;
2773  else if ( attacker.pers["teamkills_nostats"] > 1 && ‪globallogic_utils::getTimePassed() < (8000 + (attacker.pers["teamkills_nostats"] * 1000)) )
2774  teamKillDelay = 1;
2775  else
2776  teamKillDelay = attacker ‪TeamKillDelay();
2777 
2778  if ( teamKillDelay > 0 )
2779  {
2780  attacker.teamKillPunish = true;
2781  attacker thread ‪wait_and_suicide(); // can't eject the teamkilling player same frame bc it purges EV_FIRE_WEAPON fx
2782 
2783  if ( attacker ‪ShouldTeamKillKick(teamKillDelay) )
2784  {
2785  // should change "teamKillKicked" to just kicked for the next game
2786  attacker notify( "teamKillKicked" );
2787  attacker thread ‪TeamKillKick();
2788  }
2789 
2790  attacker thread ‪reduceTeamKillsOverTime();
2791  }
2792 
2793  //Play teamkill battlechatter
2794  if( isPlayer( attacker ) )
2795  thread ‪battlechatter::on_player_suicide_or_team_kill( attacker, "teamkill" );
2796  }
2797 }
2798 
2799 function ‪wait_and_suicide() // self == player
2800 {
2801  self endon( "disconnect" );
2802  self ‪util::freeze_player_controls( true );
2803 
2804  wait .25;
2805 
2806  self ‪suicide();
2807 }
2808 
2809 function ‪PlayerKilled_AwardAssists( eInflictor, attacker, weapon, lpattackteam )
2810 {
2811  if ( isdefined( self.attackers ) )
2812  {
2813  for ( j = 0; j < self.attackers.size; j++ )
2814  {
2815  player = self.attackers[j];
2816 
2817  if ( !isdefined( player ) )
2818  continue;
2819 
2820  if ( player == attacker )
2821  continue;
2822 
2823  if ( player.team != lpattackteam )
2824  continue;
2825 
2826  damage_done = self.attackerDamage[player.clientId].damage;
2827  player thread ‪globallogic_score::processAssist( self, damage_done, self.attackerDamage[player.clientId].weapon );
2828  }
2829  }
2830 
2831  if ( level.teamBased )
2832  {
2833  self ‪globallogic_score::processKillstreakAssists( attacker, eInflictor, weapon );
2834  }
2835 
2836  if ( isdefined( self.lastAttackedShieldPlayer ) && isdefined( self.lastAttackedShieldTime ) && self.lastAttackedShieldPlayer != attacker )
2837  {
2838  if ( gettime() - self.lastAttackedShieldTime < 4000 )
2839  {
2840  self.lastAttackedShieldPlayer thread ‪globallogic_score::processShieldAssist( self );
2841  }
2842  }
2843 }
2844 
2845 function ‪PlayerKilled_Kill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc )
2846 {
2847  if( !isdefined( ‪killstreaks::get_killstreak_for_weapon( weapon ) ) || ‪IS_TRUE( level.killstreaksGiveGameScore ) )
2848  ‪globallogic_score::incTotalKills(attacker.team);
2849 
2850  if( GetDvarInt( "teamOpsEnabled" ) == 1 )
2851  {
2852  if( isdefined( eInflictor ) && ‪IS_TRUE( eInflictor.teamops ) )
2853  {
2854  if( !isdefined( ‪killstreaks::get_killstreak_for_weapon( weapon ) ) || ‪IS_TRUE( level.killstreaksGiveGameScore ) )
2855  ‪globallogic_score::giveTeamScore( "kill", attacker.team, undefined, self );
2856  return;
2857  }
2858  }
2859 
2860  attacker thread ‪globallogic_score::giveKillStats( sMeansOfDeath, weapon, self );
2861 
2862 
2863  if ( isAlive( attacker ) )
2864  {
2865  if ( !isdefined( eInflictor ) || !isdefined( eInflictor.requiredDeathCount ) || attacker.deathCount == eInflictor.requiredDeathCount )
2866  {
2867  shouldGiveKillstreak = ‪killstreaks::should_give_killstreak( weapon );
2868  //attacker thread _properks::earnedAKill();
2869 
2870  if ( shouldGiveKillstreak )
2871  {
2872  attacker ‪killstreaks::add_to_killstreak_count( weapon );
2873  }
2874 
2875  attacker.pers["cur_total_kill_streak"]++;
2876  attacker setplayercurrentstreak( attacker.pers["cur_total_kill_streak"] );
2877 
2878  //Kills gotten through killstreak weapons should not the players killstreak
2879  if ( isdefined( level.killstreaks ) && shouldGiveKillstreak )
2880  {
2881  attacker.pers["cur_kill_streak"]++;
2882 
2883  if ( attacker.pers["cur_kill_streak"] >= 2 )
2884  {
2885  if ( attacker.pers["cur_kill_streak"] == 10 )
2886  {
2887  attacker ‪challenges::killstreakTen();
2888  }
2889  if ( attacker.pers["cur_kill_streak"] <= 30 )
2890  {
2891  ‪scoreevents::processScoreEvent( "killstreak_" + attacker.pers["cur_kill_streak"], attacker, self, weapon );
2892 
2893  if ( attacker.pers["cur_kill_streak"] == 30 )
2894  {
2896  }
2897  }
2898  else
2899  {
2900  ‪scoreevents::processScoreEvent( "killstreak_more_than_30", attacker, self, weapon );
2901  }
2902  }
2903 
2904  if ( !isdefined( level.usingMomentum ) || !level.usingMomentum )
2905  {
2906  if( GetDvarInt( "teamOpsEnabled" ) == 0 )
2907  attacker thread ‪killstreaks::give_for_streak();
2908  }
2909  }
2910  }
2911  }
2912 
2913  if ( attacker.pers["cur_kill_streak"] > attacker.kill_streak )
2914  {
2915  if ( level.rankedMatch && !level.disableStatTracking )
2916  {
2917  attacker setDStat( "HighestStats", "kill_streak", attacker.pers["totalKillstreakCount"] );
2918  }
2919  attacker.kill_streak = attacker.pers["cur_kill_streak"];
2920  }
2921 
2922 
2923  if ( attacker.pers["cur_kill_streak"] > attacker.gametype_kill_streak )
2924  {
2925  attacker ‪persistence::stat_set_with_gametype( "kill_streak", attacker.pers["cur_kill_streak"] );
2926  attacker.gametype_kill_streak = attacker.pers["cur_kill_streak"];
2927  }
2928 
2929  killstreak = ‪killstreaks::get_killstreak_for_weapon( weapon );
2930 
2931  if ( isdefined( killstreak ) )
2932  {
2933  if ( ‪scoreevents::isRegisteredEvent( killstreak ) )
2934  {
2935  ‪scoreevents::processScoreEvent( killstreak, attacker, self, weapon );
2936  }
2937 
2938  if( isdefined( eInflictor ) && ( killstreak == "dart" || killstreak == "inventory_dart" ) )
2939  {
2940  eInflictor notify( "veh_collision" );
2941  }
2942  }
2943  else
2944  {
2945  ‪scoreevents::processScoreEvent( "kill", attacker, self, weapon );
2946 
2947  // if ( sMeansOfDeath == "MOD_HEAD_SHOT" || ( sMeansOfDeath == "MOD_IMPACT" && sHitLoc == "head" ) ) // TODO: add back when applicable LOOT6 weapon is ready
2948  if ( sMeansOfDeath == "MOD_HEAD_SHOT" )
2949  {
2950  ‪scoreevents::processScoreEvent( "headshot", attacker, self, weapon );
2951  attacker ‪util::player_contract_event( "headshot" );
2952  }
2953  else if ( ‪weapon_utils::isMeleeMOD( sMeansOfDeath ) )
2954  {
2955  ‪scoreevents::processScoreEvent( "melee_kill", attacker, self, weapon );
2956  }
2957  }
2958 
2959  attacker thread ‪globallogic_score::trackAttackerKill( self.‪name, self.pers["rank"], self.pers["rankxp"], self.pers["prestige"], self getXuid(), weapon );
2960 
2961  attackerName = attacker.name;
2962  self thread ‪globallogic_score::trackAttackeeDeath( attackerName, attacker.pers["rank"], attacker.pers["rankxp"], attacker.pers["prestige"], attacker getXuid() );
2963  self thread ‪medals::setLastKilledBy( attacker );
2964 
2965  attacker thread ‪globallogic_score::incKillstreakTracker( weapon );
2966 
2967  // to prevent spectator gain score for team-spectator after throwing a granade and killing someone before he switched
2968  if ( level.teamBased && attacker.team != "spectator")
2969  {
2970  if( !isdefined( killstreak ) || ‪IS_TRUE( level.killstreaksGiveGameScore ) )
2971  ‪globallogic_score::giveTeamScore( "kill", attacker.team, attacker, self );
2972  }
2973 
2974  scoreSub = level.deathPointLoss;
2975  if ( scoreSub != 0 )
2976  {
2978  }
2979 
2980  level thread ‪playKillBattleChatter( attacker, weapon, self, eInflictor );
2981 }
2982 
2983 function ‪should_allow_postgame_death( sMeansOfDeath )
2984 {
2985  if ( sMeansOfDeath == "MOD_POST_GAME" )
2986  return true;
2987 
2988  return false;
2989 }
2990 
2991 function ‪do_post_game_death(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
2992 {
2993  if ( !‪should_allow_postgame_death( sMeansOfDeath ) )
2994  return;
2995 
2997 
2998  self.sessionstate = "dead";
2999  self.spectatorclient = -1;
3000  self.killcamentity = -1;
3001  self.archivetime = 0;
3002  self.psoffsettime = 0;
3003 
3004  clone_weapon = weapon;
3005 
3006  // we do not want the weapon death fx to play if this is not a melee weapon and its a melee attack
3007  // ideally the mod be passed to the client side and let it decide but this is post ship t7 and this is safest
3008  if ( ‪weapon_utils::isMeleeMOD(sMeansOfDeath) && clone_weapon.type != "melee" )
3009  {
3010  clone_weapon = level.weaponNone;
3011  }
3012  body = self clonePlayer( deathAnimDuration, clone_weapon, attacker );
3013 
3014  if ( isdefined( body ) )
3015  {
3016  self ‪createDeadBody( attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, (0,0,0), deathAnimDuration, eInflictor, body );
3017  }
3018 }
3019 
3020 function ‪Callback_PlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, enteredResurrect = false)
3021 {
3022  profilelog_begintiming( 7, "ship" );
3023 
3024  self endon( "spawned" );
3025 
3026 
3027  if ( game["state"] == "postgame" )
3028  {
3029  ‪do_post_game_death(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration);
3030  return;
3031  }
3032 
3033  if ( self.sessionteam == "spectator" )
3034  return;
3035 
3036  self notify( "killed_player" );
3037  self ‪callback::callback( #"on_player_killed" );
3038 
3039  self needsRevive( false );
3040 
3041  if ( isdefined( self.burning ) && self.burning == true )
3042  {
3043  self setburn( 0 );
3044  }
3045 
3046  self.suicide = false;
3047  self.teamKilled = false;
3048 
3049  if ( isdefined( level.takeLivesOnDeath ) && ( level.takeLivesOnDeath == true ) )
3050  {
3051  if ( self.pers["lives"] )
3052  {
3053  self.pers["lives"]--;
3054  if ( self.pers["lives"] == 0 )
3055  {
3056  level notify( "player_eliminated" );
3057  self notify( "player_eliminated" );
3058  }
3059  }
3060  if ( game[self.team + "_lives"] )
3061  {
3062  game[self.team + "_lives"]--;
3063  if ( game[self.team + "_lives"] == 0 )
3064  {
3065  level notify( "player_eliminated" );
3066  self notify( "player_eliminated" );
3067  }
3068  }
3069  }
3070 
3071  self thread ‪globallogic_audio::flush_leader_dialog_key_on_player( "equipmentDestroyed" );
3072  //self thread globallogic_audio::flush_leader_dialog_key_on_player( "equipmentHacked" );
3073 
3074  weapon = ‪updateWeapon( eInflictor, weapon );
3075 
3076  wasInLastStand = false;
3077  bledOut = false;
3078  deathTimeOffset = 0;
3079  lastWeaponBeforeDroppingIntoLastStand = undefined;
3080  attackerStance = undefined;
3081  self.lastStandThisLife = undefined;
3082  self.vAttackerOrigin = undefined;
3083 
3084  // need to get this before changing the sessionstate
3085  weapon_at_time_of_death = self GetCurrentWeapon();
3086 
3087  if ( isdefined( self.useLastStandParams ) && enteredResurrect == false )
3088  {
3089  self.useLastStandParams = undefined;
3090 
3091  assert( isdefined( self.lastStandParams ) );
3092  if ( !level.teamBased || ( !isdefined( attacker ) || !isplayer( attacker ) || attacker.team != self.team || attacker == self ) )
3093  {
3094  eInflictor = self.lastStandParams.eInflictor;
3095  attacker = self.lastStandParams.attacker;
3096  attackerStance = self.lastStandParams.attackerStance;
3097  iDamage = self.lastStandParams.iDamage;
3098  sMeansOfDeath = self.lastStandParams.sMeansOfDeath;
3099  weapon = self.lastStandParams.sWeapon;
3100  vDir = self.lastStandParams.vDir;
3101  sHitLoc = self.lastStandParams.sHitLoc;
3102  self.vAttackerOrigin = self.lastStandParams.vAttackerOrigin;
3103  self.killcam_entity_info_cached = self.lastStandParams.killcam_entity_info_cached;
3104  deathTimeOffset = (gettime() - self.lastStandParams.lastStandStartTime) / 1000;
3105  bledOut = true;
3106  if ( isdefined( self.previousPrimary ) )
3107  {
3108  wasInLastStand = true;
3109  lastWeaponBeforeDroppingIntoLastStand = self.previousPrimary;
3110  }
3111  }
3112  self.lastStandParams = undefined;
3113  }
3114 
3115  self StopSounds();
3116 
3117  bestPlayer = undefined;
3118  bestPlayerMeansOfDeath = undefined;
3119  obituaryMeansOfDeath = undefined;
3120  bestPlayerWeapon = undefined;
3121  obituaryWeapon = weapon;
3122  assistedSuicide = false;
3123  if ( (!isdefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || ( isdefined( attacker.isMagicBullet ) && attacker.isMagicBullet == true ) || attacker == self ) && isdefined( self.attackers ) && !self IsPlayerUnderwater() )
3124  {
3125  if ( !isdefined(bestPlayer) )
3126  {
3127  for ( i = 0; i < self.attackers.size; i++ )
3128  {
3129  player = self.attackers[i];
3130  if ( !isdefined( player ) )
3131  continue;
3132 
3133  if (!isdefined( self.attackerDamage[ player.clientId ] ) || ! isdefined( self.attackerDamage[ player.clientId ].damage ) )
3134  continue;
3135 
3136  if ( player == self || (level.teamBased && player.team == self.team ) )
3137  continue;
3138 
3139  if ( self.attackerDamage[ player.clientId ].lasttimedamaged + 2500 < getTime() )
3140  continue;
3141 
3142  if ( !‪allowedAssistWeapon( self.attackerDamage[ player.clientId ].weapon ) )
3143  continue;
3144 
3145  if ( self.attackerDamage[ player.clientId ].damage > 1 && ! isdefined( bestPlayer ) )
3146  {
3147  bestPlayer = player;
3148  bestPlayerMeansOfDeath = self.attackerDamage[ player.clientId ].meansOfDeath;
3149  bestPlayerWeapon = self.attackerDamage[ player.clientId ].weapon;
3150  }
3151  else if ( isdefined( bestPlayer ) && self.attackerDamage[ player.clientId ].damage > self.attackerDamage[ bestPlayer.clientId ].damage )
3152  {
3153  bestPlayer = player;
3154  bestPlayerMeansOfDeath = self.attackerDamage[ player.clientId ].meansOfDeath;
3155  bestPlayerWeapon = self.attackerDamage[ player.clientId ].weapon;
3156  }
3157  }
3158  }
3159  if ( isdefined ( bestPlayer ) )
3160  {
3161  ‪scoreevents::processScoreEvent( "assisted_suicide", bestPlayer, self, weapon );
3162  self RecordKillModifier("assistedsuicide");
3163  assistedSuicide = true;
3164  }
3165  }
3166 
3167  if ( isdefined ( bestPlayer ) )
3168  {
3169  attacker = bestPlayer;
3170  obituaryMeansOfDeath = bestPlayerMeansOfDeath;
3171  obituaryWeapon = bestPlayerWeapon;
3172  if ( isdefined( bestPlayerWeapon ) )
3173  {
3174  weapon = bestPlayerWeapon;
3175  }
3176  }
3177 
3178  if ( isplayer( attacker ) )
3179  attacker.damagedPlayers[self.clientid] = undefined;
3180 
3181  if ( enteredResurrect == false )
3182  {
3183  ‪globallogic::DoWeaponSpecificKillEffects(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime);
3184  }
3185 
3186  self.deathTime = getTime();
3187 
3188  if ( attacker != self && (!level.teamBased || attacker.team != self.team ))
3189  {
3190  assert( IsDefined( self.lastspawntime ) );
3191  self.aliveTimes[self.aliveTimeCurrentIndex] = self.deathTime - self.lastspawntime;
3192  self.aliveTimeCurrentIndex = (self.aliveTimeCurrentIndex + 1) % level.aliveTimeMaxCount;
3193  }
3194 
3195  attacker = ‪updateAttacker( attacker, weapon );
3196  eInflictor = ‪updateInflictor( eInflictor );
3197 
3198  sMeansOfDeath = self ‪PlayerKilled_UpdateMeansOfDeath( attacker, eInflictor, weapon, sMeansOfDeath, sHitLoc );
3199 
3200  if ( !isdefined( obituaryMeansOfDeath ) )
3201  obituaryMeansOfDeath = sMeansOfDeath;
3202 
3203  self.hasRiotShield = false;
3204  self.hasRiotShieldEquipped = false;
3205 
3206  self thread ‪updateGlobalBotKilledCounter();
3207 
3208  self ‪PlayerKilled_WeaponStats( attacker, weapon, sMeansOfDeath, wasInLastStand, lastWeaponBeforeDroppingIntoLastStand, eInflictor );
3209 
3210  if ( bledOut == false )
3211  {
3212  if( GetDvarInt( "teamOpsEnabled" ) == 1 && ( isdefined( eInflictor ) && ‪IS_TRUE( eInflictor.teamops ) ) )
3213  {
3214  self ‪PlayerKilled_Obituary( eInflictor, eInflictor, obituaryWeapon, obituaryMeansOfDeath );
3215  }
3216  else
3217  {
3218  self ‪PlayerKilled_Obituary( attacker, eInflictor, obituaryWeapon, obituaryMeansOfDeath );
3219  }
3220  }
3221 
3222  if ( enteredResurrect == false )
3223  {
3224 // spawnlogic::death_occured(self, attacker);
3225 
3226  self.sessionstate = "dead";
3227  self.statusicon = "hud_status_dead";
3228  }
3229 
3230  self.pers["weapon"] = undefined;
3231 
3232  self.killedPlayersCurrent = [];
3233 
3234  self.deathCount++;
3235 
3236 /#
3237  println( "players("+self.clientId+") death count ++: " + self.deathCount );
3238 #/
3239 
3240  if ( bledout == false )
3241  {
3242  self ‪PlayerKilled_Killstreaks( attacker, weapon );
3243  }
3244 
3245  lpselfnum = self getEntityNumber();
3246  lpselfname = self.name;
3247  lpattackGuid = "";
3248  lpattackname = "";
3249  lpselfteam = self.team;
3250  lpselfguid = self getGuid();
3251  lpattackteam = "";
3252  lpattackorigin = ( 0, 0, 0 );
3253 
3254  lpattacknum = -1;
3255 
3256  //check if we should award assist points
3257  awardAssists = false;
3258  wasTeamKill = false;
3259  wasSuicide = false;
3260 
3261  ‪scoreevents::processScoreEvent( "death", self, self, weapon );
3262  self.pers["resetMomentumOnSpawn"] = level.scoreResetOnDeath;
3263 
3264 
3265  if( isPlayer( attacker ) )
3266  {
3267  lpattackGuid = attacker getGuid();
3268  lpattackname = attacker.name;
3269  lpattackteam = attacker.team;
3270  lpattackorigin = attacker.origin;
3271 
3272  if ( attacker == self || assistedSuicide == true ) // killed himself
3273  {
3274  doKillcam = false;
3275  wasSuicide = true;
3276 
3277  awardAssists = self ‪PlayerKilled_Suicide( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc );
3278  if( assistedSuicide == true )
3279  attacker thread ‪globallogic_score::giveKillStats( sMeansOfDeath, weapon, self );
3280  }
3281  else
3282  {
3283  lpattacknum = attacker getEntityNumber();
3284 
3285  doKillcam = true;
3286 
3287  if ( level.teamBased && self.team == attacker.team && sMeansOfDeath == "MOD_GRENADE" && level.friendlyfire == 0 )
3288  {
3289  }
3290  else if ( level.teamBased && self.team == attacker.team ) // killed by a friendly
3291  {
3292  wasTeamKill = true;
3293 
3294  self ‪PlayerKilled_TeamKill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc );
3295  }
3296  else
3297  {
3298  if ( bledOut == false )
3299  {
3300  self ‪PlayerKilled_Kill( eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc );
3301 
3302  if ( level.teamBased )
3303  {
3304  //check if assist points should be awarded
3305  awardAssists = true;
3306  }
3307  }
3308  }
3309  }
3310  }
3311  else if ( isdefined( attacker ) && ( attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" ) )
3312  {
3313  doKillcam = false;
3314 
3315  lpattacknum = -1;
3316  lpattackguid = "";
3317  lpattackname = "";
3318  lpattackteam = "world";
3319 
3320  ‪scoreevents::processScoreEvent( "suicide", self );
3321  self ‪globallogic_score::incPersStat( "suicides", 1 );
3322  self.suicides = self ‪globallogic_score::getPersStat( "suicides" );
3323 
3324  self.suicide = true;
3325 
3326  //Check for player death related battlechatter
3327  thread ‪battlechatter::on_player_suicide_or_team_kill( self, "suicide" ); //Play suicide battlechatter
3328 
3329  //check if assist points should be awarded
3330  awardAssists = true;
3331 
3332  if ( level.maxSuicidesBeforeKick > 0 && level.maxSuicidesBeforeKick <= self.suicides )
3333  {
3334  // should change "teamKillKicked" to just kicked for the next game
3335  self notify( "teamKillKicked" );
3336  self ‪SuicideKick();
3337  }
3338  }
3339  else
3340  {
3341  doKillcam = false;
3342 
3343  lpattacknum = -1;
3344  lpattackguid = "";
3345  lpattackname = "";
3346  lpattackteam = "world";
3347 
3348  wasSuicide = true;
3349 
3350  // we may have a killcam on an world entity like the rocket in cosmodrome
3351  if ( isdefined( eInflictor ) && isdefined( eInflictor.killCamEnt ) )
3352  {
3353  doKillcam = true;
3354  lpattacknum = self getEntityNumber();
3355  wasSuicide = false;
3356  }
3357 
3358  // even if the attacker isn't a player, it might be on a team
3359  if ( isdefined( attacker ) && isdefined( attacker.team ) && ( isdefined( level.teams[attacker.team] ) ) )
3360  {
3361  if ( attacker.team != self.team )
3362  {
3363  if ( level.teamBased )
3364  {
3365  if( !isdefined( ‪killstreaks::get_killstreak_for_weapon( weapon ) ) || ‪IS_TRUE( level.killstreaksGiveGameScore ) )
3366  ‪globallogic_score::giveTeamScore( "kill", attacker.team, attacker, self );
3367  }
3368 
3369  wasSuicide = false;
3370  }
3371  }
3372 
3373  //check if assist points should be awarded
3374  awardAssists = true;
3375  }
3376 
3377  if ( !level.inGracePeriod && enteredResurrect == false )
3378  {
3379  if ( sMeansOfDeath != "MOD_GRENADE" && sMeansOfDeath != "MOD_GRENADE_SPLASH" && sMeansOfDeath != "MOD_EXPLOSIVE" && sMeansOfDeath != "MOD_EXPLOSIVE_SPLASH" && sMeansOfDeath != "MOD_PROJECTILE_SPLASH" && sMeansOfDeath != "MOD_FALLING" )
3380  {
3381  if ( weapon.name != "incendiary_fire" )
3382  {
3383  self ‪weapons::drop_scavenger_for_death( attacker );
3384  }
3385  }
3386 
3387  if ( ‪should_drop_weapon_on_death( wasTeamkill, wasSuicide, weapon_at_time_of_death, sMeansOfDeath ) )
3388  {
3389  self ‪weapons::drop_for_death( attacker, weapon, sMeansOfDeath );
3390  }
3391  }
3392 
3393  //award assist points if needed
3394  if( awardAssists )
3395  {
3396  self ‪PlayerKilled_AwardAssists( eInflictor, attacker, weapon, lpattackteam );
3397  }
3398 
3399  self.lastAttacker = attacker;
3400  self.lastDeathPos = self.origin;
3401 
3402  if ( isdefined( attacker ) && isPlayer( attacker ) && attacker != self && (!level.teambased || attacker.team != self.team) )
3403  {
3404  attacker notify( "killed_enemy_player", self, weapon );
3405  if( isDefined( attacker.gadget_thief_kill_callback ) )
3406  {
3407  attacker [[attacker.gadget_thief_kill_callback]]( self, weapon );
3408  }
3409  self thread ‪challenges::playerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, attackerStance, bledOut );
3410  }
3411  else
3412  {
3413 
3414  self notify("playerKilledChallengesProcessed");
3415  }
3416 
3417  if ( isdefined ( self.attackers ))
3418  self.attackers = [];
3419 
3420 
3421  // minimize repeat checks of things like isPlayer
3422  killerHeroPowerActive = 0;
3423  killer = undefined;
3424  killerLoadoutIndex = -1;
3425  killerWasADS = false;
3426  killerInVictimFOV = false;
3427  victimInKillerFOV = false;
3428 
3429  if( isPlayer( attacker ) )
3430  {
3431  attacker.lastKillTime = gettime();
3432 
3433  killer = attacker;
3434  killerLoadoutIndex = attacker.class_num;
3435  killerWasADS = attacker playerADS() >= 1;
3436 
3437  killerInVictimFOV = ‪util::within_fov( self.origin, self.angles, attacker.origin, self.fovcosine );
3438  victimInKillerFOV = ‪util::within_fov( attacker.origin, attacker.angles, self.origin, attacker.fovcosine );
3439 
3440  if ( attacker ‪ability_player::is_using_any_gadget() )
3441  killerHeroPowerActive = 1;
3442 
3443  if( ‪killstreaks::is_killstreak_weapon( weapon ) )
3444  {
3446 
3447  }
3448  else
3449  {
3450  }
3451 
3452  attacker thread ‪weapons::bestweapon_kill( weapon );
3453  }
3454  else
3455  {
3456  }
3457 
3458  victimWeapon = undefined;
3459  victimWeaponPickedUp = false;
3460  victimKillstreakWeaponIndex = 0;
3461  if( isdefined( weapon_at_time_of_death ) )
3462  {
3463  victimWeapon = weapon_at_time_of_death;
3464  if( isdefined( self.pickedUpWeapons ) && isdefined( self.pickedUpWeapons[victimWeapon] ) )
3465  {
3466  victimWeaponPickedUp = true;
3467  }
3468 
3469  if( ‪killstreaks::is_killstreak_weapon( victimWeapon ) )
3470  {
3471  killstreak = ‪killstreaks::get_killstreak_for_weapon_for_stats( victimWeapon );
3472  if( isdefined( level.killstreaks[killstreak].menuname ) )
3473  {
3474  victimKillstreakWeaponIndex = level.killstreakindices[level.killstreaks[killstreak].menuname];
3475  }
3476  }
3477  }
3478  victimWasADS = self playerADS() >= 1;
3479  victimHeroPowerActive = self ‪ability_player::is_using_any_gadget();
3480 
3481  killerWeaponPickedUp = false;
3482  killerKillstreakWeaponIndex = 0;
3483  killerKillstreakEventIndex = 125; // 125 = not a killstreak
3484  if( isdefined( weapon ) )
3485  {
3486  if( isdefined( killer ) && isdefined( killer.pickedUpWeapons ) && isdefined( killer.pickedUpWeapons[weapon] ) )
3487  {
3488  killerWeaponPickedUp = true;
3489  }
3490 
3491  if( ‪killstreaks::is_killstreak_weapon( weapon ) )
3492  {
3494  if( isdefined( level.killstreaks[killstreak].menuname ) )
3495  {
3496  killerKillstreakWeaponIndex = level.killstreakindices[level.killstreaks[killstreak].menuname];
3497 
3498  if( isdefined( killer.killstreakEvents ) && isdefined( killer.killstreakEvents[ killerkillstreakweaponindex ] ) )
3499  {
3500  killerKillstreakEventIndex = killer.killstreakEvents[killerkillstreakweaponindex];
3501  }
3502  else
3503  {
3504  killerkillstreakeventindex = 126; // 126 = was a killstreak but no event index
3505  }
3506  }
3507  }
3508  }
3509 
3510  //
3511  // Log additional stuff in match record on death.
3512  // Mostly values we can't easily access in the existing MatchRecordDeath function in code.
3513  //
3514 
3515  matchRecordLogAdditionalDeathInfo( self, killer, victimWeapon, weapon,
3516  self.class_num, victimWeaponPickedUp, victimWasADS,
3517  killerLoadoutIndex, killerWeaponPickedUp, killerWasADS,
3518  victimHeroPowerActive, killerHeroPowerActive,
3519  victimInKillerFOV, killerInVictimFOV,
3520  killerKillstreakWeaponIndex, victimKillstreakWeaponIndex,
3521  killerkillstreakeventindex);
3522 
3523 
3524  self ‪record_special_move_data_for_life( killer );
3525 
3526  self.pickedUpWeapons = []; // reset on each death
3527 
3528 
3529  /#logPrint( "K;" + lpselfguid + ";" + lpselfnum + ";" + lpselfteam + ";" + lpselfname + ";" + lpattackguid + ";" + lpattacknum + ";" + lpattackteam + ";" + lpattackname + ";" + weapon.name + ";" + iDamage + ";" + sMeansOfDeath + ";" + sHitLoc + "\n" );#/
3530  attackerString = "none";
3531  if ( isPlayer( attacker ) ) // attacker can be the worldspawn if it's not a player
3532  attackerString = attacker getXuid() + "(" + lpattackname + ")";
3533  /#print( "d " + sMeansOfDeath + "(" + weapon.name + ") a:" + attackerString + " d:" + iDamage + " l:" + sHitLoc + " @ " + int( self.origin[0] ) + " " + int( self.origin[1] ) + " " + int( self.origin[2] ) );#/
3534 
3535  // for cod caster update the top scorers
3536  if ( !level.rankedMatch && !level.teambased )
3537  {
3538  level thread ‪update_ffa_top_scorers();
3539  }
3540 
3541  level thread ‪globallogic::updateTeamStatus();
3542  level thread ‪globallogic::updateAliveTimes(self.team);
3543 
3544  if ( isdefined( self.killcam_entity_info_cached ) )
3545  {
3546  killcam_entity_info = self.killcam_entity_info_cached;
3547  self.killcam_entity_info_cached = undefined;
3548  }
3549  else
3550  {
3551  killcam_entity_info = ‪killcam::get_killcam_entity_info( attacker, eInflictor, weapon );
3552  }
3553 
3554 
3555  // no killcam if the player is still involved with a killstreak
3556  if ( isdefined( self.killstreak_delay_killcam ) )
3557  doKillcam = false;
3558 
3560 
3561  vAttackerOrigin = undefined;
3562  if ( isdefined( attacker ) )
3563  {
3564  vAttackerOrigin = attacker.origin;
3565  }
3566 
3567  if ( enteredResurrect == false )
3568  {
3569  clone_weapon = weapon;
3570 
3571  // we do not want the weapon death fx to play if this is not a melee weapon and its a melee attack
3572  // ideally the mod be passed to the client side and let it decide but this is post ship t7 and this is safest
3573  if ( ‪weapon_utils::isMeleeMOD(sMeansOfDeath) && clone_weapon.type != "melee" )
3574  {
3575  clone_weapon = level.weaponNone;
3576  }
3577  body = self clonePlayer( deathAnimDuration, clone_weapon, attacker );
3578 
3579  if ( isdefined( body ) )
3580  {
3581  self ‪createDeadBody( attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, vAttackerOrigin, deathAnimDuration, eInflictor, body );
3582 
3583  self ‪battlechatter::play_death_vox( body, attacker, weapon, sMeansOfDeath );
3584 
3585  ‪globallogic::DoWeaponSpecificCorpseEffects(body, eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime);
3586  }
3587  }
3588 
3589  if ( enteredResurrect )
3590  {
3591  thread ‪globallogic_spawn::spawnQueuedClient( self.team, attacker );
3592  }
3593 
3594  self.switching_teams = undefined;
3595  self.joining_team = undefined;
3596  self.leaving_team = undefined;
3597 
3598  if ( bledOut == false ) // handled in PlayerLastStand
3599  {
3600  self thread [[level.onPlayerKilled]](eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration);
3601  }
3602 
3603  if ( isdefined( level.teamopsOnPlayerKilled ) )
3604  {
3605  self [[level.teamopsOnPlayerKilled]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration);
3606  }
3607 
3608  for ( iCB = 0; iCB < level.onPlayerKilledExtraUnthreadedCBs.size; iCB++ )
3609  {
3610  self [[ level.onPlayerKilledExtraUnthreadedCBs[ iCB ] ]](
3611  eInflictor,
3612  attacker,
3613  iDamage,
3614  sMeansOfDeath,
3615  weapon,
3616  vDir,
3617  sHitLoc,
3618  psOffsetTime,
3619  deathAnimDuration );
3620  }
3621 
3622  self.wantSafeSpawn = false;
3623  perks = [];
3624  // perks = globallogic::getPerks( attacker );
3625  killstreaks = globallogic::getKillstreaks( attacker );
3626 
3627  if( !isdefined( self.killstreak_delay_killcam ) )
3628  {
3629  // start the prediction now so the client gets updates while waiting to spawn
3630  self thread [[level.spawnPlayerPrediction]]();
3631  }
3632 
3633  profilelog_endtiming( 7, "gs=" + game["state"] + " zom=" + SessionModeIsZombiesGame() );
3634 
3635  // record the kill cam values for the final kill cam
3636  if ( wasTeamKill == false && assistedSuicide == false && sMeansOfDeath != "MOD_SUICIDE" && !( !isdefined( attacker ) || attacker.classname == "trigger_hurt" || attacker.classname == "worldspawn" || attacker == self || isdefined ( attacker.disableFinalKillcam ) ) )
3637  {
3638  level thread ‪killcam::record_settings( lpattacknum, self getEntityNumber(), weapon, sMeansOfDeath, self.deathTime, deathTimeOffset, psOffsetTime, killcam_entity_info, perks, killstreaks, attacker );
3639  }
3640  if ( enteredResurrect )
3641  {
3642  return;
3643  }
3644 
3645  // let the player watch themselves die
3646  wait ( 0.25 );
3647 
3648  //check if killed by a sniper
3649  weaponClass = ‪util::getWeaponClass( weapon );
3650  if( isdefined( weaponClass ) && weaponClass == "weapon_sniper" )
3651  {
3652  self thread ‪battlechatter::killed_by_sniper( attacker );
3653  }
3654  else
3655  {
3656  self thread ‪battlechatter::player_killed( attacker, killstreak );
3657  }
3658  self.cancelKillcam = false;
3659  self thread ‪killcam::cancel_on_use();
3660 
3661  // initial death cam
3662  self ‪playerkilled_watch_death(weapon, sMeansOfDeath, deathAnimDuration);
3663 
3664  // killcam
3665 
3666  if ( game["state"] != "playing" )
3667  {
3668  return;
3669  }
3670 
3671  self.respawnTimerStartTime = gettime();
3672  keep_deathcam = false;
3673  if ( isdefined( self.overridePlayerDeadStatus ) )
3674  {
3675  keep_deathcam = self [[ self.overridePlayerDeadStatus ]]();
3676  }
3677 
3678  if ( !self.cancelKillcam && doKillcam && level.killcam && ( wasTeamKill == false ) )
3679  {
3680  livesLeft = !(level.numLives && !self.pers["lives"]) && !(level.numTeamLives && !game[self.team+"_lives"]);
3681  timeUntilSpawn = ‪globallogic_spawn::TimeUntilSpawn( true );
3682  willRespawnImmediately = livesLeft && (timeUntilSpawn <= 0) && !level.playerQueuedRespawn;
3683 
3684  self ‪killcam::killcam( lpattacknum, self getEntityNumber(), killcam_entity_info, weapon, sMeansOfDeath, self.deathTime, deathTimeOffset, psOffsetTime, willRespawnImmediately, ‪globallogic_utils::timeUntilRoundEnd(), perks, killstreaks, attacker, keep_deathcam );
3685  }
3686  else if( self.cancelKillcam )
3687  {
3688  // copy of code from wait_skip_killcam_button
3689  // because fast button mashers (not hard to do) will "skip" the killcam
3690  // before it even starts
3691  if( isdefined( self.killcamsSkipped) )
3692  {
3693  self.killcamsSkipped++;
3694  }
3695  else
3696  {
3697  self.killcamsSkipped = 1;
3698  }
3699  }
3700 
3701  // secondary deathcam for resurrection
3702 
3703  secondary_deathcam = 0.0;
3704 
3705  timeUntilSpawn = ‪globallogic_spawn::TimeUntilSpawn( true );
3706  shouldDoSecondDeathCam = timeUntilSpawn > 0;
3707 
3708  if ( shouldDoSecondDeathCam && IsDefined(self.secondaryDeathCamTime) )
3709  {
3710  secondary_deathcam = self [[self.secondaryDeathCamTime]]();
3711  }
3712 
3713  if ( secondary_deathcam > 0.0 && !self.cancelKillcam )
3714  {
3715  self.spectatorclient = -1;
3716  self.killcamentity = -1;
3717  self.archivetime = 0;
3718  self.psoffsettime = 0;
3719  self.spectatekillcam = false;
3720  ‪globallogic_utils::waitForTimeOrNotify( secondary_deathcam, "end_death_delay" );
3721  self notify ( "death_delay_finished" );
3722  }
3723 
3724  // secondary deathcam is complete
3725 
3726  if ( !self.cancelKillcam && doKillcam && level.killcam && keep_deathcam )
3727  {
3728  self.sessionstate = "dead";
3729  self.spectatorclient = -1;
3730  self.killcamentity = -1;
3731  self.archivetime = 0;
3732  self.psoffsettime = 0;
3733  self.spectatekillcam = false;
3734  }
3735 
3736  if ( game["state"] != "playing" )
3737  {
3738  self.sessionstate = "dead";
3739  self.spectatorclient = -1;
3740  self.killcamtargetentity = -1;
3741  self.killcamentity = -1;
3742  self.archivetime = 0;
3743  self.psoffsettime = 0;
3744  self.spectatekillcam = false;
3745  return;
3746  }
3747 
3749  useRespawnTime = true;
3750  if( isDefined( level.hostMigrationTimer ) )
3751  {
3752  useRespawnTime = false;
3753  }
3755  //if ( isDefined( level.hostMigrationTimer ) )
3756  //return;
3757 
3758  // class may be undefined if we have changed teams
3759  if ( ‪globallogic_utils::isValidClass( self.curClass ) )
3760  {
3761  timePassed = undefined;
3762 
3763  if ( isdefined( self.respawnTimerStartTime ) && useRespawnTime )
3764  {
3765  timePassed = (gettime() - self.respawnTimerStartTime) / 1000;
3766  }
3767 
3768  self thread [[level.spawnClient]]( timePassed );
3769  self.respawnTimerStartTime = undefined;
3770  }
3771 }
3772 
3774 {
3775  waittillframeend;
3776 
3777  if ( !level.players.size || level.gameEnded )
3778  return;
3779 
3780  placement = [];
3781  foreach ( player in level.players )
3782  {
3783  if ( player.team != "spectator" )
3784  placement[placement.size] = player;
3785  }
3786 
3787  for ( i = 1; i < placement.size; i++ )
3788  {
3789  player = placement[i];
3790  playerScore = player.pointstowin;
3791  for ( j = i - 1; j >= 0 && (playerScore > placement[j].pointstowin || (playerScore == placement[j].pointstowin && player.deaths < placement[j].deaths) || (playerScore == placement[j].pointstowin && player.deaths == placement[j].deaths && player.lastKillTime > placement[j].lastKillTime)); j-- )
3792  placement[j + 1] = placement[j];
3793  placement[j + 1] = player;
3794  }
3795 
3796  ClearTopScorers();
3797  for ( i = 0; i < placement.size && i < 3; i++ )
3798  {
3799  SetTopScorer( i, placement[i], 0, 0, 0, 0, level.weaponNone );
3800  }
3801 }
3802 
3803 function ‪playerkilled_watch_death(weapon, sMeansOfDeath, deathAnimDuration)
3804 {
3805  defaultPlayerDeathWatchTime = 1.75;
3806  if ( sMeansOfDeath == "MOD_MELEE_ASSASSINATE" || 0 > weapon.deathCamTime )
3807  {
3808  defaultPlayerDeathWatchTime = (deathAnimDuration * 0.001) + 0.5;
3809  }
3810  else if ( 0 < weapon.deathCamTime )
3811  {
3812  defaultPlayerDeathWatchTime = weapon.deathCamTime;
3813  }
3814 
3815  if ( isdefined ( level.overridePlayerDeathWatchTimer ) )
3816  {
3817  defaultPlayerDeathWatchTime = [[level.overridePlayerDeathWatchTimer]]( defaultPlayerDeathWatchTime );
3818  }
3819 
3820  ‪globallogic_utils::waitForTimeOrNotify( defaultPlayerDeathWatchTime, "end_death_delay" );
3821 
3822  self notify ( "death_delay_finished" );
3823 }
3824 
3825 function ‪should_drop_weapon_on_death( wasTeamKill, wasSuicide, current_weapon, sMeansOfDeath )
3826 {
3827  // to avoid exploits dont allow weapon drops on suicide or teamkills.
3828  if ( wasTeamKill )
3829  return false;
3830 
3831  if ( wasSuicide )
3832  return false;
3833 
3834  // assuming this means that they are in a death trigger out of bounds and falling
3835  if ( sMeansOfDeath == "MOD_TRIGGER_HURT" && !self IsOnGround())
3836  return false;
3837 
3838  // dont drop any weapon if they were holding a hero weapon
3839  if ( IsDefined(current_weapon) && current_weapon.isHeroWeapon )
3840  return false;
3841 
3842  return true;
3843 }
3844 
3846 {
3847  if ( isdefined( self.pers["isBot"] ) )
3848  {
3849  level.globalLarrysKilled++;
3850  }
3851 }
3852 
3853 
3855 {
3856  if( isdefined( self.killstreak_delay_killcam ) )
3857  {
3858  while( isdefined( self.killstreak_delay_killcam ) )
3859  {
3860  wait( 0.1 );
3861  }
3862 
3863  //Plus a small amount so we can see our dead body
3864  wait( 2.0 );
3865 
3867  }
3868 }
3869 
3870 function ‪SuicideKick()
3871 {
3872  self ‪globallogic_score::incPersStat( "sessionbans", 1 );
3873 
3874  self endon("disconnect");
3875  waittillframeend;
3876 
3878 
3879  ban( self getentitynumber() );
3880  ‪globallogic_audio::leader_dialog( "gamePlayerKicked" );
3881 }
3882 
3884 {
3885  self ‪globallogic_score::incPersStat( "sessionbans", 1 );
3886 
3887  self endon("disconnect");
3888  waittillframeend;
3889 
3890  //for test purposes lets lock them out of certain game type for 2mins
3891 
3892  playlistbanquantum = ‪tweakables::getTweakableValue( "team", "teamkillerplaylistbanquantum" );
3893  playlistbanpenalty = ‪tweakables::getTweakableValue( "team", "teamkillerplaylistbanpenalty" );
3894  if ( playlistbanquantum > 0 && playlistbanpenalty > 0 )
3895  {
3896  timeplayedtotal = self GetDStat( "playerstatslist", "time_played_total", "StatValue" );
3897  minutesplayed = timeplayedtotal / 60;
3898 
3899  freebees = 2;
3900 
3901  banallowance = int( floor(minutesplayed / playlistbanquantum) ) + freebees;
3902 
3903  if ( self.sessionbans > banallowance )
3904  {
3905  self SetDStat( "playerstatslist", "gametypeban", "StatValue", timeplayedtotal + (playlistbanpenalty * 60) );
3906  }
3907  }
3908 
3910 
3911  ban( self getentitynumber() );
3912  ‪globallogic_audio::leader_dialog( "gamePlayerKicked" );
3913 }
3914 
3916 {
3917  teamkills = self.pers["teamkills_nostats"];
3918  if ( level.minimumAllowedTeamKills < 0 || teamkills <= level.minimumAllowedTeamKills )
3919  return 0;
3920 
3921  exceeded = (teamkills - level.minimumAllowedTeamKills);
3922  return level.teamKillSpawnDelay * exceeded;
3923 }
3924 
3925 
3926 function ‪ShouldTeamKillKick(teamKillDelay)
3927 {
3928  if ( teamKillDelay && ( level.minimumAllowedTeamKills >= 0 ) )
3929  {
3930  // if its more then 5 seconds into the match and we have a delay then just kick them
3931  if ( ‪globallogic_utils::getTimePassed() >= 5000 )
3932  {
3933  return true;
3934  }
3935 
3936  // if its under 5 seconds into the match only kick them if they have killed more then one players so far
3937  if ( self.pers["teamkills_nostats"] > 1 )
3938  {
3939  return true;
3940  }
3941  }
3942 
3943  return false;
3944 }
3945 
3947 {
3948  timePerOneTeamkillReduction = 20.0;
3949  reductionPerSecond = 1.0 / timePerOneTeamkillReduction;
3950 
3951  while(1)
3952  {
3953  if ( isAlive( self ) )
3954  {
3955  self.pers["teamkills_nostats"] -= reductionPerSecond;
3956  if ( self.pers["teamkills_nostats"] < level.minimumAllowedTeamKills )
3957  {
3958  self.pers["teamkills_nostats"] = level.minimumAllowedTeamKills;
3959  break;
3960  }
3961  }
3962  wait 1;
3963  }
3964 }
3965 
3966 
3967 function ‪IgnoreTeamKills( weapon, sMeansOfDeath, eInflictor )
3968 {
3969  if ( ‪weapon_utils::isMeleeMOD( sMeansOfDeath ) )
3970  return false;
3971 
3972  if ( weapon.ignoreTeamKills )
3973  return true;
3974 
3975  if ( isdefined( eInflictor ) && eInflictor.ignore_team_kills === true )
3976  return true;
3977 
3978  if( isDefined( eInflictor ) && isDefined( eInflictor.destroyedBy ) && isDefined( eInflictor.owner ) && eInflictor.destroyedBy != eInflictor.owner )
3979  return true;
3980 
3981  if ( isDefined( eInflictor ) && eInflictor.classname == "worldspawn" )
3982  return true;
3983 
3984  return false;
3985 }
3986 
3987 
3988 function ‪Callback_PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
3989 {
3990  ‪laststand::PlayerLastStand( eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
3991 }
3992 
3993 function ‪damageShellshockAndRumble( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage )
3994 {
3995  self thread ‪weapons::on_damage( eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage );
3996 
3997  if ( !self ‪util::isUsingRemote() )
3998  {
3999  self PlayRumbleOnEntity( "damage_heavy" );
4000  }
4001 }
4002 
4003 
4004 function ‪createDeadBody( attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, vAttackerOrigin, deathAnimDuration, eInflictor, body )
4005 {
4006  if ( sMeansOfDeath == "MOD_HIT_BY_OBJECT" && self GetStance() == "prone" )
4007  {
4008  self.body = body;
4009  if ( !isdefined( self.switching_teams ) )
4010  thread ‪deathicons::add( body, self, self.team, 5.0 );
4011 
4012  return;
4013  }
4014 
4015  ragdoll_now = false;
4016  if( isdefined(self.usingvehicle) && self.usingvehicle && isdefined(self.vehicleposition) && self.vehicleposition == 1 )
4017  {
4018  ragdoll_now = true;
4019  }
4020 
4021  if ( isdefined( level.ragdoll_override ) && self [[level.ragdoll_override]]( iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, vAttackerOrigin, deathAnimDuration, eInflictor, ragdoll_now, body ) )
4022  {
4023  return;
4024  }
4025 
4026  if ( ( ragdoll_now ) || self isOnLadder() || self isMantling() || sMeansOfDeath == "MOD_CRUSH" || sMeansOfDeath == "MOD_HIT_BY_OBJECT" )
4027  body startRagDoll();
4028 
4029  if ( !self IsOnGround() && sMeansOfDeath != "MOD_FALLING" )
4030  {
4031  if ( GetDvarint( "scr_disable_air_death_ragdoll" ) == 0 )
4032  {
4033  body startRagDoll();
4034  }
4035  }
4036 
4037  if( sMeansOfDeath == "MOD_MELEE_ASSASSINATE" && !attacker isOnGround() )
4038  {
4039  body ‪start_death_from_above_ragdoll( vDir );
4040  }
4041 
4042  if ( self ‪is_explosive_ragdoll( weapon, eInflictor ) )
4043  {
4044  body ‪start_explosive_ragdoll( vDir, weapon );
4045  }
4046 
4047  thread ‪delayStartRagdoll( body, sHitLoc, vDir, weapon, eInflictor, sMeansOfDeath );
4048 
4049  if ( sMeansOfDeath == "MOD_CRUSH" )
4050  {
4052  }
4053 
4054  self.body = body;
4055  if ( !isdefined( self.switching_teams ) )
4056  thread ‪deathicons::add( body, self, self.team, 5.0 );
4057 }
4058 
4059 function ‪is_explosive_ragdoll( weapon, inflictor )
4060 {
4061  if ( !isdefined( weapon ) )
4062  {
4063  return false;
4064  }
4065 
4066  // destructible explosives
4067  if ( weapon.name == "destructible_car" || weapon.name == "explodable_barrel" )
4068  {
4069  return true;
4070  }
4071 
4072  // special explosive weapons
4073  if ( weapon.projExplosionType == "grenade" )
4074  {
4075  if ( isdefined( inflictor ) && isdefined( inflictor.stuckToPlayer ) )
4076  {
4077  if ( inflictor.stuckToPlayer == self )
4078  {
4079  return true;
4080  }
4081  }
4082  }
4083 
4084  return false;
4085 }
4086 
4087 function ‪start_explosive_ragdoll( dir, weapon )
4088 {
4089  if ( !isdefined( self ) )
4090  {
4091  return;
4092  }
4093 
4094  x = RandomIntRange( 50, 100 );
4095  y = RandomIntRange( 50, 100 );
4096  z = RandomIntRange( 10, 20 );
4097 
4098  if ( isdefined( weapon ) && (weapon.name == "sticky_grenade" || weapon.name == "explosive_bolt") )
4099  {
4100  if ( isdefined( dir ) && LengthSquared( dir ) > 0 )
4101  {
4102  x = dir[0] * x;
4103  y = dir[1] * y;
4104  }
4105  }
4106  else
4107  {
4108  if ( ‪math::cointoss() )
4109  {
4110  x = x * -1;
4111  }
4112  if ( ‪math::cointoss() )
4113  {
4114  y = y * -1;
4115  }
4116  }
4117 
4118  self StartRagdoll();
4119  self LaunchRagdoll( ( x, y, z ) );
4120 }
4121 
4123 {
4124  if ( !isdefined( self ) )
4125  {
4126  return;
4127  }
4128 
4129  self StartRagdoll();
4130  self LaunchRagdoll( ( 0, 0, -100 ) );
4131 }
4132 
4133 
4135 {
4136  waittillframeend;
4137 
4138  if( isdefined( self ) )
4139  {
4140  level notify( "connecting", self );
4141  }
4142 
4143  ‪callback::callback( #"on_player_connecting" );
4144 }
4145 
4146 
4147 function ‪delayStartRagdoll( ent, sHitLoc, vDir, weapon, eInflictor, sMeansOfDeath )
4148 {
4149  if ( isdefined( ent ) )
4150  {
4151  deathAnim = ent getcorpseanim();
4152  if ( animhasnotetrack( deathAnim, "ignore_ragdoll" ) )
4153  return;
4154  }
4155 
4156  waittillframeend;
4157 
4158  if ( !isdefined( ent ) )
4159  return;
4160 
4161  if ( ent isRagDoll() )
4162  return;
4163 
4164  deathAnim = ent getcorpseanim();
4165 
4166  startFrac = 0.35;
4167 
4168  if ( animhasnotetrack( deathAnim, "start_ragdoll" ) )
4169  {
4170  times = getnotetracktimes( deathAnim, "start_ragdoll" );
4171  if ( isdefined( times ) )
4172  startFrac = times[0];
4173  }
4174 
4175  waitTime = startFrac * getanimlength( deathAnim );
4176 
4177  //waitTime -= 0.2; // account for the wait above
4178  if( waitTime > 0 )
4179  wait( waitTime );
4180 
4181  if ( isdefined( ent ) )
4182  {
4183  ent startragdoll();
4184  }
4185 }
4186 
4187 function ‪trackAttackerDamage( eAttacker, iDamage, sMeansOfDeath, weapon )
4188 {
4189  if( !IsDefined( eAttacker ) )
4190  return;
4191 
4192  if ( !IsPlayer( eAttacker ) )
4193  return;
4194 
4195  if ( self.attackerData.size == 0 )
4196  {
4197  self.firstTimeDamaged = getTime();
4198  }
4199  if ( !isdefined( self.attackerData[eAttacker.clientid] ) )
4200  {
4201  self.attackerDamage[eAttacker.clientid] = spawnstruct();
4202  self.attackerDamage[eAttacker.clientid].damage = iDamage;
4203  self.attackerDamage[eAttacker.clientid].meansOfDeath = sMeansOfDeath;
4204  self.attackerDamage[eAttacker.clientid].weapon = weapon;
4205  self.attackerDamage[eAttacker.clientid].time = getTime();
4206 
4207  self.attackers[ self.attackers.size ] = eAttacker;
4208 
4209  // we keep an array of attackers by their client ID so we can easily tell
4210  // if they're already one of the existing attackers in the above if().
4211  // we store in this array data that is useful for other things, like challenges
4212  self.attackerData[eAttacker.clientid] = false;
4213  }
4214  else
4215  {
4216  self.attackerDamage[eAttacker.clientid].damage += iDamage;
4217  self.attackerDamage[eAttacker.clientid].meansOfDeath = sMeansOfDeath;
4218  self.attackerDamage[eAttacker.clientid].weapon = weapon;
4219  if ( !isdefined( self.attackerDamage[eAttacker.clientid].time ) )
4220  self.attackerDamage[eAttacker.clientid].time = getTime();
4221  }
4222 
4223  if ( IsArray( self.attackersThisSpawn ) )
4224  {
4225  self.attackersThisSpawn[ eAttacker.clientid ] = eAttacker;
4226  }
4227 
4228  self.attackerDamage[eAttacker.clientid].lasttimedamaged = getTime();
4229  if ( ‪weapons::is_primary_weapon( weapon ) )
4230  self.attackerData[eAttacker.clientid] = true;
4231 }
4232 
4233 function ‪giveAttackerAndInflictorOwnerAssist( eAttacker, eInflictor, iDamage, sMeansOfDeath, weapon )
4234 {
4235  if ( !‪allowedAssistWeapon( weapon ) )
4236  return;
4237 
4238  self ‪trackAttackerDamage( eAttacker, iDamage, sMeansOfDeath, weapon );
4239 
4240  if ( !isdefined( eInflictor ) )
4241  return;
4242 
4243  if ( !isdefined( eInflictor.owner ) )
4244  return;
4245 
4246  if ( !isdefined( eInflictor.ownerGetsAssist ) )
4247  return;
4248 
4249  if ( !eInflictor.ownerGetsAssist )
4250  return;
4251 
4252  // if attacker and inflictor owner are the same no additional points
4253  // I dont ever know if they are different
4254  if ( isdefined( eAttacker ) && eAttacker == eInflictor.owner )
4255  return;
4256 
4257  self ‪trackAttackerDamage( eInflictor.owner, iDamage, sMeansOfDeath, weapon );
4258 }
4259 
4260 function ‪PlayerKilled_UpdateMeansOfDeath( attacker, eInflictor, weapon, sMeansOfDeath, sHitLoc )
4261 {
4262  if( ‪globallogic_utils::isHeadShot( weapon, sHitLoc, sMeansOfDeath, eInflictor ) && isPlayer( attacker ) && !weapon_utils::ismeleemod( sMeansOfDeath ) )
4263  {
4264  return "MOD_HEAD_SHOT";
4265  }
4266 
4267  // we do not want the melee icon to show up for dog attacks
4268  switch( weapon.name )
4269  {
4270  case "dog_bite":
4271  sMeansOfDeath = "MOD_PISTOL_BULLET";
4272  break;
4273  case "destructible_car":
4274  sMeansOfDeath = "MOD_EXPLOSIVE";
4275  break;
4276  case "explodable_barrel":
4277  sMeansOfDeath = "MOD_EXPLOSIVE";
4278  break;
4279  }
4280 
4281  return sMeansOfDeath;
4282 }
4283 
4284 function ‪updateAttacker( attacker, weapon )
4285 {
4286  if( isai(attacker) && isdefined( attacker.script_owner ) )
4287  {
4288  // if the person who called the dogs in switched teams make sure they don't
4289  // get penalized for the kill
4290  if ( !level.teambased || attacker.script_owner.team != self.team )
4291  attacker = attacker.script_owner;
4292  }
4293 
4294  if( attacker.classname == "script_vehicle" && isdefined( attacker.owner ) )
4295  {
4296  attacker notify("killed",self);
4297 
4298  attacker = attacker.owner;
4299  }
4300 
4301  if( isai(attacker) )
4302  attacker notify("killed",self);
4303 
4304  if ( ( isdefined ( self.capturingLastFlag ) ) && ( self.capturingLastFlag == true ) )
4305  {
4306  attacker.lastCapKiller = true;
4307  }
4308 
4309  if( isdefined( attacker ) && attacker != self && isdefined( weapon ) )
4310  {
4311  if ( weapon.name == "planemortar" )
4312  {
4313  ‪DEFAULT( attacker.planeMortarBda, 0 );
4314  attacker.planeMortarBda++;
4315  }
4316  else if( weapon.name == "dart" ||
4317  weapon.name == "dart_turret" )
4318  {
4319  ‪DEFAULT( attacker.dartBda, 0 );
4320  attacker.dartBda++;
4321  }
4322  else if( weapon.name == "straferun_rockets" || weapon.name == "straferun_gun")
4323  {
4324  if( isdefined( attacker.strafeRunbda ) )
4325  {
4326  attacker.strafeRunbda++;
4327  }
4328  }
4329  else if ( weapon.name == "remote_missile_missile" || weapon.name == "remote_missile_bomblet" )
4330  {
4331  ‪DEFAULT( attacker.remotemissileBda, 0 );
4332  attacker.remotemissileBda++;
4333  }
4334  }
4335 
4336  return attacker;
4337 }
4338 
4339 function ‪updateInflictor( eInflictor )
4340 {
4341  if( isdefined( eInflictor ) && eInflictor.classname == "script_vehicle" )
4342  {
4343  eInflictor notify("killed",self);
4344 
4345  if ( isdefined( eInflictor.bda ) )
4346  {
4347  eInflictor.bda++;
4348  }
4349  }
4350 
4351  return eInflictor;
4352 }
4353 
4354 function ‪updateWeapon( eInflictor, weapon )
4355 {
4356  // explosive barrel/car detection
4357  if ( weapon == level.weaponNone && isdefined( eInflictor ) )
4358  {
4359  if ( isdefined( eInflictor.targetname ) && eInflictor.targetname == "explodable_barrel" )
4360  weapon = GetWeapon( "explodable_barrel" );
4361  else if ( isdefined( eInflictor.destructible_type ) && isSubStr( eInflictor.destructible_type, "vehicle_" ) )
4362  weapon = GetWeapon( "destructible_car" );
4363  }
4364 
4365  return weapon;
4366 }
4367 
4368 function ‪playKillBattleChatter( attacker, weapon, victim, eInflictor )
4369 {
4370  if( IsPlayer( attacker ) )
4371  {
4372  if ( !‪killstreaks::is_killstreak_weapon( weapon ) )
4373  {
4374  level thread ‪battlechatter::say_kill_battle_chatter( attacker, weapon, victim, eInflictor );
4375  }
4376  }
4377 
4378  if( isdefined( eInflictor ) )
4379  {
4380  eInflictor notify( "bhtn_action_notify", "attack_kill" );
4381  }
4382 }
‪modify_player_damage_meansofdeath
‪function modify_player_damage_meansofdeath(eInflictor, eAttacker, sMeansOfDeath, weapon, sHitLoc)
Definition: _globallogic_player.gsc:1837
‪on_player_suicide_or_team_kill
‪function on_player_suicide_or_team_kill(player, type)
Definition: _battlechatter.gsc:356
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪can_process_contracts
‪function can_process_contracts()
Definition: _contracts.gsc:176
‪set_permissions
‪function set_permissions()
Definition: _spectating.gsc:98
‪gameRepPlayerDisconnected
‪function gameRepPlayerDisconnected()
Definition: _gamerep.gsc:222
‪player_damage_does_friendly_fire_damage_victim
‪function player_damage_does_friendly_fire_damage_victim(ignore_round_start_friendly_fire)
Definition: _globallogic_player.gsc:2044
‪waittillHostMigrationCountDown
‪function waittillHostMigrationCountDown()
Definition: hostmigration_shared.gsc:143
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪should_allow_postgame_death
‪function should_allow_postgame_death(sMeansOfDeath)
Definition: _globallogic_player.gsc:2983
‪unsetLightArmor
‪function unsetLightArmor()
Definition: _armor.gsc:62
‪IDFLAGS_SHIELD_EXPLOSIVE_IMPACT_HUGE
‪#define IDFLAGS_SHIELD_EXPLOSIVE_IMPACT_HUGE
Definition: shared.gsh:417
‪update_ffa_top_scorers
‪function update_ffa_top_scorers()
Definition: _globallogic_player.gsc:3773
‪should_drop_weapon_on_death
‪function should_drop_weapon_on_death(wasTeamKill, wasSuicide, current_weapon, sMeansOfDeath)
Definition: _globallogic_player.gsc:3825
‪getWeaponClass
‪function getWeaponClass(weapon)
Definition: util_shared.gsc:2676
‪updateAliveTimes
‪function updateAliveTimes(team)
Definition: _globallogic.gsc:3031
‪make_sure_damage_is_not_zero
‪function make_sure_damage_is_not_zero(iDamage)
Definition: _globallogic_player.gsc:1739
‪spectate_player_watcher
‪function spectate_player_watcher()
Definition: _globallogic_player.gsc:1271
‪set_music_on_player
‪function set_music_on_player(state, wait_time=0, save_state=false, return_state=false)
Definition: _globallogic_audio.gsc:1053
‪Callback_PlayerMigrated
‪function Callback_PlayerMigrated()
Definition: _globallogic_player.gsc:1343
‪processAssist
‪function processAssist(killedplayer, damagedone, weapon)
Definition: _globallogic_score.gsc:1582
‪updateAttacker
‪function updateAttacker(attacker, weapon)
Definition: _globallogic_player.gsc:4284
‪updateWeapon
‪function updateWeapon(eInflictor, weapon)
Definition: _globallogic_player.gsc:4354
‪playKillBattleChatter
‪function playKillBattleChatter(attacker, weapon, victim, eInflictor)
Definition: _globallogic_player.gsc:4368
‪cancel_on_use
‪function cancel_on_use()
Definition: _killcam.gsc:605
‪blank
‪function blank(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10)
Definition: _globallogic.gsc:333
‪upload_stats_soon
‪function upload_stats_soon()
Definition: persistence_shared.gsc:476
‪is_ricochet_protected
‪function is_ricochet_protected(player)
Definition: _killstreaks.gsc:3185
‪TeamKillKick
‪function TeamKillKick()
Definition: _globallogic_player.gsc:3883
‪is_bot
‪function is_bot()
Definition: util_shared.gsc:2488
‪should_override_entity_camera_in_demo
‪function should_override_entity_camera_in_demo(player, weapon)
Definition: _killstreaks.gsc:1409
‪figure_out_friendly_fire
‪function figure_out_friendly_fire(victim)
Definition: _globallogic_player.gsc:1614
‪GADGET_TYPE_HERO_WEAPON
‪#define GADGET_TYPE_HERO_WEAPON
Definition: _ability_util.gsh:18
‪decrementLastObituaryPlayerCountAfterFade
‪function decrementLastObituaryPlayerCountAfterFade()
Definition: scoreevents_shared.gsc:161
‪set_after_action_report_stat
‪function set_after_action_report_stat(statName, value, index)
Definition: persistence_shared.gsc:404
‪do_post_game_death
‪function do_post_game_death(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
Definition: _globallogic_player.gsc:2991
‪showPerks
‪function showPerks()
Definition: hud_util_shared.gsc:904
‪PlayerKilled_Kill
‪function PlayerKilled_Kill(eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc)
Definition: _globallogic_player.gsc:2845
‪IgnoreTeamKills
‪function IgnoreTeamKills(weapon, sMeansOfDeath, eInflictor)
Definition: _globallogic_player.gsc:3967
‪player_killed
‪function player_killed(attacker, killstreakType)
Definition: _battlechatter.gsc:477
‪record_settings
‪function record_settings(spectatorclient, targetentityindex, weapon, meansOfDeath, deathTime, deathTimeOffset, offsettime, killcam_entity_info, perks, killstreaks, attacker)
Definition: _killcam.gsc:86
‪player_is_occupant_invulnerable
‪function player_is_occupant_invulnerable(sMeansOfDeath)
Definition: _vehicle.gsc:1100
‪forceEnd
‪function forceEnd(hostsucks)
Definition: _globallogic.gsc:643
‪updateGlobalBotKilledCounter
‪function updateGlobalBotKilledCounter()
Definition: _globallogic_player.gsc:3845
‪timeUntilRoundEnd
‪function timeUntilRoundEnd()
Definition: _globallogic_utils.gsc:80
‪detach_carry_object_model
‪function detach_carry_object_model()
Definition: weapons_shared.gsc:43
‪modify_player_damage
‪function modify_player_damage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex)
Definition: _globallogic_player.gsc:1767
‪doPerkFeedBack
‪function doPerkFeedBack(player, weapon, sMeansOfDeath, eInflictor, armor_damaged)
Definition: _globallogic_player.gsc:2400
‪recordEndGameComScoreEventForPlayer
‪function recordEndGameComScoreEventForPlayer(player, result)
Definition: _globallogic_player.gsc:110
‪MP_CONTRACT_WEEKLY_SLOT_A
‪#define MP_CONTRACT_WEEKLY_SLOT_A
Definition: _contracts.gsh:12
‪player_contract_event
‪function player_contract_event(event_name, param1=undefined, param2=undefined, param3=undefined)
Definition: _util.gsc:1161
‪get_contract_stat
‪function get_contract_stat(slot, stat_name)
Definition: _contracts.gsc:462
‪waittill_any_return
‪function waittill_any_return(string1, string2, string3, string4, string5, string6, string7)
Definition: util_shared.csc:212
‪apply_damage_to_armor
‪function apply_damage_to_armor(eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, sHitLoc, friendlyFire, ignore_round_start_friendly_fire)
Definition: _globallogic_player.gsc:1691
‪cointoss
‪function cointoss()
Definition: math_shared.csc:171
‪resetAttackersThisSpawnList
‪function resetAttackersThisSpawnList()
Definition: _globallogic_player.gsc:2395
‪VAL
‪#define VAL(__var, __default)
Definition: shared.gsh:272
‪GESTURE_TYPE_THREATEN
‪#define GESTURE_TYPE_THREATEN
Definition: _globallogic_player.gsc:66
‪player_monitor_swimming
‪function player_monitor_swimming()
Definition: _globallogic_player.gsc:474
‪setShoutcasterWaitingMessage
‪function setShoutcasterWaitingMessage()
Definition: hud_message_shared.gsc:517
‪isFlashOrStunDamage
‪function isFlashOrStunDamage(weapon, meansofdeath)
Definition: _weapon_utils.gsc:18
‪Callback_PlayerKilled
‪function Callback_PlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, enteredResurrect=false)
Definition: _globallogic_player.gsc:3020
‪getArmor
‪function getArmor()
Definition: _armor.gsc:84
‪getTweakableValue
‪function getTweakableValue(category, name)
Definition: _tweakables.gsc:12
‪WaitTillKillStreakDone
‪function WaitTillKillStreakDone()
Definition: _globallogic_player.gsc:3854
‪finishPlayerDamageWrapper
‪function finishPlayerDamageWrapper(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal)
Definition: _globallogic_player.gsc:2441
‪freezePlayerForRoundEnd
‪function freezePlayerForRoundEnd()
Definition: _globallogic_player.gsc:81
‪PlayerKilled_Killstreaks
‪function PlayerKilled_Killstreaks(attacker, weapon)
Definition: _globallogic_player.gsc:2484
‪within_fov
‪function within_fov(start_origin, start_angles, end_origin, fov)
Definition: _util.gsc:56
‪setInflictorStat
‪function setInflictorStat(eInflictor, eAttacker, weapon)
Definition: _globallogic_score.gsc:1513
‪is_contract_active
‪function is_contract_active(challenge_index)
Definition: _contracts.gsc:211
‪updateInflictor
‪function updateInflictor(eInflictor)
Definition: _globallogic_player.gsc:4339
‪freeze_player_controls
‪function freeze_player_controls(b_frozen=true)
Definition: util_shared.gsc:2474
‪allowedAssistWeapon
‪function allowedAssistWeapon(weapon)
Definition: _globallogic_player.gsc:2473
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪gameHistoryPlayerKicked
‪function gameHistoryPlayerKicked()
Definition: _globallogic.gsc:1394
‪does_player_completely_avoid_damage
‪function does_player_completely_avoid_damage(iDFlags, sHitLoc, weapon, friendlyFire, attackerIsHittingSelf, sMeansOfDeath)
Definition: _globallogic_player.gsc:2106
‪isExplosiveDamage
‪function isExplosiveDamage(meansofdeath)
Definition: _loadout.gsc:1371
‪trackAttackerDamage
‪function trackAttackerDamage(eAttacker, iDamage, sMeansOfDeath, weapon)
Definition: _globallogic_player.gsc:4187
‪SQR
‪#define SQR(__var)
Definition: shared.gsh:293
‪gameRepPlayerConnected
‪function gameRepPlayerConnected()
Definition: _gamerep.gsc:186
‪reset_killstreak_delay_killcam
‪function reset_killstreak_delay_killcam()
Definition: _killstreaks.gsc:2451
‪player_damage_log
‪function player_damage_log(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex)
Definition: _globallogic_player.gsc:2131
‪updateAllAliveTimes
‪function updateAllAliveTimes()
Definition: _globallogic.gsc:3094
‪backupAndClearWinStreaks
‪function backupAndClearWinStreaks()
Definition: _globallogic_score.gsc:1311
‪add
‪function add(entity, dyingplayer, team, timeout)
Definition: _deathicons.gsc:43
‪should_do_player_damage
‪function should_do_player_damage(eAttacker, weapon, sMeansOfDeath, iDFlags)
Definition: _globallogic_player.gsc:1651
‪power_loss_event_took_damage
‪function power_loss_event_took_damage(eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage)
Definition: _ability_power.gsc:166
‪TakingBurnDamage
‪function TakingBurnDamage(eAttacker, weapon, sMeansOfDeath)
Definition: _burnplayer.gsc:34
‪player_monitor_slide
‪function player_monitor_slide()
Definition: _globallogic_player.gsc:502
‪clearShoutcasterWaitingMessage
‪function clearShoutcasterWaitingMessage()
Definition: hud_message_shared.gsc:530
‪isUsingRemote
‪function isUsingRemote()
Definition: util_shared.gsc:2705
‪IsEnemyPlayer
‪function IsEnemyPlayer(player)
Definition: util_shared.csc:1220
‪player_damage_riotshield_hit
‪function player_damage_riotshield_hit(eAttacker, iDamage, sMeansOfDeath, weapon, attackerIsHittingTeammate)
Definition: _globallogic_player.gsc:2067
‪player_monitor_travel_dist
‪function player_monitor_travel_dist()
Definition: _globallogic_player.gsc:368
‪player_monitor_wall_run
‪function player_monitor_wall_run()
Definition: _globallogic_player.gsc:446
‪giveAttackerAndInflictorOwnerAssist
‪function giveAttackerAndInflictorOwnerAssist(eAttacker, eInflictor, iDamage, sMeansOfDeath, weapon)
Definition: _globallogic_player.gsc:4233
‪IDFLAGS_NO_KNOCKBACK
‪#define IDFLAGS_NO_KNOCKBACK
Definition: shared.gsh:413
‪ArrayToString
‪function ArrayToString(inputArray)
Definition: _globallogic_player.gsc:97
‪get_killstreak_for_weapon
‪function get_killstreak_for_weapon(weapon)
Definition: _killstreaks.gsc:1357
‪isHeadShot
‪function isHeadShot(weapon, sHitLoc, sMeansOfDeath, eInflictor)
Definition: _globallogic_utils.gsc:397
‪get_killstreak_for_weapon_for_stats
‪function get_killstreak_for_weapon_for_stats(weapon)
Definition: _killstreaks.gsc:1365
‪createDeadBody
‪function createDeadBody(attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, vDir, vAttackerOrigin, deathAnimDuration, eInflictor, body)
Definition: _globallogic_player.gsc:4004
‪IncrementMatchCompletionStat
‪function IncrementMatchCompletionStat(gameMode, playedOrHosted, stat)
Definition: _globallogic.gsc:1119
‪player_damage_update_attacker
‪function player_damage_update_attacker(eInflictor, eAttacker, sMeansOfDeath)
Definition: _globallogic_player.gsc:1855
‪IDFLAGS_PENETRATION
‪#define IDFLAGS_PENETRATION
Definition: shared.gsh:414
‪figure_out_attacker
‪function figure_out_attacker(eAttacker)
Definition: _globallogic_player.gsc:1557
‪gadget_power_armor_on
‪function gadget_power_armor_on()
Definition: _ability_util.gsc:145
‪kickIfDontSpawn
‪function kickIfDontSpawn()
Definition: _globallogic_spawn.gsc:619
‪suicide
‪function suicide()
Definition: _vehicle.gsc:1309
‪Callback_PlayerDamage
‪function Callback_PlayerDamage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal)
Definition: _globallogic_player.gsc:2186
‪TimeUntilSpawn
‪function TimeUntilSpawn(includeTeamkillDelay)
Definition: _globallogic_spawn.gsc:37
‪listenForGameEnd
‪function listenForGameEnd()
Definition: _globallogic.gsc:3950
‪is_killstreak_weapon_assist_allowed
‪function is_killstreak_weapon_assist_allowed(weapon)
Definition: _killstreaks.gsc:1380
‪MP_CONTRACT_WEEKLY_SLOT_B
‪#define MP_CONTRACT_WEEKLY_SLOT_B
Definition: _contracts.gsh:13
‪DEFAULT
‪#define DEFAULT(__var, __default)
Definition: shared.gsh:270
‪player_damage_is_friendly_fire_at_round_start
‪function player_damage_is_friendly_fire_at_round_start()
Definition: _globallogic_player.gsc:2004
‪PlayerKilled_UpdateMeansOfDeath
‪function PlayerKilled_UpdateMeansOfDeath(attacker, eInflictor, weapon, sMeansOfDeath, sHitLoc)
Definition: _globallogic_player.gsc:4260
‪hostMigrationTimerThink
‪function hostMigrationTimerThink()
Definition: hostmigration_shared.gsc:180
‪killstreakTen
‪function killstreakTen()
Definition: challenges_shared.gsc:1444
‪drop_for_death
‪function drop_for_death(attacker, sWeapon, sMeansOfDeath)
Definition: _weapons.gsc:306
‪notifyConnecting
‪function notifyConnecting()
Definition: _globallogic_player.gsc:4134
‪updateTeamStatus
‪function updateTeamStatus()
Definition: _globallogic.gsc:2920
‪GetCurrentGameMode
‪function GetCurrentGameMode()
Definition: util_shared.gsc:3750
‪delayStartRagdoll
‪function delayStartRagdoll(ent, sHitLoc, vDir, weapon, eInflictor, sMeansOfDeath)
Definition: _globallogic_player.gsc:4147
‪_setPlayerScore
‪function _setPlayerScore(player, score)
Definition: _globallogic_score.gsc:519
‪DoWeaponSpecificKillEffects
‪function DoWeaponSpecificKillEffects(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _globallogic.gsc:4151
‪is_primary_weapon
‪function is_primary_weapon(weapon)
Definition: weapons_shared.gsc:15
‪UpdatePlayerKilled
‪function UpdatePlayerKilled(attacker, victim)
Definition: _behavior_tracker.gsc:183
‪_getPlayerScore
‪function _getPlayerScore(player)
Definition: _globallogic_score.gsc:538
‪player_damage_figure_out_weapon
‪function player_damage_figure_out_weapon(weapon, eInflictor)
Definition: _globallogic_player.gsc:1580
‪getTimePassed
‪function getTimePassed()
Definition: _globallogic_utils.gsc:274
‪doDamageFeedback
‪function doDamageFeedback(weapon, eInflictor, iDamage, sMeansOfDeath)
Definition: _globallogic_player.gsc:1135
‪is_killstreak_weapon
‪function is_killstreak_weapon(weapon)
Definition: killstreaks_shared.gsc:16
‪killed_by_sniper
‪function killed_by_sniper(sniper)
Definition: _battlechatter.gsc:432
‪player_monitor_inactivity
‪function player_monitor_inactivity()
Definition: _globallogic_player.gsc:555
‪player_damage_does_friendly_fire_damage_attacker
‪function player_damage_does_friendly_fire_damage_attacker(eAttacker, ignore_round_start_friendly_fire)
Definition: _globallogic_player.gsc:2015
‪waitForTimeOrNotify
‪function waitForTimeOrNotify(time, notifyname)
Definition: _globallogic_utils.gsc:378
‪incKillstreakTracker
‪function incKillstreakTracker(weapon)
Definition: _globallogic_score.gsc:1340
‪reduceTeamKillsOverTime
‪function reduceTeamKillsOverTime()
Definition: _globallogic_player.gsc:3946
‪PlayerKilled_TeamKill
‪function PlayerKilled_TeamKill(eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc)
Definition: _globallogic_player.gsc:2743
‪bbPlayerMatchEnd
‪function bbPlayerMatchEnd(gameLength, endReasonString, gameOver)
Definition: _globallogic.gsc:2417
‪Finalize
‪function Finalize()
Definition: _behavior_tracker.gsc:56
‪showMainMenuForTeam
‪function showMainMenuForTeam()
Definition: _globallogic_ui.gsc:461
‪Callback_PlayerMelee
‪function Callback_PlayerMelee(eAttacker, iDamage, weapon, vOrigin, vDir, boneIndex, shieldHit, fromBehind)
Definition: _globallogic_player.gsc:1477
‪record_misc_player_stats
‪function record_misc_player_stats()
Definition: _globallogic_player.gsc:1228
‪playerkilled_watch_death
‪function playerkilled_watch_death(weapon, sMeansOfDeath, deathAnimDuration)
Definition: _globallogic_player.gsc:3803
‪PlayerKilled_Obituary
‪function PlayerKilled_Obituary(attacker, eInflictor, weapon, sMeansOfDeath)
Definition: _globallogic_player.gsc:2615
‪modify_player_damage_friendlyfire
‪function modify_player_damage_friendlyfire(iDamage)
Definition: _globallogic_player.gsc:1754
‪giveKillStats
‪function giveKillStats(sMeansOfDeath, weapon, eVictim)
Definition: _globallogic_score.gsc:1475
‪IDFLAGS_SHIELD_EXPLOSIVE_SPLASH
‪#define IDFLAGS_SHIELD_EXPLOSIVE_SPLASH
Definition: shared.gsh:418
‪trackAttackeeDeath
‪function trackAttackeeDeath(attackerName, rank, xp, prestige, xuid)
Definition: _globallogic_score.gsc:1424
‪isAIKillstreakDamage
‪function isAIKillstreakDamage(weapon, eInflictor)
Definition: _globallogic_player.gsc:2428
‪isRoundBased
‪function isRoundBased()
Definition: util_shared.gsc:3742
‪should_give_killstreak
‪function should_give_killstreak(weapon)
Definition: _killstreaks.gsc:1780
‪start_death_from_above_ragdoll
‪function start_death_from_above_ragdoll(dir)
Definition: _globallogic_player.gsc:4122
‪player_is_spawn_protected_from_explosive
‪function player_is_spawn_protected_from_explosive(eInflictor, weapon, sMeansOfDeath)
Definition: _globallogic_player.gsc:1872
‪flush_leader_dialog_key_on_player
‪function flush_leader_dialog_key_on_player(dialogKey)
Definition: _globallogic_audio.gsc:258
‪stat_set_with_gametype
‪function stat_set_with_gametype(dataName, value, incValue)
Definition: persistence_shared.gsc:249
‪Callback_PlayerDisconnect
‪function Callback_PlayerDisconnect()
Definition: _globallogic_player.gsc:1360
‪add_to_killstreak_count
‪function add_to_killstreak_count(weapon)
Definition: _killstreaks.gsc:1751
‪isRegisteredEvent
‪function isRegisteredEvent(type)
Definition: scoreevents_shared.gsc:152
‪is_spawn_protected
‪function is_spawn_protected()
Definition: player_shared.gsc:364
‪playerKilled
‪function playerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, sHitLoc, attackerStance, bledOut)
Definition: challenges_shared.gsc:1506
‪on_damage
‪function on_damage(cause, damage, weapon)
Definition: _shellshock.gsc:27
‪PlayerKilled_AwardAssists
‪function PlayerKilled_AwardAssists(eInflictor, attacker, weapon, lpattackteam)
Definition: _globallogic_player.gsc:2809
‪Callback_PlayerConnect
‪function Callback_PlayerConnect()
Definition: _globallogic_player.gsc:577
‪isPlayerImmuneToKillstreak
‪function isPlayerImmuneToKillstreak(eAttacker, weapon)
Definition: _globallogic_player.gsc:1636
‪MP_CONTRACT_DAILY_SLOT
‪#define MP_CONTRACT_DAILY_SLOT
Definition: _contracts.gsh:14
‪TAUNT_TYPE_FIRST_PLACE
‪#define TAUNT_TYPE_FIRST_PLACE
Definition: _globallogic_player.gsc:63
‪count_players
‪function count_players()
Definition: _teams.gsc:291
‪Callback_PlayerLastStand
‪function Callback_PlayerLastStand(eInflictor, eAttacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
Definition: _globallogic_player.gsc:3988
‪killcam
‪function killcam(attackerNum, targetNum, killcam_entity_info, weapon, meansOfDeath, deathTime, deathTimeOffset, offsetTime, respawn, maxtime, perks, killstreaks, attacker, keep_deathcam)
Definition: _killcam.gsc:234
‪canUpdateWeaponContractStats
‪function canUpdateWeaponContractStats(player)
Definition: _globallogic_score.gsc:1102
‪getPersStat
‪function getPersStat(dataName)
Definition: _globallogic_score.gsc:1018
‪start_explosive_ragdoll
‪function start_explosive_ragdoll(dir, weapon)
Definition: _globallogic_player.gsc:4087
‪processKillstreakAssists
‪function processKillstreakAssists(attacker, inflictor, weapon)
Definition: _globallogic_score.gsc:1647
‪bookmark
‪function bookmark(type, time, mainClientEnt, otherClientEnt, eventPriority, inflictorEnt, overrideEntityCamera, actorEnt)
Definition: demo_shared.gsc:25
‪get_killcam_entity_info
‪function get_killcam_entity_info(attacker, eInflictor, weapon)
Definition: _killcam.gsc:1067
‪getTotalTimePlayed
‪function getTotalTimePlayed(maxLength)
Definition: _globallogic.gsc:2389
‪isValidClass
‪function isValidClass(c)
Definition: _globallogic_utils.gsc:144
‪initPersStat
‪function initPersStat(dataName, record_stats)
Definition: _globallogic_score.gsc:1004
‪is_using_any_gadget
‪function is_using_any_gadget()
Definition: _ability_player.gsc:106
‪say_kill_battle_chatter
‪function say_kill_battle_chatter(attacker, weapon, victim, inflictor)
Definition: _battlechatter.gsc:513
‪vehicleCrush
‪function vehicleCrush()
Definition: _globallogic_vehicle.gsc:365
‪onSpawnPlayer
‪function onSpawnPlayer(predictedSpawn)
Definition: _spawning.gsc:688
‪DoWeaponSpecificCorpseEffects
‪function DoWeaponSpecificCorpseEffects(body, eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime)
Definition: _globallogic.gsc:4161
‪gadget_CheckHeroAbilityKill
‪function gadget_CheckHeroAbilityKill(attacker)
Definition: _ability_player.gsc:529
‪custom_gamemodes_modified_damage
‪function custom_gamemodes_modified_damage(victim, eAttacker, iDamage, sMeansOfDeath, weapon, eInflictor, sHitLoc)
Definition: _globallogic_player.gsc:1537
‪pain_vox
‪function pain_vox(meansofDeath)
Definition: _battlechatter.gsc:329
‪IDFLAGS_NO_PROTECTION
‪#define IDFLAGS_NO_PROTECTION
Definition: shared.gsh:425
‪trackAttackerKill
‪function trackAttackerKill(name, rank, xp, prestige, xuid, weapon)
Definition: _globallogic_score.gsc:1353
‪player_monitor_doublejump
‪function player_monitor_doublejump()
Definition: _globallogic_player.gsc:528
‪player_damage_update_explosive_info
‪function player_damage_update_explosive_info(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, psOffsetTime, boneIndex)
Definition: _globallogic_player.gsc:1911
‪record_global_mp_stats_for_player_at_match_end
‪function record_global_mp_stats_for_player_at_match_end()
Definition: _globallogic_player.gsc:1191
‪do_post_game_damage
‪function do_post_game_damage(eInflictor, eAttacker, iDamage, iDFlags, sMeansOfDeath, weapon, vPoint, vDir, sHitLoc, vDamageOrigin, psOffsetTime, boneIndex, vSurfaceNormal)
Definition: _globallogic_player.gsc:2174
‪isFireDamage
‪function isFireDamage(weapon, meansofdeath)
Definition: _loadout.gsc:1408
‪play_death_vox
‪function play_death_vox(body, attacker, weapon, meansOfDeath)
Definition: _battlechatter.gsc:844
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪GAMEMODE_WAGER_MATCH
‪#define GAMEMODE_WAGER_MATCH
Definition: shared.gsh:13
‪giveTeamScore
‪function giveTeamScore(event, team, player, victim)
Definition: _globallogic_score.gsc:727
‪killstreak_30_noscorestreaks
‪function killstreak_30_noscorestreaks()
Definition: _challenges.gsc:1681
‪PlayerLastStand
‪function PlayerLastStand(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, delayOverride)
Definition: _laststand.gsc:63
‪give_for_streak
‪function give_for_streak()
Definition: _killstreaks.gsc:498
‪PlayerKilled_WeaponStats
‪function PlayerKilled_WeaponStats(attacker, weapon, sMeansOfDeath, wasInLastStand, lastWeaponBeforeDroppingIntoLastStand, inflictor)
Definition: _globallogic_player.gsc:2546
‪bestweapon_kill
‪function bestweapon_kill(weapon)
Definition: _weapons.gsc:38
‪is_explosive_damage
‪function is_explosive_damage(mod)
Definition: _zm_utility.gsc:5294
‪leader_dialog
‪function leader_dialog(dialogKey, team, excludeList, objectiveKey, killstreakId, dialogBufferKey)
Definition: _globallogic_audio.gsc:435
‪GESTURE_TYPE_GOOD_GAME
‪#define GESTURE_TYPE_GOOD_GAME
Definition: _globallogic_player.gsc:65
‪ShouldTeamKillKick
‪function ShouldTeamKillKick(teamKillDelay)
Definition: _globallogic_player.gsc:3926
‪processShieldAssist
‪function processShieldAssist(killedplayer)
Definition: _globallogic_score.gsc:1558
‪record_global_mp_stats_for_player_at_match_start
‪function record_global_mp_stats_for_player_at_match_start()
Definition: _globallogic_player.gsc:1146
‪spawnQueuedClient
‪function spawnQueuedClient(dead_player_team, killer)
Definition: _globallogic_spawn.gsc:755
‪PlayerKilled_Suicide
‪function PlayerKilled_Suicide(eInflictor, attacker, sMeansOfDeath, weapon, sHitLoc)
Definition: _globallogic_player.gsc:2673
‪hasTacticalMask
‪function hasTacticalMask(player)
Definition: _loadout.gsc:1386
‪SuicideKick
‪function SuicideKick()
Definition: _globallogic_player.gsc:3870
‪setLastKilledBy
‪function setLastKilledBy(attacker)
Definition: medals_shared.gsc:31
‪update
‪function update()
Definition: _serversettings.gsc:71
‪GESTURE_TYPE_BOAST
‪#define GESTURE_TYPE_BOAST
Definition: _globallogic_player.gsc:67
‪updateObjectiveText
‪function updateObjectiveText()
Definition: _globallogic_ui.gsc:397
‪giveRankXP
‪function giveRankXP(type, value, devAdd)
Definition: rank_shared.gsc:594
‪record_special_move_data_for_life
‪function record_special_move_data_for_life(killer)
Definition: _globallogic_player.gsc:413
‪uninterruptedObitFeedKills
‪function uninterruptedObitFeedKills(attacker, weapon)
Definition: scoreevents_shared.gsc:141
‪updateLossStats
‪function updateLossStats(loser)
Definition: _globallogic_score.gsc:1186
‪incTotalKills
‪function incTotalKills(team)
Definition: _globallogic_score.gsc:1503
‪stat_get_with_gametype
‪function stat_get_with_gametype(dataName)
Definition: persistence_shared.gsc:198
‪removeDisconnectedPlayerFromPlacement
‪function removeDisconnectedPlayerFromPlacement()
Definition: _globallogic.gsc:2659
‪damageShellshockAndRumble
‪function damageShellshockAndRumble(eAttacker, eInflictor, weapon, sMeansOfDeath, iDamage)
Definition: _globallogic_player.gsc:3993
‪TeamKillDelay
‪function TeamKillDelay()
Definition: _globallogic_player.gsc:3915
‪result
‪function result(death, attacker, mod, weapon)
Definition: _zm_aat_blast_furnace.gsc:46
‪UpdatePlayerDamage
‪function UpdatePlayerDamage(attacker, victim, damage)
Definition: _behavior_tracker.gsc:132
‪setLightArmorHP
‪function setLightArmorHP(newValue)
Definition: _armor.gsc:13
‪IDFLAGS_POWER_ARMOR
‪#define IDFLAGS_POWER_ARMOR
Definition: shared.gsh:421
‪Initialize
‪function Initialize()
Definition: _behavior_tracker.gsc:37
‪should_allow_postgame_damage
‪function should_allow_postgame_damage(sMeansOfDeath)
Definition: _globallogic_player.gsc:2166
‪cac_modified_damage
‪function cac_modified_damage(victim, attacker, damage, mod, weapon, inflictor, hitloc)
Definition: _loadout.gsc:1302
‪drop_scavenger_for_death
‪function drop_scavenger_for_death(attacker)
Definition: _weapons.gsc:1622
‪resetAttackerList
‪function resetAttackerList()
Definition: _globallogic_player.gsc:2387
‪name
‪class GroundFx name
‪getRankXpStat
‪function getRankXpStat()
Definition: rank_shared.gsc:385
‪updateWeaponContractStart
‪function updateWeaponContractStart(player)
Definition: _globallogic_score.gsc:1116
‪wait_and_suicide
‪function wait_and_suicide()
Definition: _globallogic_player.gsc:2799
‪adjust_recent_stats
‪function adjust_recent_stats()
Definition: persistence_shared.gsc:265
‪chooseNextBestNemesis
‪function chooseNextBestNemesis()
Definition: _globallogic_player.gsc:1492
‪incPersStat
‪function incPersStat(dataName, increment, record_stats, includeGametype)
Definition: _globallogic_score.gsc:1024
‪IDFLAGS_SHIELD_EXPLOSIVE_IMPACT
‪#define IDFLAGS_SHIELD_EXPLOSIVE_IMPACT
Definition: shared.gsh:416
‪isMeleeMOD
‪function isMeleeMOD(mod)
Definition: _weapon_utils.gsc:23
‪on_joined_team
‪function on_joined_team()
Definition: _globallogic_player.gsc:72
‪is_explosive_ragdoll
‪function is_explosive_ragdoll(weapon, inflictor)
Definition: _globallogic_player.gsc:4059
‪clearLowerMessage
‪function clearLowerMessage(fadetime)
Definition: _util.gsc:166