boiii-scripts/mp/_laststand.gsc
2023-04-13 17:30:38 +02:00

275 lines
13 KiB
Plaintext

// tagTMR<NOTE>: 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();
}