// tagTMR: this is a stripped down last stand implementation for the purposes of hooking into // the resurrect gadget. Removed suicide and revive triggers, all hud elements, anything cp/zm specific #using scripts\codescripts\struct; #using scripts\shared\callbacks_shared; #using scripts\shared\demo_shared; #using scripts\shared\flag_shared; #using scripts\shared\hud_util_shared; #using scripts\shared\killcam_shared; #using scripts\shared\laststand_shared; #using scripts\shared\scoreevents_shared; #using scripts\shared\system_shared; #using scripts\shared\util_shared; #using scripts\shared\clientfield_shared; #using scripts\shared\abilities\gadgets\_gadget_resurrect; #using scripts\shared\abilities\_ability_util; #using scripts\mp\gametypes\_globallogic_player; #using scripts\mp\gametypes\_globallogic_spawn; #using scripts\mp\gametypes\_killcam; #namespace laststand; function autoexec __init__sytem__() { system::register("laststand",&__init__,undefined,undefined); } function __init__() { if (level.script=="frontend") { return ; } } function player_last_stand_stats( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration ) { //stat tracking if ( IsDefined( attacker ) && IsPlayer( attacker ) && attacker != self ) { attacker.kills++; if (isdefined(weapon)) { dmgweapon = weapon; weaponPickedUp = false; if( isdefined( attacker.pickedUpWeapons ) && isdefined( attacker.pickedUpWeapons[weapon] ) ) { weaponPickedUp = true; } attacker AddWeaponStat(dmgweapon, "kills", 1, attacker.class_num, weaponPickedUp ); } } self.downs++; } function PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, delayOverride ) { if( self player_is_in_laststand() ) { return; } if ( isdefined( self.resurrect_not_allowed_by ) ) { return; } self globallogic_player::Callback_PlayerKilled(eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, 0, true ); self notify("entering_last_stand"); // check to see if we are in a game module that wants to do something with PvP damage if( isDefined( level._game_module_player_laststand_callback ) ) { self [[ level._game_module_player_laststand_callback ]]( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, delayOverride ); } self.lastStandParams = spawnstruct(); self.lastStandParams.eInflictor = eInflictor; self.lastStandParams.attacker = attacker; self.lastStandParams.iDamage = iDamage; self.lastStandParams.sMeansOfDeath = sMeansOfDeath; self.lastStandParams.sWeapon = weapon; self.lastStandParams.vDir = vDir; self.lastStandParams.sHitLoc = sHitLoc; self.lastStandParams.lastStandStartTime = gettime(); self.lastStandParams.killcam_entity_info_cached = killcam::get_killcam_entity_info( attacker, eInflictor, weapon ); self thread player_last_stand_stats( eInflictor, attacker, iDamage, sMeansOfDeath, weapon, vDir, sHitLoc, psOffsetTime, delayOverride ); self.health = 1; self.laststand = true; self.ignoreme = true; self EnableInvulnerability(); self.meleeAttackers = undefined; self.no_revive_trigger = true; callback::callback( #"on_player_laststand" ); assert( IsDefined( self.resurrect_weapon ) ); // defined in gadget_resurrect.gsc assert( self.resurrect_weapon != level.weaponNone ); slot = self ability_util::gadget_slot_for_type( 40 ); self GadgetStateChange( slot, self.resurrect_weapon, 2 ); self laststand_disable_player_weapons(); self thread MakeSureSwitchToWeapon(); self thread resurrect::enter_rejack_standby(); // UI and input watchers self thread watch_player_input(); demo::bookmark( "player_downed", gettime(), self ); } function MakeSureSwitchToWeapon() { self endon( "death" ); self endon( "disconnect" ); self endon( "bleed_out" ); self endon( "player_input_revive" ); self endon( "player_input_suicide" ); level endon("game_ended"); while( 1 ) { if( self getcurrentweapon() != self.resurrect_weapon ) { self SwitchToWeapon( self.resurrect_weapon ); } {wait(.05);}; } } // self = a player function laststand_disable_player_weapons() { weaponInventory = self GetWeaponsList( true ); self.lastActiveWeapon = self GetCurrentWeapon(); if ( self IsThrowingGrenade() ) { primaryWeapons = self GetWeaponsListPrimaries(); if( IsDefined( primaryWeapons ) && primaryWeapons.size > 0 ) { self.lastActiveWeapon = primaryWeapons[0]; self SwitchToWeaponImmediate( self.lastActiveWeapon ); } } } function laststand_enable_player_weapons( b_allow_grenades = true ) // self == player { self EnableWeaponCycling(); if ( b_allow_grenades ) { self EnableOffhandWeapons(); } if( IsDefined(self.lastActiveWeapon) && (self.lastActiveWeapon != level.weaponNone) && self HasWeapon( self.lastActiveWeapon ) ) { self SwitchToWeapon( self.lastActiveWeapon ); } else { primaryWeapons = self GetWeaponsListPrimaries(); if( IsDefined( primaryWeapons ) && primaryWeapons.size > 0 ) { self SwitchToWeapon( primaryWeapons[0] ); } } } function laststand_clean_up_on_interrupt( playerBeingRevived, reviverGun ) { self endon( "do_revive_ended_normally" ); reviveTrigger = playerBeingRevived.revivetrigger; playerBeingRevived util::waittill_any( "disconnect", "game_ended", "death" ); if( isdefined( reviveTrigger ) ) { reviveTrigger delete(); } self cleanup_suicide_hud(); if( isdefined( self.reviveProgressBar ) ) { self.reviveProgressBar hud::destroyElem(); } if( isdefined( self.reviveTextHud ) ) { self.reviveTextHud destroy(); } } function laststand_clean_up_reviving_any( playerBeingRevived ) { self endon( "do_revive_ended_normally" ); playerBeingRevived util::waittill_any( "disconnect", "zombified", "stop_revive_trigger" ); self.is_reviving_any--; if ( 0 > self.is_reviving_any ) { self.is_reviving_any = 0; } } function bleed_out() { demo::bookmark( "player_bledout", gettime(), self, undefined, 1 ); level notify("bleed_out", self.characterindex); self UndoLastStand(); self.ignoreme = false; self.laststand = undefined; self.useLastStandParams = true; // attacker may have become undefined if the player that killed me has disconnected if ( !isDefined( self.lastStandParams.attacker ) ) { self.lastStandParams.attacker = self; } self suicide(); } function watch_player_input() // self == player { self thread watch_player_input_revive(); self thread watch_player_input_suicide(); } function watch_player_input_revive() // self == player { level endon("game_ended"); self endon( "player_input_bleed_out" ); self endon( "disconnect" ); self endon( "death" ); self waittill("player_input_revive"); demo::bookmark( "player_revived", gettime(), self, self ); self Rejack(); // TODO: split this out into gadget-specific territory and keep this file last stand only self laststand_enable_player_weapons(); self.ignoreme = false; self DisableInvulnerability(); self.laststand = undefined; } function watch_player_input_suicide() // self == player { level endon("game_ended"); self endon( "player_input_revive" ); self endon( "disconnect" ); self endon( "death" ); self waittill("player_input_suicide"); self bleed_out(); }