‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_killcam.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\challenges_shared;
5 #using scripts\shared\clientfield_shared;
6 #using scripts\shared\killcam_shared;
7 #using scripts\shared\hud_util_shared;
8 #using scripts\shared\system_shared;
9 #using scripts\shared\util_shared;
10 #using scripts\shared\weapons\_tacticalinsertion;
11 #using scripts\shared\visionset_mgr_shared;
12 
13 #insert scripts\shared\shared.gsh;
14 #insert scripts\shared\version.gsh;
15 
16 #using scripts\mp\gametypes\_globallogic;
17 #using scripts\mp\gametypes\_globallogic_spawn;
18 #using scripts\mp\gametypes\_spectating;
19 
20 #using scripts\mp\_challenges;
21 #using scripts\mp\_util;
22 
23 #precache( "material", "white" );
24 #precache( "string", "PLATFORM_PRESS_TO_SKIP" );
25 #precache( "string", "PLATFORM_PRESS_TO_RESPAWN" );
26 #precache( "eventstring", "pre_killcam_transition" );
27 #precache( "eventstring", "post_killcam_transition" );
28 
29 #namespace killcam;
30 
31 ‪REGISTER_SYSTEM( "killcam", &‪__init__, undefined )
32 
33 function ‪__init__()
34 {
36  // clientuimodels are registered client-side in raw/ui/uieditor/clientfieldmodels.lua
37  ‪clientfield::register( "clientuimodel", "hudItems.killcamAllowRespawn", ‪VERSION_SHIP, 1, "int" );
38 }
39 
40 function ‪init()
41 {
42 
43  level.killcam = GetGametypeSetting( "allowKillcam" );
44  level.finalkillcam = GetGametypeSetting( "allowFinalKillcam" );
45 
47 }
48 
50 {
51  level.finalKillcamSettings = [];
52 
54 
55  foreach( team in level.teams )
56  {
58  }
59 
60  level.finalKillCam_winner = undefined;
61  level.finalKillCam_winnerPicked = undefined;
62 }
63 
65 {
66  level.finalKillcamSettings[team] = SpawnStruct();
67 
69 }
70 
72 {
73  level.finalKillcamSettings[team].spectatorclient = undefined;
74  level.finalKillcamSettings[team].weapon = undefined;
75  level.finalKillcamSettings[team].meansOfDeath = undefined;
76  level.finalKillcamSettings[team].deathTime = undefined;
77  level.finalKillcamSettings[team].deathTimeOffset = undefined;
78  level.finalKillcamSettings[team].offsettime = undefined;
79  level.finalKillcamSettings[team].killcam_entity_info = undefined;
80  level.finalKillcamSettings[team].targetentityindex = undefined;
81  level.finalKillcamSettings[team].perks = undefined;
82  level.finalKillcamSettings[team].killstreaks = undefined;
83  level.finalKillcamSettings[team].attacker = undefined;
84 }
85 
86 function ‪record_settings( spectatorclient, targetentityindex, weapon, meansOfDeath, deathTime, deathTimeOffset, offsettime, killcam_entity_info, perks, killstreaks, attacker )
87 {
88  if( isdefined( attacker ) && isdefined( attacker.team ) && isdefined( level.teams[attacker.team] ) )
89  {
90  team = attacker.team;
91 
92  level.finalKillcamSettings[ team ].spectatorclient = spectatorclient;
93  level.finalKillcamSettings[ team ].weapon = weapon;
94  level.finalKillcamSettings[ team ].meansOfDeath = meansOfDeath;
95  level.finalKillcamSettings[ team ].deathTime = deathTime;
96  level.finalKillcamSettings[ team ].deathTimeOffset = deathTimeOffset;
97  level.finalKillcamSettings[ team ].offsettime = offsettime;
98  level.finalKillcamSettings[ team ].killcam_entity_info = killcam_entity_info;
99  level.finalKillcamSettings[ team ].targetentityindex = targetentityindex;
100  level.finalKillcamSettings[ team ].perks = perks;
101  level.finalKillcamSettings[ team ].killstreaks = killstreaks;
102  level.finalKillcamSettings[ team ].attacker = attacker;
103  }
104 
105  level.finalKillcamSettings[ "none" ].spectatorclient = spectatorclient;
106  level.finalKillcamSettings[ "none" ].weapon = weapon;
107  level.finalKillcamSettings[ "none" ].meansOfDeath = meansOfDeath;
108  level.finalKillcamSettings[ "none" ].deathTime = deathTime;
109  level.finalKillcamSettings[ "none" ].deathTimeOffset = deathTimeOffset;
110  level.finalKillcamSettings[ "none" ].offsettime = offsettime;
111  level.finalKillcamSettings[ "none" ].killcam_entity_info = killcam_entity_info;
112  level.finalKillcamSettings[ "none" ].targetentityindex = targetentityindex;
113  level.finalKillcamSettings[ "none" ].perks = perks;
114  level.finalKillcamSettings[ "none" ].killstreaks = killstreaks;
115  level.finalKillcamSettings[ "none" ].attacker = attacker;
116 }
117 
119 {
120  ‪clear_final_killcam_team( "none" );
121 
122  foreach( team in level.teams )
123  {
125  }
126 
127  level.finalKillCam_winner = undefined;
128  level.finalKillCam_winnerPicked = undefined;
129 }
130 
132 {
133  if ( level.finalKillCam_winnerPicked === true )
134  {
135  level waittill( "final_killcam_done" );
136  }
137 }
138 
140 {
141  if ( isdefined( level.sidebet ) && level.sidebet )
142  {
143  return;
144  }
145  level notify( "play_final_killcam" );
148 }
149 
151 {
152  level waittill ( "play_final_killcam" );
153 
154  LUINotifyEvent( &"pre_killcam_transition" );
155 
156  wait( 0.35 );
157 
158  level.inFinalKillcam = true;
159 
160  winner = "none";
161  if( isdefined( level.finalKillCam_winner ) )
162  {
163  winner = level.finalKillCam_winner;
164  }
165 
166  winning_team = ‪globallogic::figureOutWinningTeam( winner );
167 
168  if( !isdefined( level.finalKillcamSettings[ winning_team ].targetentityindex ) )
169  {
170  level.inFinalKillcam = false;
171  level notify( "final_killcam_done" );
172  return;
173  }
174 
175  attacker = level.finalKillcamSettings[ winning_team ].attacker;
176  if( isDefined( attacker ) && isDefined( attacker.archetype ) && ( attacker.archetype == "mannequin" ) )
177  {
178  level.inFinalKillcam = false;
179  level notify( "final_killcam_done" );
180  return;
181  }
182 
183  if ( isdefined ( attacker ) )
184  {
185  ‪challenges::getFinalKill( attacker );
186  }
187 
188  visionSetNaked( GetDvarString( "mapname" ), 0.0 );
189 
190  players = level.players;
191  for ( index = 0; index < players.size; index++ )
192  {
193  player = players[index];
194  player closeInGameMenu();
195  player thread ‪final_killcam( winner );
196  }
197 
198  wait( 0.1 );
199 
200  while ( ‪are_any_players_watching() )
202 
203  level notify( "final_killcam_done" );
204  level.inFinalKillcam = false;
205 }
206 
208 {
209 }
210 
211 
213 {
214  players = level.players;
215  for ( index = 0; index < players.size; index++ )
216  {
217  player = players[index];
218  if ( isdefined( player.killcam ) )
219  return true;
220  }
221 
222  return false;
223 }
224 
226 {
227  self endon("begin_killcam");
228  self ‪util::waittill_any("disconnect","spawned");
229 
230  wait 0.05; // Allow all players entering killcam to increment 'level.numPlayersWaitingToEnterKillcam'
231  level.numPlayersWaitingToEnterKillcam--;
232 }
233 
234 function ‪killcam(
235  attackerNum, // entity number of the attacker
236  targetNum, // entity number of the target
237  killcam_entity_info, // struct containing killcam entity info
238  weapon, // killing weapon
239  meansOfDeath,
240  deathTime, // time when the player died
241  deathTimeOffset, // time between player death and beginning of killcam
242  offsetTime, // something to do with how far back in time the killer was seeing the world when he made the kill; latency related, sorta
243  ‪respawn, // will the player be allowed to respawn after the killcam?
244  maxtime, // time remaining until map ends; the killcam will never last longer than this. undefined = no limit
245  perks, // the perks the attacker had at the time of the kill
246  killstreaks, // the killstreaks the attacker had at the time of the kill
247  attacker, // entity object of attacker
248  keep_deathcam // remain in death-cam when the killcam ends
249 )
250 {
251  self endon("disconnect");
252  self endon("spawned");
253  level endon("game_ended");
254 
255  if(attackerNum < 0)
256  return;
257 
258  //this is to track and amortize number of killcams per frame
259  self thread ‪watch_for_skip_killcam();
260  level.numPlayersWaitingToEnterKillcam++;
261  assert( level.numPlayersWaitingToEnterKillcam < 20 );
262 
263  if ( level.numPlayersWaitingToEnterKillcam > 1 )
264  {
265  /#
266  println( "[KILLCAM] more than one client entering killcam this frame" );
267  #/
268 
269  wait 0.05 * (level.numPlayersWaitingToEnterKillcam - 1);
270  }
271 
272  wait 0.05; // Allow all players entering killcam to increment 'level.numPlayersWaitingToEnterKillcam'
273  level.numPlayersWaitingToEnterKillcam--;
274  assert( level.numPlayersWaitingToEnterKillcam > -1 );
275 
276  postDeathDelay = (getTime() - deathTime) / 1000;
277  predelay = postDeathDelay + deathTimeOffset;
278 
279  killcamentitystarttime = ‪get_killcam_entity_info_starttime( killcam_entity_info );
280 
281  camtime = ‪calc_time( weapon, killcamentitystarttime, predelay, ‪respawn, maxtime );
282  postdelay = ‪calc_post_delay();
283 
284  /* timeline:
285 
286  | camtime | postdelay |
287  | | predelay |
288 
289  ^ killcam start ^ player death ^ killcam end
290  ^ player starts watching killcam
291 
292  */
293 
294  killcamlength = camtime + postdelay;
295 
296  // don't let the killcam last past the end of the round.
297  if (isdefined(maxtime) && killcamlength > maxtime)
298  {
299  // first trim postdelay down to a minimum of 1 second.
300  // if that doesn't make it short enough, trim camtime down to a minimum of 1 second.
301  // if that's still not short enough, cancel the killcam.
302  if (maxtime < 2)
303  return;
304 
305  if (maxtime - camtime >= 1) {
306  // reduce postdelay so killcam ends at end of match
307  postdelay = maxtime - camtime;
308  }
309  else {
310  // distribute remaining time over postdelay and camtime
311  postdelay = 1;
312  camtime = maxtime - 1;
313  }
314 
315  // recalc killcamlength
316  killcamlength = camtime + postdelay;
317  }
318 
319  killcamoffset = camtime + predelay;
320 
321  self notify ( "begin_killcam", getTime() );
322  self util::clientnotify( "sndDEDe" );
323 
324  killcamstarttime = (gettime() - killcamoffset * 1000);
325 
326  self.sessionstate = "spectator";
327  self.spectatekillcam = true;
328  self.spectatorclient = attackerNum;
329  self.killcamentity = -1;
330  self thread ‪set_killcam_entities( killcam_entity_info, killcamstarttime );
331  self.killcamtargetentity = targetNum;
332  self.killcamweapon = weapon;
333  self.killcammod = meansOfDeath;
334  self.archivetime = killcamoffset;
335  self.killcamlength = killcamlength;
336  self.psoffsettime = offsetTime;
337 
338  //record_settings( attackerNum, targetNum, weapon, deathTime, deathTimeOffset, offsetTime, killcam_entity_info, perks, killstreaks, attacker );
339 
340  // ignore spectate permissions
341  foreach( team in level.teams )
342  {
343  self allowSpectateTeam(team, true);
344  }
345  self allowSpectateTeam("freelook", true);
346  self allowSpectateTeam("none", true);
347 
348  self thread ‪ended_killcam_cleanup();
349 
350  // wait till the next server frame to allow code a chance to update archivetime if it needs trimming
352 
353  if ( self.archivetime <= predelay ) // if we're not looking back in time far enough to even see the death, cancel
354  {
355  self.sessionstate = "dead";
356  self.spectatorclient = -1;
357  self.killcamentity = -1;
358  self.archivetime = 0;
359  self.psoffsettime = 0;
360  self.spectatekillcam = false;
361 
362  self notify ( "end_killcam" );
363 
364  return;
365  }
366 
367  self thread ‪check_for_abrupt_end();
368 
369  self.killcam = true;
370 
371  //self init_kc_elements();
372 
374 
375  if ( !( self IsSplitscreen() ) && level.perksEnabled == 1 )
376  {
377  self ‪add_timer(camtime);
378  self ‪hud::showPerks( );
379  }
380 
381  self thread ‪spawned_killcam_cleanup();
382  self thread ‪wait_skip_killcam_button();
383  self thread ‪wait_team_change_end_killcam();
384  //self thread wait_skip_killcam_safe_spawn_button();
385  self thread ‪wait_killcam_time();
387 
388  self waittill("end_killcam");
389 
390  self ‪end(false);
391 
392  if ( ‪IS_TRUE(keep_deathcam) )
393  return;
394 
395  self.sessionstate = "dead";
396  self.spectatorclient = -1;
397  self.killcamentity = -1;
398  self.archivetime = 0;
399  self.psoffsettime = 0;
400  self.spectatekillcam = false;
401 }
402 
403 function ‪set_entity( killcamentityindex, delayms )
404 {
405  self endon("disconnect");
406  self endon("end_killcam");
407  self endon("spawned");
408 
409  if ( delayms > 0 )
410  wait delayms / 1000;
411 
412  self.killcamentity = killcamentityindex;
413 }
414 
415 function ‪set_killcam_entities( entity_info, killcamstarttime )
416 {
417  for ( index = 0; index < entity_info.entity_indexes.size; index++ )
418  {
419  delayms = entity_info.entity_spawntimes[index] - killcamstarttime - 100;
420 
421  thread ‪set_entity(entity_info.entity_indexes[index], delayms );
422 
423  // return if this entity spawned before the killcam start time
424  // we dont want any older entities
425  if ( delayms <=0 )
426  return;
427  }
428 }
429 
431 {
432  self endon("disconnect");
433  self endon("end_killcam");
434 
435  wait(self.killcamlength - 0.05);
436  self notify("end_killcam");
437 }
438 
440 {
441  self endon("disconnect");
442  self endon("end_killcam");
443  secondsUntilDeath = ( ( deathTime - ‪startTime ) / 1000 );
444  deathTime = getTime() + secondsUntilDeath * 1000;
445  waitBeforeDeath = 2;
446 
447  wait( max(0, (secondsUntilDeath - waitBeforeDeath) ) );
448 
449  ‪util::setClientSysState("levelNotify", "sndFKsl" );
450 
451  setSlowMotion( 1.0, 0.25, waitBeforeDeath ); // start timescale, end timescale, lerp duration
452  wait( waitBeforeDeath + .5 );
453  setSlowMotion( 0.25, 1, 1.0 );
454 
455  wait(.5);
456 }
457 
459 {
460  self endon("disconnect");
461  self endon("end_killcam");
462 
463  while(self useButtonPressed())
464  wait .05;
465 
466  while(!(self useButtonPressed()))
467  wait .05;
468 
469  if( isdefined( self.killcamsSkipped) )
470  {
471  self.killcamsSkipped++;
472  }
473  else
474  {
475  self.killcamsSkipped = 1;
476  }
477 
478  self notify("end_killcam");
479  self ‪util::clientNotify("fkce");
480 }
481 
482 
483 
485 {
486  self endon("disconnect");
487  self endon("end_killcam");
488 
489  self waittill("changed_class");
490 
491  ‪end( false );
492 }
493 
494 
496 {
497  self endon("disconnect");
498  self endon("end_killcam");
499 
500  while(self fragButtonPressed())
501  wait .05;
502 
503  while(!(self fragButtonPressed()))
504  wait .05;
505 
506  self.wantSafeSpawn = true;
507 
508  self notify("end_killcam");
509 }
510 
511 function ‪end( final )
512 {
513  if(isdefined(self.kc_skiptext))
514  self.kc_skiptext.alpha = 0;
515  if(isdefined(self.kc_timer))
516  self.kc_timer.alpha = 0;
517 
518  self.killcam = undefined;
519 
520  self thread ‪spectating::set_permissions();
521 }
522 
524 {
525  self endon("disconnect");
526  self endon("end_killcam");
527 
528  while(1)
529  {
530  // code may trim our archivetime to zero if there is nothing "recorded" to show.
531  // this can happen when the person we're watching in our killcam goes into killcam himself.
532  // in this case, end the killcam.
533  if ( self.archivetime <= 0 )
534  break;
535  wait .05;
536  }
537 
538  self notify("end_killcam");
539 }
540 
542 {
543  self endon("end_killcam");
544  self endon("disconnect");
545 
546  self waittill("spawned");
547  self ‪end(false);
548 }
549 
550 function ‪spectator_killcam_cleanup( attacker )
551 {
552  self endon("end_killcam");
553  self endon("disconnect");
554  attacker endon ( "disconnect" );
555 
556  attacker waittill ( "begin_killcam", attackerKcStartTime );
557  waitTime = max( 0, (attackerKcStartTime - self.deathTime) - 50 );
558  wait (waitTime);
559  self ‪end(false);
560 }
561 
563 {
564  self endon("end_killcam");
565  self endon("disconnect");
566 
567  level waittill("game_ended");
568 
569  self ‪end(false);
570 
571  // spawn at an intermission point
572  self [[level.spawnIntermission]]( false );
573 }
574 
576 {
577  self endon("end_killcam");
578  self endon("disconnect");
579 
580  level waittill("game_ended");
581  self ‪end(true);
582 }
583 
585 {
586  return self useButtonPressed();
587 }
588 
590 {
591  return self fragButtonPressed();
592 }
593 
595 {
596  self.cancelKillcam = true;
597 }
598 
600 {
601  self.cancelKillcam = true;
602  self.wantSafeSpawn = true;
603 }
604 
606 {
608 }
609 
610 function ‪cancel_on_use_specific_button( pressingButtonFunc, finishedFunc )
611 {
612  self endon ( "death_delay_finished" );
613  self endon ( "disconnect" );
614  level endon ( "game_ended" );
615 
616  for ( ;; )
617  {
618  if ( !self [[pressingButtonFunc]]() )
619  {
621  continue;
622  }
623 
624  buttonTime = 0;
625  while( self [[pressingButtonFunc]]() )
626  {
627  buttonTime += 0.05;
629  }
630 
631  if ( buttonTime >= 0.5 )
632  continue;
633 
634  buttonTime = 0;
635 
636  while ( !self [[pressingButtonFunc]]() && buttonTime < 0.5 )
637  {
638  buttonTime += 0.05;
640  }
641 
642  if ( buttonTime >= 0.5 )
643  continue;
644 
645  self [[finishedFunc]]();
646  return;
647  }
648 }
649 
650 function ‪final_killcam_internal( winner )
651 {
652  winning_team = ‪globallogic::figureOutWinningTeam( winner );
653 
654  killcamSettings = level.finalKillcamSettings[ winning_team ];
655 
656  postDeathDelay = (getTime() - killcamSettings.deathTime) / 1000;
657  predelay = postDeathDelay + killcamSettings.deathTimeOffset;
658 
659  killcamentitystarttime = ‪get_killcam_entity_info_starttime( killcamSettings.killcam_entity_info );
660 
661  camtime = ‪calc_time( killcamSettings.weapon, killcamentitystarttime, predelay, false, undefined );
662  postdelay = ‪calc_post_delay();
663 
664  killcamoffset = camtime + predelay;
665  killcamlength = camtime + postdelay - 0.05; // We do the -0.05 since we are doing a wait below.
666 
667  killcamstarttime = (gettime() - killcamoffset * 1000);
668 
669  self notify ( "begin_killcam", getTime() );
670  ‪util::setClientSysState("levelNotify", "sndFKs" );
671 
672  self.sessionstate = "spectator";
673  self.spectatorclient = killcamSettings.spectatorclient;
674  self.killcamentity = -1;
675  self thread ‪set_killcam_entities( killcamSettings.killcam_entity_info, killcamstarttime );
676  self.killcamtargetentity = killcamSettings.targetentityindex;
677  self.killcamweapon = killcamSettings.weapon;
678  self.killcammod = killcamSettings.meansOfDeath;
679  self.archivetime = killcamoffset;
680  self.killcamlength = killcamlength;
681  self.psoffsettime = killcamSettings.offsettime;
682 
683  // ignore spectate permissions
684  foreach( team in level.teams )
685  {
686  self allowSpectateTeam(team, true);
687  }
688  self allowSpectateTeam("freelook", true);
689  self allowSpectateTeam("none", true);
690 
691  self thread ‪ended_final_killcam_cleanup();
692 
693  // wait till the next server frame to allow code a chance to update archivetime if it needs trimming
695 
696  if ( self.archivetime <= predelay ) // if we're not looking back in time far enough to even see the death, cancel
697  {
698  // self.sessionstate = "dead"; // DO NOT SET to state "dead" in final killcam
699  self.spectatorclient = -1;
700  self.killcamentity = -1;
701  self.archivetime = 0;
702  self.psoffsettime = 0;
703  self.spectatekillcam = false;
704 
705  self notify ( "end_killcam" );
706 
707  return;
708  }
709 
710  self thread ‪check_for_abrupt_end();
711 
712  self.killcam = true;
713 
714  if ( !( self IsSplitscreen() ) )
715  {
716  self ‪add_timer(camtime);
717  }
718 
719  self thread ‪wait_killcam_time();
720  self thread ‪wait_final_killcam_slowdown( level.finalKillcamSettings[ winning_team ].deathTime, killcamstarttime );
721 
722  self waittill("end_killcam");
723 }
724 
725 function ‪final_killcam( winner )
726 {
727  self endon("disconnect");
728  level endon("game_ended");
729 
730  if ( ‪util::wasLastRound() )
731  {
732  setMatchFlag( "final_killcam", 1 );
733  setMatchFlag( "round_end_killcam", 0 );
734  }
735  else
736  {
737  setMatchFlag( "final_killcam", 0 );
738  setMatchFlag( "round_end_killcam", 1 );
739  }
740 
741  if( level.console )
743 
744  ‪final_killcam_internal( winner );
745 
746  ‪util::setClientSysState("levelNotify", "sndFKe" );
747 
748  LUINotifyEvent( &"post_killcam_transition" );
749 
750  self FreezeControls( true );
751 
752  wait 1.5;
753 
754  self ‪end(true);
755 
756  setMatchFlag( "final_killcam", 0 );
757  setMatchFlag( "round_end_killcam", 0 );
758 
760 }
761 
762 // This puts the player to the intermission point as a spectator once the killcam is over.
764 {
765  [[level.spawnSpectator]]();
766  self FreezeControls( true );
768 }
769 
770 function ‪is_entity_weapon( weapon )
771 {
772  if ( weapon.name == "planemortar" )
773  {
774  return true;
775  }
776 
777  return false;
778 }
779 
780 function ‪calc_time( weapon, entitystarttime, predelay, ‪respawn, maxtime )
781 {
782  camtime = 0.0;
783 
784  // length from killcam start to killcam end
785  if (GetDvarString( "scr_killcam_time") == "")
786  {
787  if ( ‪is_entity_weapon( weapon ) )
788  {
789  camtime = (gettime() - entitystarttime) / 1000 - predelay - .1;
790  }
791  else if ( !‪respawn ) // if we're not going to respawn, we can take more time to watch what happened
792  {
793  camtime = 5.0;
794  }
795  else if ( weapon.isGrenadeWeapon )
796  {
797  camtime = 4.25; // show long enough to see grenade thrown
798  }
799  else
800  camtime = 2.5;
801  }
802  else
803  camtime = GetDvarfloat( "scr_killcam_time");
804 
805  if (isdefined(maxtime)) {
806  if (camtime > maxtime)
807  camtime = maxtime;
808  if (camtime < .05)
809  camtime = .05;
810  }
811 
812  return camtime;
813 }
814 
816 {
817  postdelay = 0;
818 
819  // time after player death that killcam continues for
820  if (GetDvarString( "scr_killcam_posttime") == "")
821  {
822  postdelay = 2;
823  }
824  else
825  {
826  postdelay = GetDvarfloat( "scr_killcam_posttime");
827  if (postdelay < 0.05)
828  postdelay = 0.05;
829  }
830 
831  return postdelay;
832 }
833 
835 {
836  self ‪clientfield::set_player_uimodel( "hudItems.killcamAllowRespawn", ‪respawn );
837 }
838 
839 function ‪add_timer(camtime)
840 {
841 }
842 
843 
845 {
846  if ( !isdefined( self.kc_skiptext ) )
847  {
848  self.kc_skiptext = newClientHudElem(self);
849  self.kc_skiptext.archived = false;
850  self.kc_skiptext.x = 0;
851  self.kc_skiptext.alignX = "center";
852  self.kc_skiptext.alignY = "top";
853  self.kc_skiptext.horzAlign = "center_adjustable";
854  self.kc_skiptext.vertAlign = "top_adjustable";
855  self.kc_skiptext.sort = 1; // force to draw after the bars
856  self.kc_skiptext.font = "default";
857  self.kc_skiptext.foreground = true;
858  self.kc_skiptext.hideWhenInMenu = true;
859 
860  if ( self IsSplitscreen() )
861  {
862  self.kc_skiptext.y = 20;
863  self.kc_skiptext.fontscale = 1.2; // 1.8/1.5
864  }
865  else
866  {
867  self.kc_skiptext.y = 32;
868  self.kc_skiptext.fontscale = 1.8;
869  }
870  }
871 
872  if ( !isdefined( self.kc_othertext ) )
873  {
874  self.kc_othertext = newClientHudElem(self);
875  self.kc_othertext.archived = false;
876  self.kc_othertext.y = 48;
877  self.kc_othertext.alignX = "left";
878  self.kc_othertext.alignY = "top";
879  self.kc_othertext.horzAlign = "center";
880  self.kc_othertext.vertAlign = "middle";
881  self.kc_othertext.sort = 10; // force to draw after the bars
882  self.kc_othertext.font = "small";
883  self.kc_othertext.foreground = true;
884  self.kc_othertext.hideWhenInMenu = true;
885 
886  if ( self IsSplitscreen() )
887  {
888  self.kc_othertext.x = 16;
889  self.kc_othertext.fontscale = 1.2;
890  }
891  else
892  {
893  self.kc_othertext.x = 32;
894  self.kc_othertext.fontscale = 1.6;
895  }
896  }
897 
898  if ( !isdefined( self.kc_icon ) )
899  {
900  self.kc_icon = newClientHudElem(self);
901  self.kc_icon.archived = false;
902  self.kc_icon.x = 16;
903  self.kc_icon.y = 16;
904  self.kc_icon.alignX = "left";
905  self.kc_icon.alignY = "top";
906  self.kc_icon.horzAlign = "center";
907  self.kc_icon.vertAlign = "middle";
908  self.kc_icon.sort = 1; // force to draw after the bars
909  self.kc_icon.foreground = true;
910  self.kc_icon.hideWhenInMenu = true;
911  }
912 
913  if ( !( self IsSplitscreen() ) )
914  {
915  if ( !isdefined( self.kc_timer ) )
916  {
917  self.kc_timer = ‪hud::createFontString( "hudbig", 1.0 );
918  self.kc_timer.archived = false;
919  self.kc_timer.x = 0;
920  self.kc_timer.alignX = "center";
921  self.kc_timer.alignY = "middle";
922  self.kc_timer.horzAlign = "center_safearea";
923  self.kc_timer.vertAlign = "top_adjustable";
924  self.kc_timer.y = 42;
925  self.kc_timer.sort = 1; // force to draw after the bars
926  self.kc_timer.font = "hudbig";
927  self.kc_timer.foreground = true;
928  self.kc_timer.color = (0.85,0.85,0.85);
929  self.kc_timer.hideWhenInMenu = true;
930  }
931  }
932 }
933 
934 function ‪get_closest_killcam_entity( attacker, killCamEntities, depth )
935 {
936  if ( !isdefined( depth ) )
937  depth = 0;
938 
939  closestKillcamEnt = undefined;
940  closestKillcamEntIndex = undefined;
941  closestKillcamEntDist = undefined;
942  origin = undefined;
943 
944  foreach( killcamEntIndex, killcamEnt in killCamEntities )
945  {
946  if ( killcamEnt == attacker )
947  continue;
948 
949  origin = killcamEnt.origin;
950  if ( isdefined( killcamEnt.offsetPoint ) )
951  origin += killcamEnt.offsetPoint;
952 
953  dist = DistanceSquared( self.origin, origin );
954 
955  if ( !isdefined( closestKillcamEnt ) || dist < closestKillcamEntDist )
956  {
957  closestKillcamEnt = killcamEnt;
958  closestKillcamEntDist = dist;
959  closestKillcamEntIndex = killcamEntIndex;
960  }
961  }
962 
963  // check to see if the player is visible at time of death
964  if ( depth < 3 && isdefined( closestKillcamEnt ) )
965  {
966  if ( !BulletTracePassed( closestKillcamEnt.origin, self.origin, false, self ) )
967  {
968  killCamEntities[closestKillcamEntIndex] = undefined;
969 
970  betterKillcamEnt = ‪get_closest_killcam_entity( attacker, killCamEntities, depth + 1 );
971 
972  if ( isdefined( betterKillcamEnt ) )
973  {
974  closestKillcamEnt = betterKillcamEnt;
975  }
976  }
977  }
978 
979  return closestKillcamEnt;
980 }
981 
982 function ‪get_killcam_entity( attacker, eInflictor, weapon )
983 {
984  if ( !isdefined( eInflictor ) )
985  return undefined;
986 
987  // if there is a killcam entity stored on the player who died
988  if ( isdefined(self.killcamKilledByEnt) )
989  return self.killcamKilledByEnt;
990 
991  if ( eInflictor == attacker )
992  {
993  if( !isdefined( eInflictor.isMagicBullet ) )
994  return undefined;
995  if( isdefined( eInflictor.isMagicBullet ) && !eInflictor.isMagicBullet )
996  return undefined;
997  }
998  else if ( isdefined( level.levelSpecificKillcam ) )
999  {
1000  levelSpecificKillcamEnt = self [[level.levelSpecificKillcam]]();
1001  if ( isdefined( levelSpecificKillcamEnt ) )
1002  return levelSpecificKillcamEnt;
1003  }
1004 
1005  if ( weapon.name == "hero_gravityspikes" )
1006  return undefined;
1007 
1008  if ( isdefined( attacker ) && IsPlayer( attacker ) && attacker IsRemoteControlling() && ( eInflictor.controlled === true || eInflictor.occupied === true ) )
1009  {
1010  if ( ( weapon.name == "sentinel_turret" )
1011  || ( weapon.name == "helicopter_gunner_turret_primary" )
1012  || ( weapon.name == "helicopter_gunner_turret_secondary" )
1013  || ( weapon.name == "helicopter_gunner_turret_tertiary" )
1014  || ( weapon.name == "amws_gun_turret_mp_player" )
1015  || ( weapon.name == "auto_gun_turret" ) )
1016  return undefined;
1017  }
1018 
1019  if ( weapon.name == "dart" )
1020  return undefined;
1021 
1022  if ( isdefined(eInflictor.killCamEnt) )
1023  {
1024  // this is the case with the player helis
1025  if ( eInflictor.killCamEnt == attacker )
1026  return undefined;
1027 
1028  return eInflictor.killCamEnt;
1029  }
1030  else if ( isdefined(eInflictor.killCamEntities) )
1031  {
1032  return ‪get_closest_killcam_entity( attacker, eInflictor.killCamEntities );
1033  }
1034 
1035  if ( isdefined( eInflictor.script_gameobjectname ) && eInflictor.script_gameobjectname == "bombzone" )
1036  return eInflictor.killCamEnt;
1037 
1038  return eInflictor;
1039 }
1040 
1041 function ‪get_secondary_killcam_entity(entity, entity_info )
1042 {
1043  if( !isdefined(entity) || !isdefined( entity.killcamentityindex ) )
1044  return;
1045 
1046  entity_info.entity_indexes[entity_info.entity_indexes.size] = entity.killcamentityindex;
1047  entity_info.entity_spawntimes[entity_info.entity_spawntimes.size] = entity.killcamentitystarttime;
1048 }
1049 
1050 function ‪get_primary_killcam_entity(attacker, eInflictor, weapon, entity_info )
1051 {
1052  killcamentity = self ‪get_killcam_entity( attacker, eInflictor, weapon );
1053  killcamentitystarttime = ‪killcam::get_killcam_entity_start_time( killcamentity );
1054  killcamentityindex = -1;
1055 
1056  if ( isdefined( killcamentity ) )
1057  {
1058  killcamentityindex = killcamentity getEntityNumber(); // must do this before any waiting lest the entity be deleted
1059  }
1060 
1061  entity_info.entity_indexes[entity_info.entity_indexes.size] = killcamentityindex;
1062  entity_info.entity_spawntimes[entity_info.entity_spawntimes.size] = killcamentitystarttime;
1063 
1064  ‪get_secondary_killcam_entity( killcamentity, entity_info );
1065 }
1066 
1067 function ‪get_killcam_entity_info(attacker, eInflictor, weapon)
1068 {
1069  entity_info = SpawnStruct();
1070 
1071  entity_info.entity_indexes = [];
1072  entity_info.entity_spawntimes = [];
1073 
1074  ‪get_primary_killcam_entity(attacker, eInflictor, weapon, entity_info);
1075 
1076  return entity_info;
1077 }
1078 
1080 {
1081  if ( entity_info.entity_spawntimes.size == 0 )
1082  return 0;
1083 
1084  // the last one should be the oldest
1085  return entity_info.entity_spawntimes[entity_info.entity_spawntimes.size - 1];
1086 }
‪set_permissions
‪function set_permissions()
Definition: _spectating.gsc:98
‪startTime
‪class AnimationAdjustmentInfoZ startTime
‪startLastKillcam
‪function startLastKillcam()
Definition: _killcam.gsc:207
‪spectator_killcam_cleanup
‪function spectator_killcam_cleanup(attacker)
Definition: _killcam.gsc:550
‪calc_time
‪function calc_time(weapon, entitystarttime, predelay, respawn, maxtime)
Definition: _killcam.gsc:780
‪get_killcam_entity_start_time
‪function get_killcam_entity_start_time(killcamentity)
Definition: killcam_shared.gsc:6
‪cancel_on_use
‪function cancel_on_use()
Definition: _killcam.gsc:605
‪wait_team_change_end_killcam
‪function wait_team_change_end_killcam()
Definition: _killcam.gsc:484
‪player_shutdown
‪function player_shutdown()
Definition: visionset_mgr_shared.gsc:578
‪get_secondary_killcam_entity
‪function get_secondary_killcam_entity(entity, entity_info)
Definition: _killcam.gsc:1041
‪getFinalKill
‪function getFinalKill(player)
Definition: challenges_shared.gsc:746
‪wait_killcam_time
‪function wait_killcam_time()
Definition: _killcam.gsc:430
‪watch_for_skip_killcam
‪function watch_for_skip_killcam()
Definition: _killcam.gsc:225
‪is_entity_weapon
‪function is_entity_weapon(weapon)
Definition: _killcam.gsc:770
‪ended_final_killcam_cleanup
‪function ended_final_killcam_cleanup()
Definition: _killcam.gsc:575
‪setClientSysState
‪function setClientSysState(sSysName, sSysState, player)
Definition: util_shared.gsc:1369
‪showPerks
‪function showPerks()
Definition: hud_util_shared.gsc:904
‪record_settings
‪function record_settings(spectatorclient, targetentityindex, weapon, meansOfDeath, deathTime, deathTimeOffset, offsettime, killcam_entity_info, perks, killstreaks, attacker)
Definition: _killcam.gsc:86
‪add_timer
‪function add_timer(camtime)
Definition: _killcam.gsc:839
‪ended_killcam_cleanup
‪function ended_killcam_cleanup()
Definition: _killcam.gsc:562
‪on_start_gametype
‪function on_start_gametype(func, obj)
Definition: callbacks_shared.csc:285
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪cancel_on_use_specific_button
‪function cancel_on_use_specific_button(pressingButtonFunc, finishedFunc)
Definition: _killcam.gsc:610
‪respawn
‪function respawn()
Definition: _bot.gsc:184
‪get_closest_killcam_entity
‪function get_closest_killcam_entity(attacker, killCamEntities, depth)
Definition: _killcam.gsc:934
‪wait_final_killcam_slowdown
‪function wait_final_killcam_slowdown(deathTime, startTime)
Definition: _killcam.gsc:439
‪cancel_safe_spawn_button
‪function cancel_safe_spawn_button()
Definition: _killcam.gsc:589
‪final_killcam
‪function final_killcam(winner)
Definition: _killcam.gsc:725
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪cancel_button_think
‪function cancel_button_think()
Definition: _tacticalinsertion.gsc:328
‪post_round_final_killcam
‪function post_round_final_killcam()
Definition: _killcam.gsc:139
‪erase_final_killcam
‪function erase_final_killcam()
Definition: _killcam.gsc:118
‪set_entity
‪function set_entity(killcamentityindex, delayms)
Definition: _killcam.gsc:403
‪wasLastRound
‪function wasLastRound()
Definition: util_shared.gsc:3521
‪get_killcam_entity_info_starttime
‪function get_killcam_entity_info_starttime(entity_info)
Definition: _killcam.gsc:1079
‪do_final_killcam
‪function do_final_killcam()
Definition: _killcam.gsc:150
‪cancel_callback
‪function cancel_callback()
Definition: _killcam.gsc:594
‪setThirdPerson
‪function setThirdPerson(value)
Definition: _globallogic_spawn.gsc:1029
‪createFontString
‪function createFontString(font, fontScale)
Definition: hud_util_shared.gsc:334
‪set_killcam_entities
‪function set_killcam_entities(entity_info, killcamstarttime)
Definition: _killcam.gsc:415
‪figureOutWinningTeam
‪function figureOutWinningTeam(winner)
Definition: _globallogic.gsc:1877
‪init
‪function init()
Definition: _killcam.gsc:40
‪end
‪function end(final)
Definition: _killcam.gsc:511
‪init_final_killCam_team
‪function init_final_killCam_team(team)
Definition: _killcam.gsc:64
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪get_primary_killcam_entity
‪function get_primary_killcam_entity(attacker, eInflictor, weapon, entity_info)
Definition: _killcam.gsc:1050
‪final_killcam_waiter
‪function final_killcam_waiter()
Definition: _killcam.gsc:131
‪get_killcam_entity
‪function get_killcam_entity(attacker, eInflictor, weapon)
Definition: _killcam.gsc:982
‪add_skip_text
‪function add_skip_text(respawn)
Definition: _killcam.gsc:834
‪killcam
‪function killcam(attackerNum, targetNum, killcam_entity_info, weapon, meansOfDeath, deathTime, deathTimeOffset, offsetTime, respawn, maxtime, perks, killstreaks, attacker, keep_deathcam)
Definition: _killcam.gsc:234
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪get_killcam_entity_info
‪function get_killcam_entity_info(attacker, eInflictor, weapon)
Definition: _killcam.gsc:1067
‪init_kc_elements
‪function init_kc_elements()
Definition: _killcam.gsc:844
‪are_any_players_watching
‪function are_any_players_watching()
Definition: _killcam.gsc:212
‪wait_skip_killcam_button
‪function wait_skip_killcam_button()
Definition: _killcam.gsc:458
‪clientNotify
‪function clientNotify(event)
Definition: util_shared.gsc:1416
‪resetOutcomeForAllPlayers
‪function resetOutcomeForAllPlayers()
Definition: _globallogic.gsc:1728
‪spawned_killcam_cleanup
‪function spawned_killcam_cleanup()
Definition: _killcam.gsc:541
‪set_player_uimodel
‪function set_player_uimodel(str_field_name, n_value)
Definition: clientfield_shared.gsc:75
‪final_killcam_internal
‪function final_killcam_internal(winner)
Definition: _killcam.gsc:650
‪__init__
‪function __init__()
Definition: _killcam.gsc:33
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪spawn_end_of_final_killcam
‪function spawn_end_of_final_killcam()
Definition: _killcam.gsc:763
‪init_final_killCam
‪function init_final_killCam()
Definition: _killcam.gsc:49
‪cancel_safe_spawn_callback
‪function cancel_safe_spawn_callback()
Definition: _killcam.gsc:599
‪clear_final_killcam_team
‪function clear_final_killcam_team(team)
Definition: _killcam.gsc:71
‪cancel_use_button
‪function cancel_use_button()
Definition: _killcam.gsc:584
‪wait_skip_killcam_safe_spawn_button
‪function wait_skip_killcam_safe_spawn_button()
Definition: _killcam.gsc:495
‪check_for_abrupt_end
‪function check_for_abrupt_end()
Definition: _killcam.gsc:523
‪calc_post_delay
‪function calc_post_delay()
Definition: _killcam.gsc:815
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265