‪Black Ops 3 Source Code Explorer  0.1
‪An script explorer for Black Ops 3 by ZeRoY
_zm_laststand.gsc
Go to the documentation of this file.
1 #using scripts\codescripts\struct;
2 
3 #using scripts\shared\callbacks_shared;
4 #using scripts\shared\clientfield_shared;
5 #using scripts\shared\demo_shared;
6 #using scripts\shared\flag_shared;
7 #using scripts\shared\hud_util_shared;
8 #using scripts\shared\gameobjects_shared;
9 #using scripts\shared\laststand_shared;
10 #using scripts\shared\scoreevents_shared;
11 #using scripts\shared\system_shared;
12 #using scripts\shared\util_shared;
13 #using scripts\shared\visionset_mgr_shared;
14 
15 #insert scripts\shared\version.gsh;
16 #insert scripts\shared\shared.gsh;
17 
18 #using scripts\zm\_util;
19 #using scripts\zm\_zm_equipment;
20 #using scripts\zm\_zm_hero_weapon;
21 #using scripts\zm\_zm_perks;
22 #using scripts\zm\_zm_pers_upgrades_functions;
23 #using scripts\zm\_zm_stats;
24 #using scripts\zm\_zm_utility;
25 #using scripts\zm\_zm_weapons;
26 
27 #insert scripts\zm\_zm_laststand.gsh;
28 #insert scripts\zm\_zm_perks.gsh;
29 
30 #precache( "triggerstring", "ZOMBIE_BUTTON_TO_REVIVE_PLAYER" );
31 #precache( "string", "ZOMBIE_REVIVING" );
32 
33 #precache( "string", "ZOMBIE_PLAYER_IS_REVIVING_YOU", "ZOMBIE_PLAYER_NAME_0" );
34 #precache( "string", "ZOMBIE_PLAYER_IS_REVIVING_YOU", "ZOMBIE_PLAYER_NAME_1" );
35 #precache( "string", "ZOMBIE_PLAYER_IS_REVIVING_YOU", "ZOMBIE_PLAYER_NAME_2" );
36 #precache( "string", "ZOMBIE_PLAYER_IS_REVIVING_YOU", "ZOMBIE_PLAYER_NAME_3" );
37 
38 #define SHOW_LAST_STAND_PROGRESS_BAR false
39 
40 #namespace zm_laststand;
41 
42 #define N_REVIVE_VISIBILITY_DELAY 2.0 // Delay before a revived player becomes visible to zombies again
43 
44 ‪REGISTER_SYSTEM( "zm_laststand", &‪__init__, undefined )
45 
46 function ‪__init__()
47 {
49 
50 
51  //register clientfield for each person
52  level.laststand_update_clientfields = [];
53  for( i = 0; i < 4; i++ )
54  {
55  level.laststand_update_clientfields[i] = "laststand_update" + i;
56  ‪clientfield::register( "world", level.laststand_update_clientfields[i], ‪VERSION_SHIP, 5, "counter" );
57  }
58 
59 
60 
61  level.weaponSuicide = GetWeapon( "death_self" );
62 
63  level.primaryProgressBarX = 0;
64  level.primaryProgressBarY = 110;
65  level.primaryProgressBarHeight = 4;
66  level.primaryProgressBarWidth = 120;
67  level.primaryProgressBarY_ss = 280;
68 
69  if( GetDvarString( "revive_trigger_radius" ) == "" )
70  {
71  SetDvar( "revive_trigger_radius", "40" );
72  }
73 
74  level.lastStandGetupAllowed = false;
75 
76  ‪DEFAULT( level.vsmgr_prio_visionset_zm_laststand, 1000 );
77  ‪visionset_mgr::register_info( "visionset", ‪ZM_LASTSTAND_VISIONSET, ‪VERSION_SHIP, level.vsmgr_prio_visionset_zm_laststand, 31, true, &‪visionset_mgr::ramp_in_thread_per_player, false );
78 
79  ‪DEFAULT( level.vsmgr_prio_visionset_zm_death, 1100 );
80  ‪visionset_mgr::register_info( "visionset", ‪ZM_DEATH_VISIONSET, ‪VERSION_SHIP, level.vsmgr_prio_visionset_zm_death, 31, true, &‪visionset_mgr::ramp_in_thread_per_player, false );
81 }
82 
84 {
85  level.CONST_LASTSTAND_GETUP_COUNT_START = 0; // The number of laststands in type getup that the player starts with
86 
87  level.CONST_LASTSTAND_GETUP_BAR_START = 0.5; // Fill amount of the getup bar the first time it is used
88  level.CONST_LASTSTAND_GETUP_BAR_REGEN = 0.0025; // Percent of the bar filled for auto fill logic
89  level.CONST_LASTSTAND_GETUP_BAR_DAMAGE = 0.1; // Percent of the bar removed by AI damage
90 
91  level.player_name_directive=[];
92  level.player_name_directive[0] = &"ZOMBIE_PLAYER_NAME_0";
93  level.player_name_directive[1] = &"ZOMBIE_PLAYER_NAME_1";
94  level.player_name_directive[2] = &"ZOMBIE_PLAYER_NAME_2";
95  level.player_name_directive[3] = &"ZOMBIE_PLAYER_NAME_3";
96 }
97 
98 function ‪player_last_stand_stats( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
99 {
100  //stat tracking
101  if ( isdefined( attacker ) && IsPlayer( attacker ) && attacker != self )
102  {
103  if ( "zcleansed" == level.gametype )
104  {
105  ‪demo::bookmark( "kill", gettime(), attacker, self, 0, eInflictor );
106  }
107 
108  if ( "zcleansed" == level.gametype )
109  {
110  if ( !‪IS_TRUE( attacker.is_zombie ) )
111  {
112  attacker.kills++; // only a zombie kill increments the scoreboard, even though player stats are incremented normally
113  }
114  else
115  {
116  attacker.downs++; // only a human kill increments downs
117  }
118  }
119  else
120  {
121  attacker.kills++;
122  }
123  attacker ‪zm_stats::increment_client_stat( "kills" ); //total kills
124  attacker ‪zm_stats::increment_player_stat( "kills" );
125  attacker AddWeaponStat( weapon, "kills", 1 );
126 
127  if ( ‪zm_utility::is_headshot( weapon, sHitLoc, sMeansOfDeath ))
128  {
129  attacker.headshots++;
130  attacker ‪zm_stats::increment_client_stat( "headshots" ); //headshots
131  attacker AddWeaponStat( weapon, "headshots", 1 );
132  attacker ‪zm_stats::increment_player_stat( "headshots" );
133  }
134  }
135 
137 
138  if( level ‪flag::get( "solo_game" ) && !self.lives && GetNumConnectedPlayers() < 2 ) //the "solo_game" flag does not get cleared in hot join...so this would inflate the death stats in hot join
139  {
140  self ‪zm_stats::increment_client_stat( "deaths" );
141  self ‪zm_stats::increment_player_stat( "deaths" );
142  }
143 }
144 
146 {
147  if ( "zcleansed" != level.gametype )
148  {
149  self.downs++;
150  }
151 
152  self ‪zm_stats::increment_global_stat( "TOTAL_DOWNS" );
153  self ‪zm_stats::increment_map_stat( "TOTAL_DOWNS" );
154 
155  self ‪zm_stats::increment_client_stat( "downs" );
156 
157  self ‪zm_stats::increment_player_stat( "downs" );
158  zoneName = self ‪zm_utility::get_current_zone();
159  if ( !isdefined( zoneName ) )
160  {
161  zoneName = "";
162  }
163  self RecordPlayerDownZombies( zoneName );
164 }
165 
166 function ‪PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration )
167 {
168  self notify("entering_last_stand");
169 
170  self DisableWeaponCycling();
171 
172  // check to see if we are in a game module that wants to do something with PvP damage
173  if( isdefined( level._game_module_player_laststand_callback ) )
174  {
175  self [[ level._game_module_player_laststand_callback ]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
176  }
177 
179  {
180  return;
181  }
182 
183  if (‪IS_TRUE(self.in_zombify_call))
184  {
185  return;
186  }
187 
188  self thread ‪player_last_stand_stats( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
189 
190  if( isdefined( level.playerlaststand_func ) )
191  {
192  [[level.playerlaststand_func]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
193  }
194 
195  // vision set
196  // moved to zm::player_laststand()
197  //VisionSetLastStand( "zombie_last_stand", 1 );
198 
199  self.health = 1;
200  self.laststand = true;
201  self ‪set_ignoreme( true );
202  ‪callback::callback( #"on_player_laststand" );
204  //self thread zm_buildables::onPlayerLastStand();
205 
206  //self thread call_overloaded_func( "maps\_arcademode", "arcademode_player_laststand" );
207 
208  // revive trigger
209  if ( !‪IS_TRUE( self.no_revive_trigger ) )
210  {
212  }
213  else
214  {
215  self UndoLastStand(); // hide the overhead icon if there's no trigger
216  }
217 
218  // laststand weapons
219  if ( ‪IS_TRUE( self.‪is_zombie ) )
220  {
221  self TakeAllWeapons();
222 
223  if ( isdefined( attacker ) && IsPlayer( attacker ) && attacker != self )
224  {
225  attacker notify( "killed_a_zombie_player", eInflictor, self, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration );
226  }
227  }
228  else
229  {
232  }
233 
234  if( ‪IS_TRUE(level.playerSuicideAllowed ) && GetPlayers().size > 1 )
235  {
236  if (!isdefined(level.canPlayerSuicide) || self [[level.canPlayerSuicide]]() )
237  {
238  self thread ‪suicide_trigger_spawn();
239  }
240  }
241 
242  // Reset Disabled Power Perks Array On Downed State
243  //-------------------------------------------------
244  if ( isdefined( self.disabled_perks ) )
245  {
246  self.disabled_perks = [];
247  }
248 
249  if( level.lastStandGetupAllowed )
250  {
251  self thread ‪laststand_getup();
252  }
253  else
254  {
255  // bleed out timer
256  bleedout_time = GetDvarfloat( "player_lastStandBleedoutTime" );
257 
258  if( isdefined( self.n_bleedout_time_multiplier ) )
259  {
260  bleedout_time *= self.n_bleedout_time_multiplier;
261  }
262 
263  level ‪clientfield::increment( "laststand_update" + ( self GetEntityNumber() ), 30 );
264 
265  self thread laststand_bleedout( bleedout_time );
266  }
267 
268  ‪demo::bookmark( "player_downed", gettime(), self );
269 
270  self notify( "player_downed" );
271  self thread ‪refire_player_downed();
272 
273  //clean up revive trigger if he disconnects while in laststand
275 }
276 
278 {
279  self endon("player_revived");
280  self endon("death");
281  self endon("disconnect");
282  wait(1.0);
283  if(self.num_perks)
284  {
285  self notify("player_downed");
286  }
287 }
288 
289 // self = a player
291 {
292  self DisableWeaponCycling();
293 
294  weaponInventory = self GetWeaponsList( true );
295  self.laststandPrimaryWeapons = self GetWeaponsListPrimaries();
296  self.lastActiveWeapon = self GetCurrentWeapon();
297  quickswitch = false;
298  if ( IsDefined(self) && self IsSwitchingWeapons() )
299  quickswitch = true;
300  if ( self IsThrowingGrenade() && ‪zm_utility::is_offhand_weapon( self.lastActiveWeapon ))
301  quickswitch = true;
302  if ( ‪zm_utility::is_hero_weapon( self.lastActiveWeapon ))
303  quickswitch = true;
304  if ( self.lastActiveWeapon.isriotshield )
305  quickswitch = true;
306  if ( quickswitch )
307  {
308  if ( isdefined( self.laststandPrimaryWeapons ) && self.laststandPrimaryWeapons.size > 0 )
309  {
310  self SwitchToWeaponImmediate();
311  }
312  else
313  {
315  }
316  self ‪util::waittill_any_timeout( 1, "weapon_change_complete" );
317  }
318  self.lastActiveWeapon = self GetCurrentWeapon();
319  self SetLastStandPrevWeap( self.lastActiveWeapon );
320  self.laststandpistol = undefined;
321 
322  self.hadpistol = false;
323 
324  for( i = 0; i < weaponInventory.size; i++ )
325  {
326  weapon = weaponInventory[i];
327 
328  wclass = weapon.weapClass;
329  if ( weapon.isBallisticKnife )
330  {
331  wclass = "knife";
332  }
333 
334  if ( ( wclass == "pistol" || wclass == "pistol spread" || wclass == "pistolspread" ) && !isdefined( self.laststandpistol ) )
335  {
336  self.laststandpistol = weapon;
337  self.hadpistol = true;
338 
339  }
340 
341  if ( weapon == level.weaponReviveTool || ‪IS_EQUAL(weapon,self.weaponReviveTool) )
342  {
343  // this player was killed while reviving another player
344  self ‪zm_stats::increment_client_stat( "failed_sacrifices" );
345  self ‪zm_stats::increment_player_stat( "failed_sacrifices" );
346  //iprintlnbold("failed the sacrifice - you died while reviving");
347  }
348  else if ( weapon.isPerkBottle )
349  {
350  self TakeWeapon( weapon );
351  self.lastActiveWeapon = level.weaponNone;
352  continue;
353  }
354  }
355 
356  if( ‪IS_TRUE( self.hadpistol ) && isdefined( level.zombie_last_stand_pistol_memory ) )
357  {
358  self [ [ level.zombie_last_stand_pistol_memory ] ]();
359  }
360 
361  if ( !isdefined( self.laststandpistol ) )
362  {
363  self.laststandpistol = level.laststandpistol;
364  }
365 
366  self notify("weapons_taken_for_last_stand");
367 }
368 
369 
370 // self = a player
372 {
373  // return the player's additional primary weapon, if they retained the perk through laststand - Black Ops 3 TU1 fix
374  if( self HasPerk( ‪PERK_ADDITIONAL_PRIMARY_WEAPON ) && isdefined( self.weapon_taken_by_losing_specialty_additionalprimaryweapon ) )
375  {
376  if ( isdefined(level.return_additionalprimaryweapon) )
377  {
378  self [[ level.return_additionalprimaryweapon ]]( self.weapon_taken_by_losing_specialty_additionalprimaryweapon );
379  }
380  else
381  {
382  self ‪zm_weapons::give_build_kit_weapon( self.weapon_taken_by_losing_specialty_additionalprimaryweapon );
383  }
384  }
385  else if ( isdefined(self.weapon_taken_by_losing_specialty_additionalprimaryweapon) && self.lastActiveWeapon == self.weapon_taken_by_losing_specialty_additionalprimaryweapon )
386  {
387  self.lastActiveWeapon = level.weaponNone;
388  }
389 
390  if ( isdefined( self.hadpistol ) && !self.hadpistol && isdefined( self.laststandpistol ) )
391  {
392  self TakeWeapon( self.laststandpistol );
393  }
394 
395  if( isdefined( self.hadpistol ) && self.hadpistol == true && isdefined( level.zombie_last_stand_ammo_return ) && isdefined( self.laststandpistol ) )
396  {
397  [ [ level.zombie_last_stand_ammo_return ] ]();
398  }
399 
400  self EnableWeaponCycling();
401  self EnableOffhandWeapons();
402 
403  // if we can't figure out what the last active weapon was, try to switch a primary weapon
404  //CHRIS_P: - don't try to give the player back the mortar_round weapon ( this is if the player killed himself with a mortar round)
405  if( self.lastActiveWeapon != level.weaponNone && self HasWeapon( self.lastActiveWeapon ) && !‪zm_utility::is_placeable_mine( self.lastActiveWeapon ) && !‪zm_equipment::is_equipment( self.lastActiveWeapon ) && !‪zm_utility::is_hero_weapon( self.lastActiveWeapon ) )
406  {
407  self SwitchToWeapon( self.lastActiveWeapon );
408  }
409  else
410  {
411  self SwitchToWeapon(); // Switch to any available primary
412  }
413 
414  self.laststandpistol = undefined;
415 }
416 
418 {
419  if( isdefined( e_player.laststandpistol ) )
420  {
421  return false;
422  }
423 
424  return true;
425 }
426 
427 function ‪laststand_clean_up_on_disconnect( e_revivee, w_reviver, w_revive_tool )
428 {
429  self endon( "do_revive_ended_normally" );
430 
431  reviveTrigger = e_revivee.revivetrigger;
432 
433  e_revivee waittill("disconnect");
434 
435  if( isdefined( reviveTrigger ) )
436  {
437  reviveTrigger delete();
438  }
440 
441  if( isdefined( self.reviveProgressBar ) )
442  {
443  self.reviveProgressBar ‪hud::destroyElem();
444  }
445 
446  if( isdefined( self.reviveTextHud ) )
447  {
448  self.reviveTextHud ‪destroy();
449  }
450 
451  if ( isdefined ( w_reviver ) && isdefined( w_revive_tool ) ) // PORTIZ 8/4/16: support alternate revives that don't require a tool
452  {
453  self ‪revive_give_back_weapons( w_reviver, w_revive_tool );
454  }
455 }
456 
458 {
459  self endon( "do_revive_ended_normally" );
460 
461  e_revivee ‪util::waittill_any( "disconnect", "zombified", "stop_revive_trigger" );
462 
463  self.is_reviving_any--;
464  if ( 0 > self.‪is_reviving_any )
465  {
466  self.is_reviving_any = 0;
467  }
468 
469  if( isdefined( self.reviveProgressBar ) )
470  {
471  self.reviveProgressBar ‪hud::destroyElem();
472  }
473 
474  if( isdefined( self.reviveTextHud ) )
475  {
476  self.reviveTextHud ‪destroy();
477  }
478 
479 }
480 
482 {
483  assert( isdefined( self.laststandpistol ) );
484  assert( self.laststandpistol != level.weaponNone );
485 
486  if( isdefined( level.zombie_last_stand ) )
487  {
488  [ [ level.zombie_last_stand ] ]();
489  }
490  else
491  {
492  self GiveWeapon( self.laststandpistol );
493  self GiveMaxAmmo( self.laststandpistol );
494  self SwitchToWeapon( self.laststandpistol );
495  }
496 
497  // queue up a second switch to make sure it succeeds.
498  self thread ‪wait_switch_weapon( 1, self.laststandpistol );
499 }
500 
501 function ‪wait_switch_weapon( n_delay, w_weapon )
502 {
503  self endon ("player_revived");
504  self endon ("player_suicide");
505  self endon ("zombified");
506  self endon ("disconnect");
507 
508  wait n_delay;
509  self SwitchToWeapon( w_weapon );
510 }
511 
512 
514 {
515  self endon ("player_revived");
516  self endon ("player_suicide");
517  self endon ("zombified");
518  self endon ("disconnect");
519 
520 
521  if ( ‪IS_TRUE( self.‪is_zombie ) || ‪IS_TRUE( self.no_revive_trigger ) )
522  {
523  self notify("bled_out");
524  ‪util::wait_network_frame(); //to guarantee the notify gets sent and processed before the rest of this script continues to turn the guy into a spectator
525 
526  self ‪bleed_out();
527 
528  return;
529  }
530 
531  //self PlayLoopSound("heart_beat",delay); // happens on client now DSL
532 
533  // Notify client that we're in last stand.
534 
535  self ‪clientfield::set( "zmbLastStand", 1 );
536 
537  self.bleedout_time = ‪delay;
538 
539  n_default_bleedout_time = GetDvarfloat( "player_lastStandBleedoutTime" );
540  n_bleedout_time = self.bleedout_time;
541  n_start_time = gettime();
542 
543  while ( self.bleedout_time > Int( ‪delay * 0.5 ) )
544  {
545  // If we lost the time override while down, maybe break out
546  if( ( n_bleedout_time > n_default_bleedout_time ) && (!isdefined(self.n_bleedout_time_multiplier)) )
547  {
548  n_current_time = gettime();
549  n_total_time = ( n_current_time - n_start_time ) / 1000;
550  if( n_total_time > n_default_bleedout_time )
551  {
552  ‪delay = 4;
553  self.bleedout_time = 2;
554  break;
555  }
556  }
557 
558  self.bleedout_time -= 1;
559  wait( 1 );
560  }
561 
562  ‪visionset_mgr::activate( "visionset", ‪ZM_DEATH_VISIONSET, self, ‪delay * 0.5 );
563 
564  while ( self.bleedout_time > 0 )
565  {
566  self.bleedout_time -= 1;
567  level ‪clientfield::increment( "laststand_update" + ( self GetEntityNumber() ), self.bleedout_time + 1 );
568  wait( 1 );
569  }
570 
571 
572  //VisionSetLastStand( "zombie_death", delay * 0.5 );
573 
574  //CODER_MOD: TOMMYK 07/13/2008
575  while( isdefined( self.revivetrigger ) && isdefined( self.revivetrigger.beingRevived ) && self.revivetrigger.beingRevived == 1 )
576  {
577  wait( 0.1 );
578  }
579 
580  self notify("bled_out");
581  ‪util::wait_network_frame(); //to guarantee the notify gets sent and processed before the rest of this script continues to turn the guy into a spectator
582 
583  self ‪bleed_out();
584 
585 }
586 
587 
588 function ‪bleed_out()
589 {
591  if( isdefined( self.reviveTrigger ) )
592  self.reviveTrigger delete();
593  self.reviveTrigger=undefined;
594 
595  self ‪clientfield::set( "zmbLastStand", 0 );
596  //self AddPlayerStat( "zombie_deaths", 1 );
597  self ‪zm_stats::increment_client_stat( "deaths" );
598  self ‪zm_stats::increment_player_stat( "deaths" );
599  self RecordPlayerDeathZombies();
600  self.last_bleed_out_time = GetTime();
601 
602  self ‪zm_equipment::take();
604 
605  level ‪clientfield::increment( "laststand_update" + ( self GetEntityNumber() ), 1 );
606 
607  ‪demo::bookmark( "zm_player_bledout", gettime(), self, undefined, 1 );
608 
609  level notify("bleed_out", self.characterindex);
610  //clear the revive icon
611  self UndoLastStand();
612 
615 
616  if (isdefined(level.is_zombie_level ) && level.is_zombie_level)
617  {
618  self thread [[level.player_becomes_zombie]]();
619  }
620  else if (isdefined(level.is_specops_level ) && level.is_specops_level)
621  {
622  self thread [[level.spawnSpectator]]();
623  }
624  else
625  {
626  self ‪set_ignoreme( false );
627  }
628 }
629 
631 {
632  radius = GetDvarint( "revive_trigger_radius" );
633 
634  self.suicidePrompt = newclientHudElem( self );
635 
636  self.suicidePrompt.alignX = "center";
637  self.suicidePrompt.alignY = "middle";
638  self.suicidePrompt.horzAlign = "center";
639  self.suicidePrompt.vertAlign = "bottom";
640  self.suicidePrompt.y = -170;
641  if ( self IsSplitScreen() )
642  {
643  self.suicidePrompt.y = -132;
644  }
645  self.suicidePrompt.foreground = true;
646  self.suicidePrompt.font = "default";
647  self.suicidePrompt.fontScale = 1.5;
648  self.suicidePrompt.alpha = 1;
649  self.suicidePrompt.color = ( 1.0, 1.0, 1.0 );
650  self.suicidePrompt.hidewheninmenu = true;
651 
652  self thread ‪suicide_trigger_think();
653 }
654 
655 // logic for the revive trigger
657 {
658  self endon ( "disconnect" );
659  self endon ( "zombified" );
660  self endon ( "stop_revive_trigger" );
661  self endon ( "player_revived");
662  self endon ( "bled_out");
663  self endon ("fake_death");
664  level endon("end_game");
665  level endon("stop_suicide_trigger");
666 
667  //in case the game ends while this is running
669 
670  //in case user is holding UseButton while this is running
672 
673  // If player was holding use while going into last stand, wait for them to release it
674  while ( self UseButtonPressed() )
675  {
676  wait ( 1 );
677  }
678 
679  if(!isdefined(self.suicidePrompt))
680  {
681  return;
682  }
683 
684  while( true )
685  {
686  wait ( 0.1 );
687 
688  if(!isdefined(self.suicidePrompt))
689  {
690  continue;
691  }
692 
693  self.suicidePrompt setText( &"ZOMBIE_BUTTON_TO_SUICIDE" );
694 
695  if ( !self ‪is_suiciding() )
696  {
697  continue;
698  }
699 
700  self.pre_suicide_weapon = self GetCurrentWeapon();
701  self GiveWeapon( level.weaponSuicide );
702  self SwitchToWeapon( level.weaponSuicide );
703  duration = self doCowardsWayAnims();
704 
705  suicide_success = ‪suicide_do_suicide( duration );
706  self.laststand = undefined;
707  self TakeWeapon( level.weaponSuicide );
708 
709  if ( suicide_success )
710  {
711  self notify("player_suicide");
712 
713  ‪util::wait_network_frame(); //to guarantee the notify gets sent and processed before the rest of this script continues to turn the guy into a spectator
714 
715  //Stat Tracking
716  self ‪zm_stats::increment_client_stat( "suicides" );
717 
718  self ‪bleed_out();
719 
720  return;
721  }
722 
723  self SwitchToWeapon( self.pre_suicide_weapon );
724  self.pre_suicide_weapon = undefined;
725  }
726 }
727 
728 function ‪suicide_do_suicide(duration)
729 {
730  level endon("end_game");
731  level endon("stop_suicide_trigger");
732 
733  suicideTime = duration; //1.5;
734 
735  ‪timer = 0;
736 
737  suicided = false;
738 
739  self.suicidePrompt setText( "" );
740 
741  if( !isdefined(self.suicideProgressBar) )
742  {
743  self.suicideProgressBar = self ‪hud::createPrimaryProgressBar();
744  }
745 
746  if( !isdefined(self.suicideTextHud) )
747  {
748  self.suicideTextHud = newclientHudElem( self );
749  }
750 
751  self.suicideProgressBar ‪hud::updateBar( 0.01, 1 / suicideTime );
752 
753  self.suicideTextHud.alignX = "center";
754  self.suicideTextHud.alignY = "middle";
755  self.suicideTextHud.horzAlign = "center";
756  self.suicideTextHud.vertAlign = "bottom";
757  self.suicideTextHud.y = -173;
758  if ( self IsSplitScreen() )
759  {
760  self.suicideTextHud.y = -147;
761  }
762  self.suicideTextHud.foreground = true;
763  self.suicideTextHud.font = "default";
764  self.suicideTextHud.fontScale = 1.8;
765  self.suicideTextHud.alpha = 1;
766  self.suicideTextHud.color = ( 1.0, 1.0, 1.0 );
767  self.suicideTextHud.hidewheninmenu = true;
768  self.suicideTextHud setText( &"ZOMBIE_SUICIDING" );
769 
770  while( self ‪is_suiciding() )
771  {
773  ‪timer += 0.05;
774 
775  if( ‪timer >= suicideTime)
776  {
777  suicided = true;
778  break;
779  }
780  }
781 
782  if( isdefined( self.suicideProgressBar ) )
783  {
784  self.suicideProgressBar ‪hud::destroyElem();
785  }
786 
787  if( isdefined( self.suicideTextHud ) )
788  {
789  self.suicideTextHud ‪destroy();
790  }
791 
792  if ( isDefined(self.suicidePrompt) )
793  {
794  self.suicidePrompt setText( &"ZOMBIE_BUTTON_TO_SUICIDE" );
795  }
796  return suicided;
797 }
798 
799 function ‪can_suicide()
800 {
801  if ( !isAlive( self ) )
802  {
803  return false;
804  }
805 
807  {
808  return false;
809  }
810 
811  if ( !isdefined( self.suicidePrompt ) )
812  {
813  return false;
814  }
815 
816  if ( ‪IS_TRUE( self.‪is_zombie ) )
817  {
818  return false;
819  }
820 
821  if ( ‪IS_TRUE( level.intermission ) )
822  {
823  return false;
824  }
825 
826  return true;
827 }
828 
829 function ‪is_suiciding( revivee )
830 {
831  return ( self UseButtonPressed() && ‪can_suicide() );
832 }
833 
834 
835 
836 // spawns the trigger used for the player to get revived
838 {
839  if ( isdefined( level.revive_trigger_spawn_override_link ) )
840  {
841  [[ level.revive_trigger_spawn_override_link ]]( self );
842  }
843  else
844  {
845  radius = GetDvarint( "revive_trigger_radius" );
846  self.revivetrigger = ‪spawn( "trigger_radius", (0.0,0.0,0.0), 0, radius, radius );
847  self.revivetrigger setHintString( "" ); // only show the hint string if the triggerer is facing me
848  self.revivetrigger setCursorHint( "HINT_NOICON" );
849  self.revivetrigger SetMovingPlatformEnabled( true );
850  self.revivetrigger EnableLinkTo();
851  self.revivetrigger.origin = self.origin;
852  self.revivetrigger LinkTo( self );
853  self.revivetrigger SetInvisibleToPlayer( self );
854 
855  self.revivetrigger.beingRevived = 0;
856  self.revivetrigger.createtime = gettime();
857  }
858 
859  self thread ‪revive_trigger_think();
860  //self.revivetrigger thread revive_debug();
861 }
862 
863 
864 // logic for the revive trigger
865 function ‪revive_trigger_think( t_secondary )
866 {
867  self endon ( "disconnect" );
868  self endon ( "zombified" );
869  self endon ( "stop_revive_trigger" );
870  level endon("end_game");
871  self endon( "death" );
872 
873  while ( true )
874  {
876 
877  if( isdefined( t_secondary ) )
878  {
879  t_revive = t_secondary;
880  }
881  else
882  {
883  t_revive = self.revivetrigger;
884  }
885 
886  t_revive setHintString( "" );
887 
888  for ( i = 0; i < level.players.size; i++ )
889  {
890  n_depth = 0;
891  n_depth = self depthinwater();
892 
893  if( isdefined( t_secondary ) )
894  {
895  // ignore revive trigger touch check but use touch check with secondary
896  if ( ( level.players[i] ‪can_revive( self, true, true ) && level.players[i] IsTouching( t_revive ) ) || n_depth > 20 )
897  {
898  t_revive setReviveHintString( &"ZOMBIE_BUTTON_TO_REVIVE_PLAYER", self.team );
899  break;
900  }
901  }
902  else
903  {
904  // PORTIZ 8/4/16: allow special revive overrides to be used
905  if ( level.players[i] ‪can_revive_via_override( self ) || level.players[i] ‪can_revive( self ) || n_depth > 20)
906  {
907  // TODO: This will turn on the trigger hint for every player within
908  // the radius once one of them faces the revivee, even if the others
909  // are facing away. Either we have to display the hints manually here
910  // (making sure to prioritize against any other hints from nearby objects),
911  // or we need a new combined radius+lookat trigger type.
912  t_revive setReviveHintString( &"ZOMBIE_BUTTON_TO_REVIVE_PLAYER", self.team );
913  break;
914  }
915  }
916  }
917 
918  for ( i = 0; i < level.players.size; i++ )
919  {
920  e_reviver = level.players[i];
921 
922  if( self == e_reviver || !e_reviver ‪is_reviving( self, t_secondary ) )
923  {
924  continue;
925  }
926 
927  // PORTIZ 8/4/16: if we're using a special revive override, check to see if the revive tool should be used
928  if ( !isdefined( e_reviver.s_revive_override_used ) || e_reviver.s_revive_override_used.b_use_revive_tool )
929  {
930  w_revive_tool = level.weaponReviveTool;
931  if ( isdefined(e_reviver.weaponReviveTool) )
932  {
933  w_revive_tool = e_reviver.weaponReviveTool;
934  }
935 
936  // give the syrette
937  w_reviver = e_reviver GetCurrentWeapon();
938  assert( isdefined( w_reviver ) );
939  if ( w_reviver == w_revive_tool )
940  {
941  //already reviving somebody
942  continue;
943  }
944 
945  e_reviver GiveWeapon( w_revive_tool );
946  e_reviver SwitchToWeapon( w_revive_tool );
947  e_reviver SetWeaponAmmoStock( w_revive_tool, 1 );
948 
949  e_reviver thread ‪revive_give_back_weapons_when_done( w_reviver, w_revive_tool, self );
950  }
951  else
952  {
953  w_reviver = undefined;
954  w_revive_tool = undefined; // make sure it's undefined after previous iteration of this loop
955  }
956 
957  //CODER_MOD: TOMMY K
958  b_revive_successful = e_reviver ‪revive_do_revive( self, w_reviver, w_revive_tool, t_secondary );
959 
960  e_reviver notify("revive_done");
961 
962  //PI CHANGE: player couldn't jump - allow this again now that they are revived
963  if ( IsPlayer( self ) )
964  {
965  self AllowJump(true);
966  }
967  //END PI CHANGE
968 
969  self.laststand = undefined;
970 
971  if( b_revive_successful )
972  {
973  if( isdefined( level.a_revive_success_perk_func ) )
974  {
975  foreach( func in level.a_revive_success_perk_func )
976  {
977  self [[ func ]]();
978  }
979  }
980 
981  self thread ‪revive_success( e_reviver );
983 
984  self notify( "stop_revive_trigger" ); // will endon primary or secondary as necessary
985  return;
986  }
987  }
988  }
989 }
990 
991 function ‪revive_give_back_weapons_wait( e_reviver, e_revivee )
992 {
993  e_revivee endon ( "disconnect" );
994  e_revivee endon ( "zombified" );
995  e_revivee endon ( "stop_revive_trigger" );
996  level endon("end_game");
997  e_revivee endon( "death" );
998 
999  e_reviver waittill("revive_done");
1000 }
1001 
1002 function ‪revive_give_back_weapons_when_done( w_reviver, w_revive_tool, e_revivee )
1003 {
1004  ‪revive_give_back_weapons_wait( self, e_revivee );
1005 
1006  self ‪revive_give_back_weapons( w_reviver, w_revive_tool );
1007 }
1008 
1009 function ‪revive_give_back_weapons( w_reviver, w_revive_tool )
1010 {
1011  // take the syrette
1012  self TakeWeapon( w_revive_tool );
1013 
1014  // Don't switch to their old primary weapon if they got put into last stand while trying to revive a teammate
1016  {
1017  return;
1018  }
1019 
1020  if( IsDefined( level.revive_give_back_weapons_custom_func ) && self [[ level.revive_give_back_weapons_custom_func ]] ( w_reviver ) )
1021  {
1022  return;
1023  }
1024 
1025  if ( w_reviver != level.weaponNone && !‪zm_utility::is_placeable_mine( w_reviver ) && !‪zm_equipment::is_equipment( w_reviver )&& !w_reviver.isFlourishWeapon && self HasWeapon( w_reviver ) )
1026  {
1028  }
1029  else
1030  {
1032  }
1033 }
1034 
1035 
1036 function ‪can_revive( e_revivee, ignore_sight_checks = false, ignore_touch_checks = false )
1037 {
1038  if ( !isdefined( e_revivee.revivetrigger ) )
1039  {
1040  return false;
1041  }
1042 
1043  if ( !isAlive( self ) )
1044  {
1045  return false;
1046  }
1047 
1049  {
1050  return false;
1051  }
1052 
1053  if( self.team != e_revivee.team )
1054  {
1055  return false;
1056  }
1057 
1058  if ( ‪IS_TRUE( self.‪is_zombie ) )
1059  {
1060  return false;
1061  }
1062 
1063  if ( self ‪zm_utility::has_powerup_weapon() )
1064  {
1065  return false;
1066  }
1067 
1068  if ( self ‪zm_utility::has_hero_weapon() )
1069  {
1070  return false;
1071  }
1072 
1073  if ( ‪IS_TRUE( level.can_revive_use_depthinwater_test ) && e_revivee depthinwater() > 10 )
1074  {
1075  return true;
1076  }
1077 
1078  if ( isdefined( level.can_revive ) && ![[ level.can_revive ]]( e_revivee ) )
1079  {
1080  return false;
1081  }
1082 
1083  if ( isdefined( level.can_revive_game_module ) && ![[ level.can_revive_game_module ]]( e_revivee ) )
1084  {
1085  return false;
1086  }
1087 
1088  if( !ignore_sight_checks && ( isdefined( level.revive_trigger_should_ignore_sight_checks ) ) )
1089  {
1090  ignore_sight_checks = [[ level.revive_trigger_should_ignore_sight_checks ]]( self );
1091 
1092  if( ignore_sight_checks && isdefined(e_revivee.revivetrigger.beingRevived) && (e_revivee.revivetrigger.beingRevived==1) )
1093  {
1094  ignore_touch_checks = true;
1095  }
1096  }
1097 
1098  if( !ignore_touch_checks )
1099  {
1100  if ( !self IsTouching( e_revivee.revivetrigger ) )
1101  {
1102  return false;
1103  }
1104  }
1105 
1106  if( !ignore_sight_checks )
1107  {
1108  if ( !self ‪laststand::is_facing( e_revivee ) )
1109  {
1110  return false;
1111  }
1112 
1113  if ( !SightTracePassed( self.origin + ( 0, 0, 50 ), e_revivee.origin + ( 0, 0, 30 ), false, undefined ) )
1114  {
1115  return false;
1116  }
1117 
1118  //chrisp - fix issue where guys can sometimes revive thru a wall
1119  if ( !bullettracepassed( self.origin + (0, 0, 50), e_revivee.origin + (0, 0, 30), false, undefined ) )
1120  {
1121  return false;
1122  }
1123  }
1124 
1125  //iprintlnbold("REVIVE IS GOOD");
1126  return true;
1127 }
1128 
1129 function ‪is_reviving( e_revivee, t_secondary ) // self = reviver player
1130 {
1131  if ( self ‪is_reviving_via_override( e_revivee ) ) // PORTIZ 8/4/16: support special revive overrides
1132  {
1133  return true;
1134  }
1135 
1136  if( isdefined( t_secondary ) )
1137  {
1138  return( self UseButtonPressed() && self ‪can_revive( e_revivee, true, true ) && self IsTouching( t_secondary ) );
1139  }
1140 
1141  return ( self UseButtonPressed() && ‪can_revive( e_revivee ) );
1142 }
1143 
1145 {
1146  return ‪IS_TRUE( self.‪is_reviving_any );
1147 }
1148 
1149 function ‪revive_get_revive_time( e_revivee )
1150 {
1151  // reviveTime used to be set from a Dvar, but this can no longer be tunable:
1152  // it has to match the length of the third-person revive animations for
1153  // co-op gameplay to run smoothly.
1154  reviveTime = 3;
1155 
1156  if ( self HasPerk( ‪PERK_QUICK_REVIVE ) )
1157  {
1158  reviveTime = reviveTime / 2;
1159  }
1160 
1161  if ( isdefined(self.get_revive_time) )
1162  {
1163  reviveTime = self [[self.get_revive_time]](e_revivee);
1164  }
1165 
1166  return reviveTime;
1167 }
1168 
1169 // self = reviver
1170 function ‪revive_do_revive( e_revivee, w_reviver, w_revive_tool, t_secondary )
1171 {
1172  assert( self ‪is_reviving( e_revivee, t_secondary ) );
1173 
1174  reviveTime = self ‪revive_get_revive_time( e_revivee );
1175 
1176  ‪timer = 0;
1177  revived = false;
1178 
1179  //CODER_MOD: TOMMYK 07/13/2008
1180  e_revivee.revivetrigger.beingRevived = 1;
1181  ‪name = level.player_name_directive[self GetEntityNumber()];
1182  e_revivee.revive_hud setText( &"ZOMBIE_PLAYER_IS_REVIVING_YOU", ‪name );
1183  e_revivee ‪laststand::revive_hud_show_n_fade( 3.0 );
1184 
1185  e_revivee.revivetrigger setHintString( "" );
1186 
1187  if ( IsPlayer( e_revivee ) )
1188  {
1189  e_revivee startrevive( self );
1190  }
1191 
1192  if( ‪SHOW_LAST_STAND_PROGRESS_BAR && !isdefined(self.reviveProgressBar) )
1193  {
1194  self.reviveProgressBar = self ‪hud::createPrimaryProgressBar();
1195  }
1196 
1197  if( !isdefined(self.reviveTextHud) )
1198  {
1199  self.reviveTextHud = newclientHudElem( self );
1200  }
1201 
1202  self thread ‪laststand_clean_up_on_disconnect( e_revivee, w_reviver, w_revive_tool );
1203 
1204  if ( !isdefined( self.‪is_reviving_any ) )
1205  {
1206  self.is_reviving_any = 0;
1207  }
1208  self.is_reviving_any++;
1209  self thread ‪laststand_clean_up_reviving_any( e_revivee );
1210 
1211  if( isdefined(self.reviveProgressBar) )
1212  {
1213  self.reviveProgressBar ‪hud::updateBar( 0.01, 1 / reviveTime );
1214  }
1215 
1216  self.reviveTextHud.alignX = "center";
1217  self.reviveTextHud.alignY = "middle";
1218  self.reviveTextHud.horzAlign = "center";
1219  self.reviveTextHud.vertAlign = "bottom";
1220  self.reviveTextHud.y = -113;
1221  if ( self IsSplitScreen() )
1222  {
1223  self.reviveTextHud.y = -347;
1224  }
1225  self.reviveTextHud.foreground = true;
1226  self.reviveTextHud.font = "default";
1227  self.reviveTextHud.fontScale = 1.8;
1228  self.reviveTextHud.alpha = 1;
1229  self.reviveTextHud.color = ( 1.0, 1.0, 1.0 );
1230  self.reviveTextHud.hidewheninmenu = true;
1231  self.reviveTextHud setText( &"ZOMBIE_REVIVING" );
1232 
1233  //stat tracking - failed revive
1234  self thread ‪check_for_failed_revive(e_revivee);
1235 
1236  while( self ‪is_reviving( e_revivee, t_secondary ) )
1237  {
1239  ‪timer += 0.05;
1240 
1242  {
1243  break;
1244  }
1245 
1246  if( isdefined( e_revivee.revivetrigger.auto_revive ) && e_revivee.revivetrigger.auto_revive == true )
1247  {
1248  break;
1249  }
1250 
1251  if( ‪timer >= reviveTime)
1252  {
1253  revived = true;
1254  break;
1255  }
1256  }
1257 
1258  if( isdefined( self.reviveProgressBar ) )
1259  {
1260  self.reviveProgressBar ‪hud::destroyElem();
1261  }
1262 
1263  if( isdefined( self.reviveTextHud ) )
1264  {
1265  self.reviveTextHud ‪destroy();
1266  }
1267 
1268  if( isdefined( e_revivee.revivetrigger.auto_revive ) && e_revivee.revivetrigger.auto_revive == true )
1269  {
1270  // ww: just fall through this part, no stoprevive
1271  }
1272  else if( !revived )
1273  {
1274  if ( IsPlayer( e_revivee ) )
1275  {
1276  e_revivee stoprevive( self );
1277  }
1278  }
1279 
1280  // CODER_MOD: TOMMYK 07/13/2008
1281  e_revivee.revivetrigger setHintString( &"ZOMBIE_BUTTON_TO_REVIVE_PLAYER" );
1282  e_revivee.revivetrigger.beingRevived = 0;
1283 
1284  self notify( "do_revive_ended_normally" );
1285  self.is_reviving_any--;
1286 
1287  // This player stopper reviving (kick of a thread to check to see if the player now bleeds out)
1288  if( !revived )
1289  {
1290  e_revivee thread ‪checkforbleedout( self );
1291  }
1292 
1293  return revived;
1294 }
1295 
1296 
1297 //*****************************************************************************
1298 // Persistent upgrade, revive upgrade lost check
1299 //*****************************************************************************
1300 
1301 // self = player who failed to revive a college
1302 function ‪checkforbleedout( player )
1303 {
1304  self endon ( "player_revived" );
1305  self endon ( "player_suicide" );
1306  self endon ( "disconnect" );
1307  player endon( "disconnect" );
1308 
1309 // MikeA: You now automatically lose the upgrade if you fail a revive
1310 /*
1311  self waittill( "bled_out" );
1312 */
1313 
1314  // Only in classic mode
1315  if( isdefined(player) && ‪zm_utility::is_Classic() )
1316  {
1317  ‪DEFAULT(player.failed_revives,0);
1318  player.failed_revives++;
1319  player notify( "player_failed_revive" );
1320  }
1321 }
1322 
1323 
1324 //*****************************************************************************
1325 //*****************************************************************************
1326 
1327 function ‪auto_revive( reviver, dont_enable_weapons )
1328 {
1329  if( isdefined( self.revivetrigger ) )
1330  {
1331  self.revivetrigger.auto_revive = true;
1332  if( self.revivetrigger.beingRevived == 1 )
1333  {
1334  while( true )
1335  {
1336  if( !isdefined( self.revivetrigger ) || ( self.revivetrigger.beingRevived == 0 ) )
1337  {
1338  break;
1339  }
1341 
1342  }
1343  }
1344 
1345  if( isdefined( self.revivetrigger ) )
1346  {
1347  self.revivetrigger.auto_trigger = false;
1348  }
1349  }
1350 
1351  self reviveplayer();
1352 
1353  // Make sure max health is set back to default
1354  self ‪zm_perks::perk_set_max_health_if_jugg( "health_reboot", true, false );
1355 
1356  self ‪clientfield::set( "zmbLastStand", 0 );
1357 
1358  self notify( "stop_revive_trigger" );
1359  if(isdefined(self.revivetrigger))
1360  {
1361  self.revivetrigger delete();
1362  self.revivetrigger = undefined;
1363  }
1365 
1366  // make sure we're cleaning up visionsets when auto reviving
1369 
1370  self notify("clear_red_flashing_overlay");
1371 
1372  self AllowJump( true );
1373 
1375  self.laststand = undefined;
1376 
1377  //don't do this for Grief
1378  if(!‪IS_TRUE(level.isresetting_grief))
1379  {
1380  // ww: moving the revive tracking, wasn't catching below the auto_revive
1381  if( isPlayer( reviver ) ) //check for cases where robot companion is the reviver
1382  {
1383  reviver.revives++;
1384  //stat tracking
1385  reviver ‪zm_stats::increment_client_stat( "revives" );
1386  reviver ‪zm_stats::increment_player_stat( "revives" );
1387  self RecordPlayerReviveZombies( reviver );
1388  ‪demo::bookmark( "zm_player_revived", gettime(), reviver, self );
1389  }
1390  }
1391 
1392  self notify ( "player_revived", reviver );
1393 
1394  // necessary wait to let bgb give back perks
1396 
1397  if( !isdefined(dont_enable_weapons) || (dont_enable_weapons == false) )
1398  {
1400  }
1401 }
1402 
1403 
1404 function ‪remote_revive( reviver )
1405 {
1407  {
1408  return;
1409  }
1410  self playsound( "zmb_character_remote_revived" );
1411  self thread ‪auto_revive( reviver );
1412 
1413 }
1414 
1415 
1416 function ‪revive_success( reviver, b_track_stats = true )
1417 {
1418  // Maybe it was a whoswho corpse that was revived
1419  if( !IsPlayer(self) )
1420  {
1421  self notify ( "player_revived", reviver );
1422  return;
1423  }
1424 
1425  if( ‪IS_TRUE( b_track_stats ) )
1426  {
1427  ‪demo::bookmark( "zm_player_revived", gettime(), reviver, self );
1428  }
1429 
1430  self notify ( "player_revived", reviver );
1431  reviver notify ( "player_did_a_revive", self );
1432  self reviveplayer();
1433 
1434  // Make sure max health is set back to default
1435  self ‪zm_perks::perk_set_max_health_if_jugg( "health_reboot", true, false );
1436 
1437  //CODER_MOD: TOMMYK 06/26/2008 - For coop scoreboards
1438 
1439  //don't do this for Grief when the rounds reset
1440  if( !‪IS_TRUE(level.isresetting_grief) && ‪IS_TRUE( b_track_stats ) )
1441  {
1442  reviver.revives++;
1443  //stat tracking
1444  reviver ‪zm_stats::increment_client_stat( "revives" );
1445  reviver ‪zm_stats::increment_player_stat( "revives" );
1446  reviver ‪xp_revive_once_per_round( self );
1447  self RecordPlayerReviveZombies( reviver );
1448  reviver.upgrade_fx_origin = self.origin;
1449  }
1450 
1451  if( ‪IS_TRUE( b_track_stats ) )
1452  {
1453  reviver thread ‪check_for_sacrifice(); //stat tracking
1454  }
1455 
1456  // CODER MOD: TOMMY K - 07/30/08
1457  //reviver thread call_overloaded_func( "maps\_arcademode", "arcademode_player_revive" );
1458 
1459  //CODER_MOD: Jay (6/17/2008): callback to revive challenge
1460  if( isdefined( level.missionCallbacks ) )
1461  {
1462  // removing coop challenges for now MGORDON
1463  //maps\_challenges_coop::doMissionCallback( "playerRevived", reviver );
1464  }
1465 
1466  self ‪clientfield::set( "zmbLastStand", 0 );
1467 
1468  self.revivetrigger delete();
1469  self.revivetrigger = undefined;
1471 
1473 
1476 
1477  // necessary wait to let bgb give back perks
1480 }
1481 
1482 function ‪xp_revive_once_per_round( player_being_revived )
1483 {
1484  if( !isdefined(self.number_revives_per_round) )
1485  {
1486  self.number_revives_per_round = [];
1487  }
1488 
1489  if( !isdefined(self.number_revives_per_round[player_being_revived.characterIndex]) )
1490  {
1491  self.number_revives_per_round[player_being_revived.characterIndex] = 0;
1492  }
1493 
1494  if( self.number_revives_per_round[player_being_revived.characterIndex] == 0 )
1495  {
1496  ‪scoreevents::processScoreEvent( "revive_an_ally", self );
1497  }
1498  self.number_revives_per_round[player_being_revived.characterIndex]++;
1499 }
1500 
1501 
1502 // Function so this can be threaded and delayed.
1503 function ‪set_ignoreme( b_ignoreme )
1504 {
1505  ‪DEFAULT(self.laststand_ignoreme,false);
1506  if ( b_ignoreme != self.laststand_ignoreme )
1507  {
1508  self.laststand_ignoreme = b_ignoreme;
1509  if ( b_ignoreme )
1511  else
1513  }
1514 }
1515 
1516 
1517 function ‪revive_force_revive( reviver )
1518 {
1519  assert( isdefined( self ) );
1520  assert( IsPlayer( self ) );
1521  assert( self ‪laststand::player_is_in_laststand() );
1522 
1523  self thread ‪revive_success( reviver );
1524 }
1525 
1527 {
1528 
1529  self.laststand_info = SpawnStruct();
1530  self.laststand_info.type_getup_lives = level.CONST_LASTSTAND_GETUP_COUNT_START;
1531 }
1532 
1534 {
1535  self endon ("player_revived");
1536  self endon ("disconnect");
1537 
1538 
1540 
1541  self ‪clientfield::set( "zmbLastStand", 1 );
1542 
1543  self.laststand_info.getup_bar_value = level.CONST_LASTSTAND_GETUP_BAR_START;
1544 
1545  self thread ‪laststand::laststand_getup_hud();
1546  self thread ‪laststand_getup_damage_watcher();
1547 
1548  while ( self.laststand_info.getup_bar_value < 1 )
1549  {
1550  self.laststand_info.getup_bar_value += level.CONST_LASTSTAND_GETUP_BAR_REGEN;
1552  }
1553 
1554  self ‪auto_revive( self );
1555 
1556  self ‪clientfield::set( "zmbLastStand", 0 );
1557 }
1558 
1560 {
1561  self endon ("player_revived");
1562  self endon ("disconnect");
1563 
1564  while( true )
1565  {
1566  self waittill( "damage" );
1567 
1568  self.laststand_info.getup_bar_value -= level.CONST_LASTSTAND_GETUP_BAR_DAMAGE;
1569 
1570  if( self.laststand_info.getup_bar_value < 0 )
1571  {
1572  self.laststand_info.getup_bar_value = 0;
1573  }
1574  }
1575 }
1576 
1577 // a sacrifice is when a player sucessfully revives another player, but dies afterwards
1579 {
1580  self ‪util::delay_notify("sacrifice_denied",1); //dying within 1 second of reviving another player is considered to be a 'sacrifice'
1581  self endon("sacrifice_denied");
1582 
1583  self waittill("player_downed");
1584 
1585  //stat tracking
1586  self ‪zm_stats::increment_client_stat( "sacrifices" );
1587  self ‪zm_stats::increment_player_stat( "sacrifices" );
1588  //iprintlnbold("sacrifice made");
1589 }
1590 
1591 //when a player is downed, any player that starts/stops reviving him will fail the revive if the player bleeds out
1592 function ‪check_for_failed_revive(e_revivee)
1593 {
1594  self endon("disconnect");
1595 
1596  e_revivee endon("disconnect"); //end if the player being revived disconnects
1597  e_revivee endon("player_suicide");
1598 
1599  self notify("checking_for_failed_revive"); //to prevent stacking this thread if the same player starts/stops reviving several times while the player is downed
1600  self endon("checking_for_failed_revive");
1601 
1602  e_revivee endon("player_revived"); //end if the player gets revived
1603 
1604  e_revivee waittill("bled_out"); // the player being revived bled out
1605 
1606  //stat tracking
1607  self ‪zm_stats::increment_client_stat( "failed_revives" );
1608  self ‪zm_stats::increment_player_stat( "failed_revives" );
1609  //iprintlnbold("failed the revive");
1610 }
1611 
1612 
1614 {
1615 }
1616 
1617 //*****************************************************************************
1618 //*****************************************************************************
1619 
1620 // PORTIZ: allow special revive mechanics on a per player basis
1621 // func_is_reviving: logic to check if the player is currently reviving
1622 // func_can_revive: logic to check if the player can revive (by default, will be the same as func_is_reviving)
1623 // b_use_revive_tool: whether or not this revive will give the player the revive tool
1624 function ‪register_revive_override( func_is_reviving, func_can_revive = undefined, b_use_revive_tool = false ) // self == player
1625 {
1626  if ( !isdefined( self.a_s_revive_overrides ) )
1627  {
1628  self.a_s_revive_overrides = [];
1629  }
1630 
1631  s_revive_override = SpawnStruct();
1632 
1633  s_revive_override.func_is_reviving = func_is_reviving;
1634 
1635  if ( isdefined( func_can_revive ) )
1636  {
1637  s_revive_override.func_can_revive = func_can_revive;
1638  }
1639  else
1640  {
1641  s_revive_override.func_can_revive = func_is_reviving; // in some cases (like for zm_bgb_near_death_experience) these two cases will be the same
1642  }
1643 
1644  s_revive_override.b_use_revive_tool = b_use_revive_tool;
1645 
1646  self.a_s_revive_overrides[ self.a_s_revive_overrides.size ] = s_revive_override;
1647 
1648  return s_revive_override; // return the struct so it can be deregistered later
1649 }
1650 
1651 function ‪deregister_revive_override( s_revive_override )
1652 {
1653  if ( isdefined( self.a_s_revive_overrides ) )
1654  {
1655  ArrayRemoveValue( self.a_s_revive_overrides, s_revive_override );
1656  }
1657 }
1658 
1659 function ‪can_revive_via_override( e_revivee ) // self == reviver player
1660 {
1661  if ( isdefined( self.a_s_revive_overrides ) )
1662  {
1663  for ( i = 0; i < self.a_s_revive_overrides.size; i++ )
1664  {
1665  if ( self [[ self.a_s_revive_overrides[ i ].func_can_revive ]]( e_revivee ) )
1666  {
1667  return true;
1668  }
1669  }
1670  }
1671 
1672  return false;
1673 }
1674 
1675 function ‪is_reviving_via_override( e_revivee ) // self == reviver player
1676 {
1677  if ( isdefined( self.a_s_revive_overrides ) )
1678  {
1679  for ( i = 0; i < self.a_s_revive_overrides.size; i++ )
1680  {
1681  if ( self [[ self.a_s_revive_overrides[ i ].func_is_reviving ]]( e_revivee ) )
1682  {
1683  self.s_revive_override_used = self.a_s_revive_overrides[ i ];
1684  return true;
1685  }
1686  }
1687  }
1688 
1689  self.s_revive_override_used = undefined;
1690  return false;
1691 }
‪is_zombie
‪function is_zombie()
Definition: zombie_utility.gsc:1320
‪processScoreEvent
‪function processScoreEvent(event, player, victim, weapon)
Definition: scoreevents_shared.gsc:19
‪is_equipment
‪function is_equipment(weapon)
Definition: _zm_equipment.gsc:691
‪callback
‪function callback(event, localclientnum, params)
Definition: callbacks_shared.csc:13
‪Laststand_Bleedout
‪function Laststand_Bleedout(delay)
Definition: _zm_laststand.gsc:513
‪revive_get_revive_time
‪function revive_get_revive_time(e_revivee)
Definition: _zm_laststand.gsc:1149
‪cleanup_laststand_on_disconnect
‪function cleanup_laststand_on_disconnect()
Definition: laststand_shared.gsc:275
‪activate
‪function activate()
Definition: traps_shared.gsc:655
‪get_current_zone
‪function get_current_zone(return_zone)
Definition: _zm_utility.gsc:3614
‪suicide_do_suicide
‪function suicide_do_suicide(duration)
Definition: _zm_laststand.gsc:728
‪laststand_getup_damage_watcher
‪function laststand_getup_damage_watcher()
Definition: _zm_laststand.gsc:1559
‪suicide_trigger_spawn
‪function suicide_trigger_spawn()
Definition: _zm_laststand.gsc:630
‪is_facing
‪function is_facing(facee, requiredDot=0.9)
Definition: laststand_shared.gsc:116
‪add_weighted_down
‪function add_weighted_down()
Definition: _zm_laststand.gsc:1613
‪suicide_trigger_think
‪function suicide_trigger_think()
Definition: _zm_laststand.gsc:656
‪increment_client_stat
‪function increment_client_stat(stat_name, include_gametype)
Definition: _zm_stats.gsc:389
‪check_for_failed_revive
‪function check_for_failed_revive(e_revivee)
Definition: _zm_laststand.gsc:1592
‪timer
‪function timer(n_time, str_endon, x, y, height)
Definition: lui_shared.gsc:163
‪PlayerLastStand
‪function PlayerLastStand(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
Definition: _zm_laststand.gsc:166
‪increment_player_stat
‪function increment_player_stat(stat_name)
Definition: _zm_stats.gsc:369
‪laststand_global_init
‪function laststand_global_init()
Definition: _zm_laststand.gsc:83
‪increment_map_stat
‪function increment_map_stat(stat_name)
Definition: _zm_stats.gsc:449
‪VERSION_SHIP
‪#define VERSION_SHIP
Definition: version.gsh:36
‪laststand_clean_up_reviving_any
‪function laststand_clean_up_reviving_any(e_revivee)
Definition: _zm_laststand.gsc:457
‪bleed_out
‪function bleed_out()
Definition: _zm_laststand.gsc:588
‪register_revive_override
‪function register_revive_override(func_is_reviving, func_can_revive=undefined, b_use_revive_tool=false)
Definition: _zm_laststand.gsc:1624
‪N_REVIVE_VISIBILITY_DELAY
‪#define N_REVIVE_VISIBILITY_DELAY
Definition: _zm_laststand.gsc:42
‪is_suiciding
‪function is_suiciding(revivee)
Definition: _zm_laststand.gsc:829
‪is_Classic
‪function is_Classic()
Definition: _zm_utility.gsc:42
‪ZM_DEATH_VISIONSET
‪#define ZM_DEATH_VISIONSET
Definition: _zm_laststand.gsh:2
‪revive_give_back_weapons_wait
‪function revive_give_back_weapons_wait(e_reviver, e_revivee)
Definition: _zm_laststand.gsc:991
‪is_reviving
‪function is_reviving(e_revivee, t_secondary)
Definition: _zm_laststand.gsc:1129
‪destroyElem
‪function destroyElem()
Definition: hud_util_shared.gsc:755
‪clean_up_suicide_hud_on_bled_out
‪function clean_up_suicide_hud_on_bled_out()
Definition: laststand_shared.gsc:98
‪can_revive
‪function can_revive(e_revivee, ignore_sight_checks=false, ignore_touch_checks=false)
Definition: _zm_laststand.gsc:1036
‪laststand_disable_player_weapons
‪function laststand_disable_player_weapons()
Definition: _zm_laststand.gsc:290
‪spawn
‪function spawn(v_origin=(0, 0, 0), v_angles=(0, 0, 0))
Definition: struct.csc:23
‪laststand_enable_player_weapons
‪function laststand_enable_player_weapons()
Definition: _zm_laststand.gsc:371
‪waittill_any_timeout
‪function waittill_any_timeout(n_timeout, string1, string2, string3, string4, string5)
Definition: util_shared.csc:423
‪IS_TRUE
‪#define IS_TRUE(__a)
Definition: shared.gsh:251
‪get
‪function get(kvp_value, kvp_key="targetname")
Definition: struct.csc:13
‪delay
‪function delay(time_or_notify, str_endon, func, arg1, arg2, arg3, arg4, arg5, arg6)
Definition: util_shared.csc:784
‪revive_force_revive
‪function revive_force_revive(reviver)
Definition: _zm_laststand.gsc:1517
‪revive_success
‪function revive_success(reviver, b_track_stats=true)
Definition: _zm_laststand.gsc:1416
‪take_hero_weapon
‪function take_hero_weapon()
Definition: _zm_hero_weapon.gsc:393
‪deregister_revive_override
‪function deregister_revive_override(s_revive_override)
Definition: _zm_laststand.gsc:1651
‪switch_back_primary_weapon
‪function switch_back_primary_weapon(oldprimary, immediate=false)
Definition: _zm_weapons.gsc:280
‪revive_trigger_think
‪function revive_trigger_think(t_secondary)
Definition: _zm_laststand.gsc:865
‪createPrimaryProgressBar
‪function createPrimaryProgressBar()
Definition: hud_util_shared.gsc:602
‪DEFAULT
‪#define DEFAULT(__var, __default)
Definition: shared.gsh:270
‪revive_give_back_weapons_when_done
‪function revive_give_back_weapons_when_done(w_reviver, w_revive_tool, e_revivee)
Definition: _zm_laststand.gsc:1002
‪give_fallback_weapon
‪function give_fallback_weapon(immediate=false)
Definition: _zm_melee_weapon.gsc:208
‪wait_switch_weapon
‪function wait_switch_weapon(n_delay, w_weapon)
Definition: _zm_laststand.gsc:501
‪increment_global_stat
‪function increment_global_stat(stat_name)
Definition: _zm_stats.gsc:332
‪wait_network_frame
‪function wait_network_frame(n_count=1)
Definition: util_shared.gsc:64
‪updateBar
‪function updateBar(barFrac, rateOfChange)
Definition: hud_util_shared.gsc:294
‪PERK_QUICK_REVIVE
‪#define PERK_QUICK_REVIVE
Definition: _zm_perks.gsh:24
‪has_powerup_weapon
‪function has_powerup_weapon()
Definition: _zm_utility.gsc:4519
‪remote_revive
‪function remote_revive(reviver)
Definition: _zm_laststand.gsc:1404
‪on_player_last_stand
‪function on_player_last_stand()
Definition: gameobjects_shared.gsc:237
‪checkforbleedout
‪function checkforbleedout(player)
Definition: _zm_laststand.gsc:1302
‪waittill_any
‪function waittill_any(str_notify1, str_notify2, str_notify3, str_notify4, str_notify5)
Definition: util_shared.csc:375
‪increment_downed_stat
‪function increment_downed_stat()
Definition: _zm_laststand.gsc:145
‪deactivate
‪function deactivate()
Definition: traps_shared.gsc:649
‪laststand_has_players_weapons_returned
‪function laststand_has_players_weapons_returned(e_player)
Definition: _zm_laststand.gsc:417
‪laststand_give_pistol
‪function laststand_give_pistol()
Definition: _zm_laststand.gsc:481
‪cleanup_suicide_hud
‪function cleanup_suicide_hud()
Definition: laststand_shared.gsc:67
‪revive_give_back_weapons
‪function revive_give_back_weapons(w_reviver, w_revive_tool)
Definition: _zm_laststand.gsc:1009
‪revive_do_revive
‪function revive_do_revive(e_revivee, w_reviver, w_revive_tool, t_secondary)
Definition: _zm_laststand.gsc:1170
‪is_reviving_via_override
‪function is_reviving_via_override(e_revivee)
Definition: _zm_laststand.gsc:1675
‪revive_trigger_spawn
‪function revive_trigger_spawn()
Definition: _zm_laststand.gsc:837
‪is_headshot
‪function is_headshot(weapon, sHitLoc, sMeansOfDeath)
Definition: _zm_utility.gsc:5265
‪laststand_getup_hud
‪function laststand_getup_hud()
Definition: laststand_shared.gsc:238
‪increment
‪function increment(str_field_name, n_increment_count=1)
Definition: clientfield_shared.gsc:110
‪delay_notify
‪function delay_notify(time_or_notify, str_notify, str_endon)
Definition: util_shared.csc:822
‪is_offhand_weapon
‪function is_offhand_weapon(weapon)
Definition: _zm_utility.gsc:4507
‪give_build_kit_weapon
‪function give_build_kit_weapon(weapon)
Definition: _zm_weapons.gsc:2543
‪REGISTER_SYSTEM
‪#define REGISTER_SYSTEM(__sys, __func_init_preload, __reqs)
Definition: shared.gsh:204
‪bookmark
‪function bookmark(type, time, mainClientEnt, otherClientEnt, eventPriority, inflictorEnt, overrideEntityCamera, actorEnt)
Definition: demo_shared.gsc:25
‪is_hero_weapon
‪function is_hero_weapon(weapon)
Definition: _zm_utility.gsc:4408
‪can_suicide
‪function can_suicide()
Definition: _zm_laststand.gsc:799
‪laststand_clean_up_on_disconnect
‪function laststand_clean_up_on_disconnect(e_revivee, w_reviver, w_revive_tool)
Definition: _zm_laststand.gsc:427
‪xp_revive_once_per_round
‪function xp_revive_once_per_round(player_being_revived)
Definition: _zm_laststand.gsc:1482
‪register_info
‪function register_info(type, name, version, lerp_step_count)
Definition: visionset_mgr_shared.csc:334
‪set_ignoreme
‪function set_ignoreme(b_ignoreme)
Definition: _zm_laststand.gsc:1503
‪update_lives_remaining
‪function update_lives_remaining(increment)
Definition: laststand_shared.gsc:200
‪PERK_ADDITIONAL_PRIMARY_WEAPON
‪#define PERK_ADDITIONAL_PRIMARY_WEAPON
Definition: _zm_perks.gsh:30
‪set
‪function set(str_field_name, n_value)
Definition: clientfield_shared.gsc:34
‪can_revive_via_override
‪function can_revive_via_override(e_revivee)
Definition: _zm_laststand.gsc:1659
‪IS_EQUAL
‪#define IS_EQUAL(__a, __b)
Definition: shared.gsh:250
‪take
‪function take(killstreak)
Definition: _killstreaks.gsc:568
‪player_is_in_laststand
‪function player_is_in_laststand()
Definition: laststand_shared.gsc:18
‪auto_revive
‪function auto_revive(reviver, dont_enable_weapons)
Definition: _zm_laststand.gsc:1327
‪__init__
‪function __init__()
Definition: _zm_laststand.gsc:46
‪destroy
‪function destroy(watcher, owner)
Definition: _decoy.gsc:108
‪register
‪function register()
Definition: _ai_tank.gsc:126
‪revive_hud_show_n_fade
‪function revive_hud_show_n_fade(time)
Definition: laststand_shared.gsc:162
‪clean_up_suicide_hud_on_end_game
‪function clean_up_suicide_hud_on_end_game()
Definition: laststand_shared.gsc:76
‪laststand_getup
‪function laststand_getup()
Definition: _zm_laststand.gsc:1533
‪check_for_sacrifice
‪function check_for_sacrifice()
Definition: _zm_laststand.gsc:1578
‪refire_player_downed
‪function refire_player_downed()
Definition: _zm_laststand.gsc:277
‪SHOW_LAST_STAND_PROGRESS_BAR
‪#define SHOW_LAST_STAND_PROGRESS_BAR
Definition: _zm_laststand.gsc:38
‪decrement_ignoreme
‪function decrement_ignoreme()
Definition: _zm_utility.gsc:3840
‪has_hero_weapon
‪function has_hero_weapon()
Definition: weapons_shared.gsc:201
‪name
‪class GroundFx name
‪is_placeable_mine
‪function is_placeable_mine(weapon)
Definition: _zm_utility.gsc:4267
‪ramp_in_thread_per_player
‪function ramp_in_thread_per_player(player, duration)
Definition: visionset_mgr_shared.gsc:229
‪player_last_stand_stats
‪function player_last_stand_stats(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration)
Definition: _zm_laststand.gsc:98
‪ZM_LASTSTAND_VISIONSET
‪#define ZM_LASTSTAND_VISIONSET
Definition: _zm_laststand.gsh:1
‪player_getup_setup
‪function player_getup_setup()
Definition: _zm_laststand.gsc:1526
‪increment_ignoreme
‪function increment_ignoreme()
Definition: _zm_utility.gsc:3833
‪perk_set_max_health_if_jugg
‪function perk_set_max_health_if_jugg(str_perk, set_preMaxHealth, clamp_health_to_max_health)
Definition: _zm_perks.gsc:791
‪WAIT_SERVER_FRAME
‪#define WAIT_SERVER_FRAME
Definition: shared.gsh:265
‪is_reviving_any
‪function is_reviving_any()
Definition: _zm_laststand.gsc:1144