1 #using scripts\codescripts\struct;
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;
13 #insert scripts\shared\shared.gsh;
14 #insert scripts\shared\version.gsh;
16 #using scripts\mp\gametypes\_globallogic;
17 #using scripts\mp\gametypes\_globallogic_spawn;
18 #using scripts\mp\gametypes\_spectating;
20 #using scripts\mp\_challenges;
21 #using scripts\mp\_util;
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" );
43 level.killcam = GetGametypeSetting(
"allowKillcam" );
44 level.finalkillcam = GetGametypeSetting(
"allowFinalKillcam" );
51 level.finalKillcamSettings = [];
55 foreach( team
in level.teams )
60 level.finalKillCam_winner = undefined;
61 level.finalKillCam_winnerPicked = undefined;
66 level.finalKillcamSettings[team] = SpawnStruct();
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;
86 function record_settings( spectatorclient, targetentityindex, weapon, meansOfDeath, deathTime, deathTimeOffset, offsettime, killcam_entity_info, perks, killstreaks, attacker )
88 if( isdefined( attacker ) && isdefined( attacker.team ) && isdefined( level.teams[attacker.team] ) )
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;
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;
122 foreach( team
in level.teams )
127 level.finalKillCam_winner = undefined;
128 level.finalKillCam_winnerPicked = undefined;
133 if ( level.finalKillCam_winnerPicked ===
true )
135 level waittill(
"final_killcam_done" );
141 if ( isdefined( level.sidebet ) && level.sidebet )
145 level notify(
"play_final_killcam" );
152 level waittill (
"play_final_killcam" );
154 LUINotifyEvent( &
"pre_killcam_transition" );
158 level.inFinalKillcam =
true;
161 if( isdefined( level.finalKillCam_winner ) )
163 winner = level.finalKillCam_winner;
168 if( !isdefined( level.finalKillcamSettings[ winning_team ].targetentityindex ) )
170 level.inFinalKillcam =
false;
171 level notify(
"final_killcam_done" );
175 attacker = level.finalKillcamSettings[ winning_team ].attacker;
176 if( isDefined( attacker ) && isDefined( attacker.archetype ) && ( attacker.archetype ==
"mannequin" ) )
178 level.inFinalKillcam =
false;
179 level notify(
"final_killcam_done" );
183 if ( isdefined ( attacker ) )
188 visionSetNaked( GetDvarString(
"mapname" ), 0.0 );
190 players = level.players;
191 for ( index = 0; index < players.size; index++ )
193 player = players[index];
194 player closeInGameMenu();
203 level notify(
"final_killcam_done" );
204 level.inFinalKillcam =
false;
214 players = level.players;
215 for ( index = 0; index < players.size; index++ )
217 player = players[index];
218 if ( isdefined( player.killcam ) )
227 self endon(
"begin_killcam");
231 level.numPlayersWaitingToEnterKillcam--;
251 self endon(
"disconnect");
252 self endon(
"spawned");
253 level endon(
"game_ended");
260 level.numPlayersWaitingToEnterKillcam++;
261 assert( level.numPlayersWaitingToEnterKillcam < 20 );
263 if ( level.numPlayersWaitingToEnterKillcam > 1 )
266 println(
"[KILLCAM] more than one client entering killcam this frame" );
269 wait 0.05 * (level.numPlayersWaitingToEnterKillcam - 1);
273 level.numPlayersWaitingToEnterKillcam--;
274 assert( level.numPlayersWaitingToEnterKillcam > -1 );
276 postDeathDelay = (getTime() - deathTime) / 1000;
277 predelay = postDeathDelay + deathTimeOffset;
294 killcamlength = camtime + postdelay;
297 if (isdefined(maxtime) && killcamlength > maxtime)
305 if (maxtime - camtime >= 1) {
307 postdelay = maxtime - camtime;
312 camtime = maxtime - 1;
316 killcamlength = camtime + postdelay;
319 killcamoffset = camtime + predelay;
321 self notify (
"begin_killcam", getTime() );
322 self util::clientnotify(
"sndDEDe" );
324 killcamstarttime = (gettime() - killcamoffset * 1000);
326 self.sessionstate =
"spectator";
327 self.spectatekillcam =
true;
328 self.spectatorclient = attackerNum;
329 self.killcamentity = -1;
331 self.killcamtargetentity = targetNum;
332 self.killcamweapon = weapon;
333 self.killcammod = meansOfDeath;
334 self.archivetime = killcamoffset;
335 self.killcamlength = killcamlength;
336 self.psoffsettime = offsetTime;
341 foreach( team
in level.teams )
343 self allowSpectateTeam(team,
true);
345 self allowSpectateTeam(
"freelook",
true);
346 self allowSpectateTeam(
"none",
true);
353 if (
self.archivetime <= predelay )
355 self.sessionstate =
"dead";
356 self.spectatorclient = -1;
357 self.killcamentity = -1;
358 self.archivetime = 0;
359 self.psoffsettime = 0;
360 self.spectatekillcam =
false;
362 self notify (
"end_killcam" );
375 if ( !(
self IsSplitscreen() ) && level.perksEnabled == 1 )
388 self waittill(
"end_killcam");
395 self.sessionstate =
"dead";
396 self.spectatorclient = -1;
397 self.killcamentity = -1;
398 self.archivetime = 0;
399 self.psoffsettime = 0;
400 self.spectatekillcam =
false;
405 self endon(
"disconnect");
406 self endon(
"end_killcam");
407 self endon(
"spawned");
412 self.killcamentity = killcamentityindex;
417 for ( index = 0; index < entity_info.entity_indexes.size; index++ )
419 delayms = entity_info.entity_spawntimes[index] - killcamstarttime - 100;
421 thread
set_entity(entity_info.entity_indexes[index], delayms );
432 self endon(
"disconnect");
433 self endon(
"end_killcam");
435 wait(
self.killcamlength - 0.05);
436 self notify(
"end_killcam");
441 self endon(
"disconnect");
442 self endon(
"end_killcam");
443 secondsUntilDeath = ( ( deathTime -
startTime ) / 1000 );
444 deathTime = getTime() + secondsUntilDeath * 1000;
447 wait( max(0, (secondsUntilDeath - waitBeforeDeath) ) );
451 setSlowMotion( 1.0, 0.25, waitBeforeDeath );
452 wait( waitBeforeDeath + .5 );
453 setSlowMotion( 0.25, 1, 1.0 );
460 self endon(
"disconnect");
461 self endon(
"end_killcam");
463 while(
self useButtonPressed())
466 while(!(
self useButtonPressed()))
469 if( isdefined(
self.killcamsSkipped) )
471 self.killcamsSkipped++;
475 self.killcamsSkipped = 1;
478 self notify(
"end_killcam");
486 self endon(
"disconnect");
487 self endon(
"end_killcam");
489 self waittill(
"changed_class");
497 self endon(
"disconnect");
498 self endon(
"end_killcam");
500 while(
self fragButtonPressed())
503 while(!(
self fragButtonPressed()))
506 self.wantSafeSpawn =
true;
508 self notify(
"end_killcam");
513 if(isdefined(
self.kc_skiptext))
514 self.kc_skiptext.alpha = 0;
515 if(isdefined(
self.kc_timer))
516 self.kc_timer.alpha = 0;
518 self.killcam = undefined;
525 self endon(
"disconnect");
526 self endon(
"end_killcam");
533 if (
self.archivetime <= 0 )
538 self notify(
"end_killcam");
543 self endon(
"end_killcam");
544 self endon(
"disconnect");
546 self waittill(
"spawned");
552 self endon(
"end_killcam");
553 self endon(
"disconnect");
554 attacker endon (
"disconnect" );
556 attacker waittill (
"begin_killcam", attackerKcStartTime );
557 waitTime = max( 0, (attackerKcStartTime -
self.deathTime) - 50 );
564 self endon(
"end_killcam");
565 self endon(
"disconnect");
567 level waittill(
"game_ended");
572 self [[level.spawnIntermission]]( false );
577 self endon(
"end_killcam");
578 self endon(
"disconnect");
580 level waittill(
"game_ended");
586 return self useButtonPressed();
591 return self fragButtonPressed();
596 self.cancelKillcam =
true;
601 self.cancelKillcam =
true;
602 self.wantSafeSpawn =
true;
612 self endon (
"death_delay_finished" );
613 self endon (
"disconnect" );
614 level endon (
"game_ended" );
618 if ( !
self [[pressingButtonFunc]]() )
625 while(
self [[pressingButtonFunc]]() )
631 if ( buttonTime >= 0.5 )
636 while ( !
self [[pressingButtonFunc]]() && buttonTime < 0.5 )
642 if ( buttonTime >= 0.5 )
645 self [[finishedFunc]]();
654 killcamSettings = level.finalKillcamSettings[ winning_team ];
656 postDeathDelay = (getTime() - killcamSettings.deathTime) / 1000;
657 predelay = postDeathDelay + killcamSettings.deathTimeOffset;
661 camtime =
calc_time( killcamSettings.weapon, killcamentitystarttime, predelay,
false, undefined );
664 killcamoffset = camtime + predelay;
665 killcamlength = camtime + postdelay - 0.05;
667 killcamstarttime = (gettime() - killcamoffset * 1000);
669 self notify (
"begin_killcam", getTime() );
672 self.sessionstate =
"spectator";
673 self.spectatorclient = killcamSettings.spectatorclient;
674 self.killcamentity = -1;
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;
684 foreach( team
in level.teams )
686 self allowSpectateTeam(team,
true);
688 self allowSpectateTeam(
"freelook",
true);
689 self allowSpectateTeam(
"none",
true);
696 if (
self.archivetime <= predelay )
699 self.spectatorclient = -1;
700 self.killcamentity = -1;
701 self.archivetime = 0;
702 self.psoffsettime = 0;
703 self.spectatekillcam =
false;
705 self notify (
"end_killcam" );
714 if ( !(
self IsSplitscreen() ) )
722 self waittill(
"end_killcam");
727 self endon(
"disconnect");
728 level endon(
"game_ended");
732 setMatchFlag(
"final_killcam", 1 );
733 setMatchFlag(
"round_end_killcam", 0 );
737 setMatchFlag(
"final_killcam", 0 );
738 setMatchFlag(
"round_end_killcam", 1 );
748 LUINotifyEvent( &
"post_killcam_transition" );
750 self FreezeControls(
true );
756 setMatchFlag(
"final_killcam", 0 );
757 setMatchFlag(
"round_end_killcam", 0 );
765 [[level.spawnSpectator]]();
766 self FreezeControls(
true );
772 if ( weapon.name ==
"planemortar" )
785 if (GetDvarString(
"scr_killcam_time") ==
"")
789 camtime = (gettime() - entitystarttime) / 1000 - predelay - .1;
795 else if ( weapon.isGrenadeWeapon )
803 camtime = GetDvarfloat(
"scr_killcam_time");
805 if (isdefined(maxtime)) {
806 if (camtime > maxtime)
820 if (GetDvarString(
"scr_killcam_posttime") ==
"")
826 postdelay = GetDvarfloat(
"scr_killcam_posttime");
827 if (postdelay < 0.05)
846 if ( !isdefined(
self.kc_skiptext ) )
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;
856 self.kc_skiptext.font =
"default";
857 self.kc_skiptext.foreground =
true;
858 self.kc_skiptext.hideWhenInMenu =
true;
860 if (
self IsSplitscreen() )
862 self.kc_skiptext.y = 20;
863 self.kc_skiptext.fontscale = 1.2;
867 self.kc_skiptext.y = 32;
868 self.kc_skiptext.fontscale = 1.8;
872 if ( !isdefined(
self.kc_othertext ) )
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;
882 self.kc_othertext.font =
"small";
883 self.kc_othertext.foreground =
true;
884 self.kc_othertext.hideWhenInMenu =
true;
886 if (
self IsSplitscreen() )
888 self.kc_othertext.x = 16;
889 self.kc_othertext.fontscale = 1.2;
893 self.kc_othertext.x = 32;
894 self.kc_othertext.fontscale = 1.6;
898 if ( !isdefined(
self.kc_icon ) )
900 self.kc_icon = newClientHudElem(
self);
901 self.kc_icon.archived =
false;
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;
909 self.kc_icon.foreground =
true;
910 self.kc_icon.hideWhenInMenu =
true;
913 if ( !(
self IsSplitscreen() ) )
915 if ( !isdefined(
self.kc_timer ) )
918 self.kc_timer.archived =
false;
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;
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;
936 if ( !isdefined( depth ) )
939 closestKillcamEnt = undefined;
940 closestKillcamEntIndex = undefined;
941 closestKillcamEntDist = undefined;
944 foreach( killcamEntIndex, killcamEnt
in killCamEntities )
946 if ( killcamEnt == attacker )
949 origin = killcamEnt.origin;
950 if ( isdefined( killcamEnt.offsetPoint ) )
951 origin += killcamEnt.offsetPoint;
953 dist = DistanceSquared(
self.origin, origin );
955 if ( !isdefined( closestKillcamEnt ) || dist < closestKillcamEntDist )
957 closestKillcamEnt = killcamEnt;
958 closestKillcamEntDist = dist;
959 closestKillcamEntIndex = killcamEntIndex;
964 if ( depth < 3 && isdefined( closestKillcamEnt ) )
966 if ( !BulletTracePassed( closestKillcamEnt.origin,
self.origin,
false,
self ) )
968 killCamEntities[closestKillcamEntIndex] = undefined;
972 if ( isdefined( betterKillcamEnt ) )
974 closestKillcamEnt = betterKillcamEnt;
979 return closestKillcamEnt;
984 if ( !isdefined( eInflictor ) )
988 if ( isdefined(
self.killcamKilledByEnt) )
989 return self.killcamKilledByEnt;
991 if ( eInflictor == attacker )
993 if( !isdefined( eInflictor.isMagicBullet ) )
995 if( isdefined( eInflictor.isMagicBullet ) && !eInflictor.isMagicBullet )
998 else if ( isdefined( level.levelSpecificKillcam ) )
1000 levelSpecificKillcamEnt =
self [[level.levelSpecificKillcam]]();
1001 if ( isdefined( levelSpecificKillcamEnt ) )
1002 return levelSpecificKillcamEnt;
1005 if ( weapon.name ==
"hero_gravityspikes" )
1008 if ( isdefined( attacker ) && IsPlayer( attacker ) && attacker IsRemoteControlling() && ( eInflictor.controlled ===
true || eInflictor.occupied === true ) )
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" ) )
1019 if ( weapon.name ==
"dart" )
1022 if ( isdefined(eInflictor.killCamEnt) )
1025 if ( eInflictor.killCamEnt == attacker )
1028 return eInflictor.killCamEnt;
1030 else if ( isdefined(eInflictor.killCamEntities) )
1035 if ( isdefined( eInflictor.script_gameobjectname ) && eInflictor.script_gameobjectname ==
"bombzone" )
1036 return eInflictor.killCamEnt;
1043 if( !isdefined(entity) || !isdefined( entity.killcamentityindex ) )
1046 entity_info.entity_indexes[entity_info.entity_indexes.size] = entity.killcamentityindex;
1047 entity_info.entity_spawntimes[entity_info.entity_spawntimes.size] = entity.killcamentitystarttime;
1054 killcamentityindex = -1;
1056 if ( isdefined( killcamentity ) )
1058 killcamentityindex = killcamentity getEntityNumber();
1061 entity_info.entity_indexes[entity_info.entity_indexes.size] = killcamentityindex;
1062 entity_info.entity_spawntimes[entity_info.entity_spawntimes.size] = killcamentitystarttime;
1069 entity_info = SpawnStruct();
1071 entity_info.entity_indexes = [];
1072 entity_info.entity_spawntimes = [];
1081 if ( entity_info.entity_spawntimes.size == 0 )
1085 return entity_info.entity_spawntimes[entity_info.entity_spawntimes.size - 1];