1039 lines
30 KiB
Plaintext
1039 lines
30 KiB
Plaintext
#include common_scripts\utility;
|
|
#include maps\mp\alien\_utility;
|
|
#include maps\mp\_utility;
|
|
|
|
CONST_AFTER_REVIVE_DAMAGE_SHIELD_TIME = 3000; // in ms
|
|
CONST_SELF_REVIVE_WAIT = 5;
|
|
CONST_BLEED_OUT_TIME = 35; // in sec
|
|
CONST_SPECTATOR_REVIVE_TIME = 6000; // in ms
|
|
CONST_NORMAL_REVIVE_TIME = 5000; // in ms
|
|
CONST_REVIVE_PENALTY = 2000; // in ms
|
|
CONST_REVIVE_TIME_CAP = 10000; // in ms
|
|
CONST_CURRENCY_PENALTY = 500;
|
|
CONST_INITIAL_LASTSTANDS = 1;
|
|
|
|
CONST_FAST_REVIVE_UPGRADE_SCALAR = 1.20; // 20% faster revives with this upgrade purchased
|
|
|
|
CONST_BLACK_VISION_SET = "black_bw";
|
|
CONST_B_AND_W_VISION_SET = "cheat_bw";
|
|
CONST_BLEED_OUT_DOGTAG_MODEL = "prop_dogtags_friend_iw6";
|
|
CONST_BLEED_OUT_DOGTAG_MODEL_ANIM = "mp_dogtag_spin";
|
|
|
|
UI_REVIVING = 3;
|
|
UI_DOWNEDPLAYER = 4;
|
|
|
|
DROP_TO_GROUND_UP_DIST = 32;
|
|
DROP_TO_GROUND_DOWN_DIST = -64;
|
|
|
|
Callback_PlayerLastStandAlien( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, psOffsetTime, deathAnimDuration, bleedOutSpawnEntity )
|
|
{
|
|
blackBox_lastStand( attacker, iDamage );
|
|
|
|
if ( maps\mp\alien\_utility::is_chaos_mode() )
|
|
maps\mp\alien\_chaos_laststand::chaos_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity );
|
|
else
|
|
regularExtinction_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity );
|
|
}
|
|
|
|
regularExtinction_PlayerLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity )
|
|
{
|
|
gameShouldEnd = gameShouldEnd( self );
|
|
|
|
if ( gameShouldEnd )
|
|
level thread maps\mp\gametypes\aliens::AlienEndGame( "axis", maps\mp\alien\_hud::get_end_game_string_index( "kia" ) );
|
|
|
|
if ( self.inLastStand )
|
|
forceBleedOut( bleedOutSpawnEntity );
|
|
else
|
|
dropIntoLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity, gameShouldEnd );
|
|
}
|
|
|
|
forceBleedOut( bleedOutSpawnEntity )
|
|
{
|
|
Assert( is_killed_by_kill_trigger( bleedOutSpawnEntity ) ); // The force bleed out situation can only happen when player falls off the world while in laststand. The bleedOutSpawnEntity has to be defined in that case.
|
|
|
|
if ( isPlayingSolo() )
|
|
self setOrigin( bleedOutSpawnEntity.origin );
|
|
|
|
self.bleedOutSpawnEntityOverride = bleedOutSpawnEntity;
|
|
|
|
self notify ( "force_bleed_out" );
|
|
}
|
|
|
|
dropIntoLastStand( eInflictor, attacker, iDamage, sMeansOfDeath, sWeapon, vDir, sHitLoc, bleedOutSpawnEntity, gameShouldEnd )
|
|
{
|
|
self endon( "disconnect" );
|
|
level endon( "game_ended" );
|
|
|
|
self notify( "last_stand" );
|
|
|
|
enter_GamemodeSpecificAction();
|
|
|
|
enter_laststand();
|
|
|
|
if ( mayDoLastStandAlien( self, gameShouldEnd, bleedOutSpawnEntity ) )
|
|
{
|
|
revived = waitInLastStand( bleedOutSpawnEntity, gameShouldEnd );
|
|
|
|
if ( !revived )
|
|
waitInSpecator( bleedOutSpawnEntity, gameShouldEnd );
|
|
}
|
|
else
|
|
{
|
|
waitInSpecator( bleedOutSpawnEntity, gameShouldEnd );
|
|
}
|
|
|
|
self notify( "revive" );
|
|
|
|
exit_laststand();
|
|
|
|
exit_GamemodeSpecificAction();
|
|
}
|
|
|
|
enter_laststand()
|
|
{
|
|
self.inLastStand = true;
|
|
self.lastStand = true;
|
|
self.ignoreme = true;
|
|
self.health = 1;
|
|
self _disableUsability();
|
|
}
|
|
|
|
exit_laststand()
|
|
{
|
|
// should be reverse of enter_laststand()
|
|
self LastStandRevive();
|
|
self setStance( "stand" );
|
|
|
|
self.inLastStand = false;
|
|
self.lastStand = undefined;
|
|
self.ignoreme = false;
|
|
self.health = maps\mp\gametypes\aliens::getHealthCap();
|
|
self _enableUsability();
|
|
}
|
|
|
|
// has to be called after store_weapons_status.
|
|
enter_GamemodeSpecificAction_GetCurrentWeapon( exclusion_list )
|
|
{
|
|
lastWeapon = self GetCurrentWeapon();
|
|
|
|
if ( lastWeapon == "none" )
|
|
{
|
|
return self.copy_fullweaponlist[ 0 ];
|
|
}
|
|
|
|
foreach( excluded_weapon in exclusion_list )
|
|
{
|
|
if ( lastWeapon == excluded_weapon )
|
|
{
|
|
return self.copy_fullweaponlist[ 0 ];
|
|
}
|
|
}
|
|
|
|
return lastWeapon;
|
|
}
|
|
|
|
enter_GamemodeSpecificAction()
|
|
{
|
|
level thread maps\mp\alien\_music_and_dialog::playVOForDowned( self );
|
|
maps\mp\alien\_gamescore::update_team_encounter_performance( maps\mp\alien\_gamescore::get_team_score_component_name(), "num_players_enter_laststand" );
|
|
|
|
//maps\mp\killstreaks\_remotetank::restoreweapons(); //try to restore the weapons from the MP killstreaks before storing for last stand ( store_weapons_status will store an undefined array and fail)
|
|
weapons_excluded = [ "alienbomb_mp",
|
|
"killstreak_remote_uav_mp",
|
|
"mortar_detonator_mp",
|
|
"switchblade_laptop_mp",
|
|
"aliendeployable_crate_marker_mp",
|
|
"iw6_alienminigun_mp",
|
|
"iw6_alienminigun1_mp",
|
|
"iw6_alienminigun2_mp",
|
|
"iw6_alienminigun3_mp",
|
|
"iw6_alienminigun4_mp",
|
|
"iw6_alienmk32_mp",
|
|
"iw6_alienmk321_mp",
|
|
"iw6_alienmk322_mp",
|
|
"iw6_alienmk323_mp",
|
|
"iw6_alienmk324_mp",
|
|
"alienflare_mp",
|
|
"aliensemtex_mp",
|
|
"alienclaymore_mp",
|
|
"alientrophy_mp",
|
|
"alienbetty_mp",
|
|
"alienthrowingknife_mp",
|
|
"iw6_alienmaaws_mp",
|
|
"alienmortar_shell_mp",
|
|
"iw6_aliendlc21_mp",
|
|
"iw6_aliendlc22_mp" ,
|
|
"iw6_aliendlc31_mp",
|
|
"iw6_aliendlc32_mp" ,
|
|
"iw6_aliendlc33_mp" ,
|
|
"iw6_aliendlc43_mp",
|
|
"aliencortex_mp" ];
|
|
|
|
self store_weapons_status( weapons_excluded ); // store weapons, but only ones allowed, drill is removed here as it will spawn on laststand
|
|
self.lastWeapon = enter_GamemodeSpecificAction_GetCurrentWeapon( weapons_excluded ); // must be called after store_weapons_status
|
|
self.bleedOutSpawnEntityOverride = undefined;
|
|
self.laststand_pistol = self GetWeaponsListPrimaries()[0];
|
|
self.being_revived = false;
|
|
self thread only_use_weapon();
|
|
self maps\mp\alien\_persistence::take_player_currency( CONST_CURRENCY_PENALTY, true );
|
|
self maps\mp\alien\_persistence::eog_player_update_stat( "downs", 1 );
|
|
self maps\mp\alien\_alien_matchdata::inc_downed_counts();
|
|
|
|
//update the "no last stand" challenge
|
|
maps\mp\alien\_challenge::update_challenge( "no_laststand" );
|
|
|
|
self setClientOmnvar( "ui_alien_player_in_laststand", true );
|
|
|
|
/#
|
|
self maps\mp\alien\_hud::update_hud_laststand_count();
|
|
#/
|
|
}
|
|
|
|
exit_GamemodeSpecificAction()
|
|
{
|
|
self thread maps\mp\alien\_music_and_dialog::ext_last_stand_sfx();
|
|
self.haveInvulnerabilityAvailable = true;
|
|
self.damageShieldExpireTime = getTime() + CONST_AFTER_REVIVE_DAMAGE_SHIELD_TIME;
|
|
self VisionSetNakedForPlayer( "", 0 );
|
|
self maps\mp\alien\_utility::restore_client_fog( 0 );
|
|
self maps\mp\alien\_progression::restore_all_perks();
|
|
|
|
/#
|
|
if ( alien_mode_has( "nogame" ) )
|
|
{
|
|
self.laststand_ammo = WeaponMaxAmmo( self.laststand_pistol );
|
|
self.laststand_clip_ammo = WeaponClipSize( self.laststand_pistol );
|
|
}
|
|
#/
|
|
self SetWeaponAmmoStock( self.laststand_pistol, self.laststand_ammo );
|
|
self SetWeaponAmmoClip( self.laststand_pistol, self.laststand_clip_ammo );
|
|
|
|
inclusion_list = ["alienflare_mp",
|
|
"aliensemtex_mp",
|
|
"alienclaymore_mp",
|
|
"alientrophy_mp",
|
|
"alienbetty_mp",
|
|
"alienthrowingknife_mp",
|
|
"alienmortar_shell_mp",
|
|
"iw6_aliendlc21_mp",
|
|
"iw6_aliendlc22_mp",
|
|
"iw6_aliendlc31_mp",
|
|
"iw6_aliendlc32_mp",
|
|
"iw6_aliendlc43_mp",
|
|
"iw6_aliendlc33_mp" ];
|
|
|
|
self restore_weapons_status( inclusion_list );
|
|
|
|
self setClientOmnvar( "ui_alien_player_in_laststand", false );
|
|
self.laststand_ammo = undefined;
|
|
self.bleedOutSpawnEntityOverride = undefined;
|
|
self maps\mp\alien\_alien_matchdata::inc_revived_counts();
|
|
self SetSpawnWeapon( self.lastWeapon );
|
|
maps\mp\alien\_death::set_kill_trigger_event_processed( self, false );
|
|
|
|
if( is_chaos_mode() )
|
|
maps\mp\alien\_chaos_laststand::chaos_exit_GamemodeSpecificAction( self );
|
|
|
|
}
|
|
|
|
waitInLastStand( bleedOutSpawnEntity, gameShouldEnd )
|
|
{
|
|
self endon( "disconnect" );
|
|
self endon( "revive");
|
|
level endon( "game_ended" );
|
|
/#
|
|
if ( self maps\mp\alien\_debug::shouldSelfRevive() )
|
|
return debug_self_revive();
|
|
#/
|
|
if ( !gameShouldEnd )
|
|
{
|
|
self visionFadeToBlack( CONST_BLEED_OUT_TIME );
|
|
self thread playDeathSoundInLastStand( CONST_BLEED_OUT_TIME );
|
|
|
|
if ( isPlayingSolo() )
|
|
{
|
|
take_lastStand( self, 1 );
|
|
self setClientOmnvar ( "ui_laststand_end_milliseconds", gettime() + ( CONST_SELF_REVIVE_WAIT * 1000 ) );
|
|
register_laststand_ammo();
|
|
}
|
|
else
|
|
{
|
|
self setClientOmnvar ( "ui_laststand_end_milliseconds", gettime() + ( CONST_BLEED_OUT_TIME * 1000 ) );
|
|
}
|
|
}
|
|
|
|
if ( isPlayingSolo() )
|
|
return ( wait_for_self_revive( bleedOutSpawnEntity, gameShouldEnd ) );
|
|
else
|
|
return ( wait_to_be_revived( self, self.origin, undefined, undefined, true, CONST_NORMAL_REVIVE_TIME, (0.33, 0.75, 0.24), CONST_BLEED_OUT_TIME, false, gameShouldEnd ) );
|
|
}
|
|
|
|
waitInSpecator( bleedOutSpawnEntity, gameShouldEnd )
|
|
{
|
|
self endon( "disconnect" );
|
|
level endon( "game_ended" );
|
|
|
|
self notify( "death" );
|
|
|
|
register_laststand_ammo();
|
|
|
|
waitframe(); // Clear out callstack to prevent overrun
|
|
|
|
// register downed
|
|
level.alienBBData[ "times_died" ]++;
|
|
self maps\mp\alien\_persistence::eog_player_update_stat( "deaths", 1 );
|
|
|
|
if ( isDefined ( self.bleedOutSpawnEntityOverride ) )
|
|
{
|
|
bleedOutSpawnEntity = self.bleedOutSpawnEntityOverride;
|
|
self.bleedOutSpawnEntityOverride = undefined;
|
|
}
|
|
|
|
if ( is_killed_by_kill_trigger( bleedOutSpawnEntity ) )
|
|
{
|
|
spawnLoc = drop_to_ground( bleedOutSpawnEntity.origin, DROP_TO_GROUND_UP_DIST, DROP_TO_GROUND_DOWN_DIST );
|
|
spawnAngle = bleedOutSpawnEntity.angles;
|
|
}
|
|
else
|
|
{
|
|
maps\mp\alien\_gamescore::update_team_encounter_performance( maps\mp\alien\_gamescore::get_team_score_component_name(), "num_players_bleed_out" );
|
|
maps\mp\alien\_alien_matchdata::inc_bleedout_counts();
|
|
|
|
spawnLoc = self.origin;
|
|
spawnAngle = self.angles;
|
|
}
|
|
|
|
maps\mp\alien\_challenge::update_challenge( "no_bleedout" );
|
|
self setClientOmnvar ( "ui_laststand_end_milliseconds", 0 ); //remove last stand timer
|
|
|
|
result = wait_to_be_revived( self, spawnLoc, CONST_BLEED_OUT_DOGTAG_MODEL, CONST_BLEED_OUT_DOGTAG_MODEL_ANIM, false, CONST_SPECTATOR_REVIVE_TIME, ( 1.0, 0, 0 ), undefined, true, gameShouldEnd );
|
|
assert( result == true ); // sanity check
|
|
|
|
self updateSessionState( "playing" );
|
|
|
|
self.forceSpawnOrigin = spawnLoc;
|
|
self.forceSpawnAngles = spawnAngle;
|
|
|
|
if ( isDefined( self.forceTeleportOrigin ) )
|
|
self.forceSpawnOrigin = self.forceTeleportOrigin;
|
|
if ( isDefined( self.forceTeleportAngles ) )
|
|
self.forceSpawnAngles= self.forceTeleportAngles;
|
|
|
|
self maps\mp\gametypes\_playerlogic::spawnPlayer( true );
|
|
}
|
|
|
|
wait_for_self_revive( bleedOutSpawnEntity, gameShouldEnd )
|
|
{
|
|
if ( gameShouldEnd )
|
|
{
|
|
level waittill( "forever" ); //<NOTE J.C.> When this happens, the "game_ended" notify will already happen. Wait here is to
|
|
self setClientOmnvar ( "ui_laststand_end_milliseconds", 0 ); // make sure the player stays in this state until game fully ended.
|
|
return false; // Returning a false here is to be logically consistent of always returning true/false from this function
|
|
}
|
|
|
|
if ( is_killed_by_kill_trigger( bleedOutSpawnEntity ) )
|
|
self setOrigin( bleedOutSpawnEntity.origin );
|
|
else
|
|
wait CONST_SELF_REVIVE_WAIT;
|
|
|
|
self setClientOmnvar ( "ui_laststand_end_milliseconds", 0 );
|
|
return true;
|
|
}
|
|
|
|
|
|
wait_to_be_revived( downedPlayer, spawnLoc, entityModel, entityModelAnim, linkToOwner, reviveTime, iconColor, timeLimit, shouldSpectate, gameShouldEnd, isChaosMode )
|
|
{
|
|
register_laststand_ammo();
|
|
|
|
reviveEnt = makeReviveEntity( downedPlayer, spawnLoc, entityModel, entityModelAnim, linkToOwner );
|
|
reviveEnt thread cleanUpReviveEnt( downedPlayer );
|
|
|
|
if ( is_true( isChaosMode ))
|
|
self _disableWeapon();
|
|
|
|
if ( shouldSpectate )
|
|
self thread enter_spectate( downedPlayer, spawnLoc, reviveEnt );
|
|
|
|
if ( gameShouldEnd )
|
|
{
|
|
level waittill( "forever" ); //<NOTE J.C.> When this happens, the "game_ended" notify will already happen. Wait here is to
|
|
// make sure the player stays in this state until game fully ended.
|
|
return false; // Returning a false here is to be logically consistent of always returning true/false from this function
|
|
}
|
|
else
|
|
{
|
|
reviveIconEnt = reviveEnt;
|
|
|
|
if ( shouldSpectate )
|
|
reviveIconEnt = makeReviveIconEntity( downedPlayer, reviveEnt );
|
|
|
|
reviveIconEnt maps\mp\alien\_hud::makeReviveIcon( downedPlayer, iconColor, timeLimit );
|
|
|
|
downedPlayer.reviveEnt = reviveEnt;
|
|
downedPlayer.reviveIconEnt = reviveIconEnt;
|
|
|
|
reviveEnt thread lastStandWaittillLifeReceived( downedPlayer, reviveTime );
|
|
|
|
if ( isDefined( timeLimit ) )
|
|
result = reviveEnt waittill_any_ents_or_timeout_return( timeLimit, reviveEnt, "revive_success", downedPlayer, "force_bleed_out" , downedPlayer , "revive_success" );
|
|
else if ( !isDefined( timelimit) && is_true( isChaosMode ) )
|
|
result = reviveEnt waittill_any_ents_return( reviveEnt, "revive_success", downedPlayer, "force_bleed_out" , downedPlayer , "revive_success" );
|
|
else
|
|
result = reviveEnt waittill_any_return( "revive_success" );
|
|
|
|
if ( result == "timeout" && is_being_revived( downedPlayer ) )
|
|
result = reviveEnt waittill_any_return( "revive_success", "revive_fail" );
|
|
|
|
if ( result == "revive_success" )
|
|
{
|
|
if ( is_true( isChaosMode ))
|
|
self _enableWeapon();
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
|
|
lastStandWaittillLifeReceived( downedPlayer, reviveTime )
|
|
{
|
|
self endon( "death" );
|
|
level endon( "game_ended" );
|
|
|
|
while ( true )
|
|
{
|
|
self MakeUsable();
|
|
self waittill( "trigger", reviver );
|
|
self makeUnUsable();
|
|
|
|
if ( !isplayer( reviver ) || !( reviver isOnGround() ) )
|
|
continue;
|
|
|
|
reviveTimeScaler = reviver maps\mp\alien\_perk_utility::perk_GetReviveTimeScalar();
|
|
|
|
if ( downedPlayer maps\mp\alien\_persistence::is_upgrade_enabled( "faster_revive_upgrade" ) )
|
|
reviveTimeScaler = reviveTimeScaler * CONST_FAST_REVIVE_UPGRADE_SCALAR;
|
|
|
|
reviveTimeScaled = int( reviveTime / reviveTimeScaler );
|
|
revive_success = get_revive_result( downedPlayer, reviver, self.origin, reviveTimeScaled );
|
|
|
|
if ( revive_success )
|
|
{
|
|
record_revive_success( reviver, downedPlayer );
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
self notify( "revive_fail" );
|
|
continue;
|
|
}
|
|
}
|
|
downedPlayer setClientOmnvar ( "ui_laststand_end_milliseconds", 0 );
|
|
self notify( "revive_success" );
|
|
}
|
|
|
|
medic_revive( reviver, downedPlayer )
|
|
{
|
|
instant_revive( downedPlayer );
|
|
record_revive_success( reviver, downedPlayer );
|
|
}
|
|
|
|
record_revive_success( reviver, downedPlayer )
|
|
{
|
|
level thread maps\mp\alien\_music_and_dialog::playVOForRevived( reviver );
|
|
//<NOTE J.C.> Ideally, this should be move to the game mode specific action section but there is no clean way to pass the revive back up
|
|
reviver maps\mp\alien\_persistence::set_player_revives();
|
|
reviver maps\mp\alien\_persistence::eog_player_update_stat( "revives", 1 );
|
|
downedPlayer thread maps\mp\gametypes\_hud_message::playerCardSplashNotify( "revived", reviver );
|
|
}
|
|
|
|
makeReviveEntity( downedPlayer, spawnLoc, entityModel, entityModelAnim, linkToOwner )
|
|
{
|
|
REVIVE_ENT_VERTICAL_OFFSET = ( 0, 0, 20 );
|
|
|
|
spawnLoc = drop_to_ground( spawnLoc + REVIVE_ENT_VERTICAL_OFFSET, DROP_TO_GROUND_UP_DIST, DROP_TO_GROUND_DOWN_DIST );
|
|
reviveEnt = spawn( "script_model", spawnLoc );
|
|
reviveEnt setCursorHint( "HINT_NOICON" );
|
|
reviveEnt setHintString( &"PLATFORM_REVIVE" );
|
|
reviveEnt.owner = downedPlayer;
|
|
reviveEnt.inUse = false;
|
|
reviveEnt.targetname = "revive_trigger";
|
|
|
|
if ( isDefined( entityModel ) )
|
|
reviveEnt setModel( entityModel );
|
|
|
|
if ( isDefined( entityModelAnim ) )
|
|
reviveEnt ScriptModelPlayAnim( entityModelAnim );
|
|
|
|
if ( linkToOwner )
|
|
reviveEnt linkTo( downedPlayer, "tag_origin", REVIVE_ENT_VERTICAL_OFFSET, ( 0, 0, 0 ) );
|
|
|
|
return reviveEnt;
|
|
}
|
|
|
|
makeReviveIconEntity( downedPlayer, reviveEnt )
|
|
{
|
|
// When bleed out, we need an entity above revive ent to set the HUD waypoint to
|
|
VERTICAL_OFFSET_ABOVE_REVIVE_ENT = ( 0, 0, 30 );
|
|
reviveIconEnt = spawn( "script_model", reviveEnt.origin + VERTICAL_OFFSET_ABOVE_REVIVE_ENT );
|
|
reviveIconEnt thread cleanUpReviveEnt( downedPlayer );
|
|
|
|
return reviveIconEnt;
|
|
}
|
|
|
|
mayDoLastStandAlien( player, gameShouldEnd, bleedOutSpawnEntity )
|
|
{
|
|
/#
|
|
if ( alien_mode_has( "nogame" ) )
|
|
return true;
|
|
#/
|
|
|
|
if ( isPlayingSolo() )
|
|
return solo_mayDoLastStand( gameShouldEnd, bleedOutSpawnEntity );
|
|
else
|
|
return coop_mayDoLastStand( bleedOutSpawnEntity );
|
|
}
|
|
|
|
solo_mayDoLastStand( gameShouldEnd, bleedOutSpawnEntity )
|
|
{
|
|
if ( gameShouldEnd && is_killed_by_kill_trigger( bleedOutSpawnEntity ) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
coop_mayDoLastStand( bleedOutSpawnEntity )
|
|
{
|
|
if ( is_killed_by_kill_trigger( bleedOutSpawnEntity ) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
only_use_weapon( weapon )
|
|
{
|
|
if ( isDefined ( self.isCarrying ) && self.isCarrying ) //player was carrying an object...wait until it deletes
|
|
{
|
|
wait ( .5 );
|
|
}
|
|
|
|
pistol = self GetWeaponsListPrimaries()[0];
|
|
|
|
save_weapon_list = ["alienflare_mp",
|
|
"aliensemtex_mp",
|
|
"alienclaymore_mp",
|
|
"alientrophy_mp",
|
|
"alienbetty_mp",
|
|
"iw6_aliendlc43_mp",
|
|
"alienthrowingknife_mp" ,
|
|
"alienmortar_shell_mp",
|
|
"iw6_aliendlc21_mp",
|
|
"iw6_aliendlc22_mp" ,
|
|
"iw6_aliendlc31_mp",
|
|
"iw6_aliendlc32_mp" ,
|
|
"iw6_aliendlc33_mp" ];
|
|
|
|
can_use_pistol = can_use_pistol_during_last_stand( self );
|
|
|
|
if( can_use_pistol )
|
|
save_weapon_list[save_weapon_list.size] = pistol;
|
|
|
|
self _takeWeaponsExceptList( save_weapon_list );
|
|
|
|
if( can_use_pistol )
|
|
{
|
|
pistol_ammo = self GetAmmoCount( pistol );
|
|
pistol_clip_size = WeaponClipSize( pistol );
|
|
|
|
if( pistol_ammo < pistol_clip_size )
|
|
{
|
|
self SetWeaponAmmoClip( pistol, pistol_clip_size );
|
|
}
|
|
self SwitchToWeapon( pistol );
|
|
}
|
|
}
|
|
|
|
can_use_pistol_during_last_stand( player )
|
|
{
|
|
if ( is_chaos_mode() && player get_last_stand_count() == 0 )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
cleanUpReviveEnt( owner )
|
|
{
|
|
self endon ( "death" );
|
|
|
|
owner waittill_any( "death", "disconnect", "revive" );
|
|
self delete();
|
|
}
|
|
|
|
player_init_laststand()
|
|
{
|
|
if ( maps\mp\alien\_utility::is_chaos_mode() )
|
|
maps\mp\alien\_chaos_laststand::chaos_player_init_laststand();
|
|
else
|
|
regularExtinction_player_init_laststand();
|
|
}
|
|
|
|
regularExtinction_player_init_laststand()
|
|
{
|
|
if ( isPlayingSolo() && !IsSplitScreen() )
|
|
{
|
|
set_last_stand_count( self, CONST_INITIAL_LASTSTANDS );
|
|
self thread init_selfrevive_icon( CONST_INITIAL_LASTSTANDS );
|
|
}
|
|
}
|
|
|
|
init_selfrevive_icon( initial_lastStand_count )
|
|
{
|
|
self endon( "death" );
|
|
self endon( "disconnect" );
|
|
level endon( "game_ended" );
|
|
wait 5.0;
|
|
|
|
selfrevive_count = self get_last_stand_count();
|
|
assert( selfrevive_count == initial_lastStand_count );
|
|
|
|
self SetClientOmnvar( "ui_alien_selfrevive", selfrevive_count );
|
|
}
|
|
|
|
give_lastStand( player, num )
|
|
{
|
|
if ( !isDefined( num ) )
|
|
num = 1;
|
|
|
|
new_last_stand_count = ( player get_last_stand_count() ) + num;
|
|
set_last_stand_count( player, new_last_stand_count );
|
|
}
|
|
|
|
take_lastStand( player, num )
|
|
{
|
|
if ( !isDefined( num ) )
|
|
num = 1;
|
|
|
|
new_last_stand_count = ( player get_last_stand_count() ) - num;
|
|
set_last_stand_count( player, max( new_last_stand_count, 0 ) );
|
|
}
|
|
|
|
gameShouldEnd( player_just_down )
|
|
{
|
|
/#
|
|
if ( maps\mp\alien\_debug::self_revive_activated() )
|
|
return false;
|
|
|
|
if ( alien_mode_has( "nogame" ) )
|
|
return false;
|
|
#/
|
|
|
|
if( isPlayingSolo() )
|
|
return solo_gameShouldEnd( player_just_down );
|
|
else
|
|
return coop_gameShouldEnd( player_just_down );
|
|
}
|
|
|
|
solo_gameShouldEnd( player_just_down )
|
|
{
|
|
if ( player_just_down.inLastStand )
|
|
return false;
|
|
|
|
return ( player_just_down get_last_stand_count() == 0 );
|
|
}
|
|
|
|
coop_gameShouldEnd( player_just_down )
|
|
{
|
|
return everyone_else_all_in_lastStand( player_just_down );
|
|
}
|
|
|
|
everyone_else_all_in_lastStand( player_just_down )
|
|
{
|
|
foreach( player in level.players )
|
|
{
|
|
if ( player == player_just_down )
|
|
continue;
|
|
|
|
if ( !player_in_laststand( player ) )
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
get_revive_result( downed_player, reviver, pos, use_time )
|
|
{
|
|
reviver.isCapturingCrate = true;
|
|
|
|
use_ent = createUseEnt( pos );
|
|
use_ent thread cleanUpReviveEnt( downed_player );
|
|
result = revive_use_hold_think( downed_player, reviver, use_ent, use_time );
|
|
|
|
reviver.isCapturingCrate = false;
|
|
|
|
return result;
|
|
}
|
|
|
|
createUseEnt( pos )
|
|
{
|
|
useEnt = Spawn( "script_origin", pos );
|
|
useEnt.curProgress = 0;
|
|
useEnt.useTime = 0;
|
|
useEnt.useRate = 8000;
|
|
useEnt.inUse = false;
|
|
|
|
return useEnt;
|
|
}
|
|
|
|
playDeathSoundInLastStand( bleedOutTime )
|
|
{
|
|
self endon( "disconnect" );
|
|
self endon( "revive" );
|
|
level endon( "game_ended" );
|
|
|
|
self playDeathSound();
|
|
|
|
wait bleedOutTime / 3;
|
|
self playDeathSound();
|
|
|
|
wait bleedOutTime / 3;
|
|
self playDeathSound();
|
|
}
|
|
|
|
visionFadeToBlack( transitionTime )
|
|
{
|
|
ASSET_SPECIFIC_TRANSITION_TIME_SCALER = 2.4; // making the transition look good
|
|
self VisionSetNakedForPlayer( CONST_BLACK_VISION_SET, transitionTime * ASSET_SPECIFIC_TRANSITION_TIME_SCALER );
|
|
self maps\mp\alien\_utility::restore_client_fog( 0 );
|
|
}
|
|
|
|
enter_spectate( downedPlayer, spawnLoc, reviveEnt )
|
|
{
|
|
downedPlayer endon( "disconnect" );
|
|
level endon( "game_ended" );
|
|
|
|
enter_camera_zoomout();
|
|
|
|
camera_zoomout( downedPlayer, spawnLoc, reviveEnt );
|
|
|
|
exit_camera_zoomout();
|
|
}
|
|
|
|
camera_zoomout( downedPlayer, spawnLoc, reviveEnt )
|
|
{
|
|
reviveEnt endon( "revive_success" );
|
|
|
|
VERTICAL_PADDING = ( 0, 0, 30 );
|
|
START_VERTICAL_OFFSET = ( 0, 0, 100 );
|
|
FLY_UP_VERTICAL_OFFSET = ( 0, 0, 400 );
|
|
CAMERA_ZOOM_OUT_TIME = 2.0;
|
|
CAMERA_ACCE_TIME = 0.6;
|
|
CAMERA_DECE_TIME = 0.6;
|
|
|
|
startPos = spawnLoc + VERTICAL_PADDING;
|
|
trace = BulletTrace( startPos, startPos + START_VERTICAL_OFFSET, false, downedPlayer );
|
|
camera_fly_start_pos = trace[ "position" ];
|
|
trace = BulletTrace( camera_fly_start_pos, camera_fly_start_pos + FLY_UP_VERTICAL_OFFSET, false, downedPlayer );
|
|
camera_fly_end_pos = trace[ "position" ];
|
|
|
|
mover = spawn( "script_model", camera_fly_start_pos );
|
|
mover setmodel( "tag_origin" );
|
|
mover.angles = VectorToAngles( ( 0, 0, -1 ) );
|
|
mover thread cleanUpReviveEnt( downedPlayer );
|
|
|
|
downedPlayer CameraLinkTo( mover, "tag_origin" );
|
|
|
|
mover moveTo( camera_fly_end_pos, CAMERA_ZOOM_OUT_TIME , CAMERA_ACCE_TIME, CAMERA_DECE_TIME );
|
|
mover waittill( "movedone" );
|
|
mover delete();
|
|
|
|
downedPlayer maps\mp\gametypes\_playerlogic::respawn_asSpectator();
|
|
}
|
|
|
|
enter_camera_zoomout()
|
|
{
|
|
self PlayerHide(); // hide player's body so only the corpse can be seen
|
|
self FreezeControls( true );
|
|
self VisionSetNakedForPlayer( CONST_B_AND_W_VISION_SET, 0 );
|
|
self maps\mp\alien\_utility::restore_client_fog( 0 );
|
|
}
|
|
|
|
exit_camera_zoomout()
|
|
{
|
|
self CameraUnlink();
|
|
self FreezeControls( false );
|
|
}
|
|
|
|
revive_use_hold_think( downed_player, reviver, use_ent, use_time )
|
|
{
|
|
enter_revive_use_hold_think( downed_player, reviver, use_ent, use_time );
|
|
thread wait_for_exit_revive_use_hold_think( downed_player, reviver, use_ent );
|
|
|
|
current_progress = 0;
|
|
result = false;
|
|
|
|
while ( should_revive_continue( reviver ) )
|
|
{
|
|
if ( current_progress >= use_time )
|
|
{
|
|
result = true;
|
|
break;
|
|
}
|
|
downed_player SetClientOmnvar ( "ui_securing_progress",current_progress / use_time);
|
|
reviver SetClientOmnvar ( "ui_securing_progress",current_progress / use_time );
|
|
current_progress += 50; // in ms
|
|
waitframe();
|
|
}
|
|
|
|
use_ent notify ( "use_hold_think_complete" );
|
|
use_ent waittill ( "exit_use_hold_think_complete" );
|
|
return result;
|
|
}
|
|
|
|
enter_revive_use_hold_think( downed_player, reviver, use_ent, use_time )
|
|
{
|
|
downed_player SetClientOmnvar( "ui_securing",UI_DOWNEDPLAYER );
|
|
reviver SetClientOmnvar( "ui_securing",UI_REVIVING );
|
|
|
|
downed_player.being_revived = true;
|
|
|
|
reviver playerLinkTo( use_ent );
|
|
reviver PlayerLinkedOffsetEnable();
|
|
//reviver _disableWeapon();
|
|
reviver disable_weapon_timeout( ( use_time + 0.05 ), "revive_weapon_management" );
|
|
reviver.isReviving = true;
|
|
}
|
|
|
|
wait_for_exit_revive_use_hold_think( downed_player, reviver, use_ent )
|
|
{
|
|
waittill_any_ents( use_ent, "use_hold_think_complete", downed_player, "disconnect", downed_player, "revive_success", downed_player, "force_bleed_out" );
|
|
|
|
if ( isReallyAlive( downed_player ) ) // downed_player might already disconnect
|
|
{
|
|
downed_player.being_revived = false;
|
|
downed_player SetClientOmnvar( "ui_securing",0 );
|
|
}
|
|
|
|
reviver Unlink();
|
|
//reviver _enableWeapon();
|
|
reviver enable_weapon_wrapper( "revive_weapon_management" );
|
|
reviver SetClientOmnvar( "ui_securing",0 );
|
|
reviver.isReviving = false;
|
|
|
|
use_ent notify( "exit_use_hold_think_complete" );
|
|
}
|
|
|
|
should_revive_continue( reviver )
|
|
{
|
|
return ( !level.gameEnded && isReallyAlive( reviver ) && reviver useButtonPressed() && !reviver.inLastStand );
|
|
}
|
|
|
|
register_laststand_ammo()
|
|
{
|
|
self.laststand_ammo = self GetWeaponAmmoStock( self.laststand_pistol );
|
|
self.laststand_clip_ammo = self GetWeaponAmmoClip( self.laststand_pistol );
|
|
}
|
|
|
|
_takeWeaponsExceptList( saveWeaponList )
|
|
{
|
|
weaponsList = self GetWeaponsListAll();
|
|
|
|
foreach ( weapon in weaponsList )
|
|
{
|
|
if ( array_contains( saveWeaponList, weapon ) )
|
|
{
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
self takeWeapon( weapon );
|
|
}
|
|
}
|
|
}
|
|
|
|
blackBox_lastStand( attacker, iDamage )
|
|
{
|
|
// =========================== blackbox print [START] ===========================
|
|
// register downed
|
|
level.alienBBData[ "times_downed" ]++;
|
|
|
|
// is attacker agent, if so, what type
|
|
attacker_is_agent = IsAgent( attacker ); // boolean
|
|
|
|
if ( attacker_is_agent )
|
|
{
|
|
attacker_alive_time = ( gettime() - attacker.birthtime ) / 1000;
|
|
|
|
attacker_agent_type = "unknown agent";
|
|
if ( isdefined( attacker.agent_type ) )
|
|
{
|
|
attacker_agent_type = attacker.agent_type;
|
|
if ( isdefined( attacker.alien_type ) )
|
|
attacker_agent_type = attacker.alien_type;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
attacker_alive_time = 0;
|
|
|
|
if ( isplayer( attacker ) )
|
|
attacker_agent_type = "player";
|
|
else
|
|
attacker_agent_type = "nonagent";
|
|
}
|
|
|
|
// attacker origin
|
|
attackerx = 0.0;
|
|
attackery = 0.0;
|
|
attackerz = 0.0;
|
|
if ( isdefined( attacker ) && IsAgent( attacker ) )
|
|
{
|
|
attackerx = attacker.origin[ 0 ];
|
|
attackery = attacker.origin[ 1 ];
|
|
attackerz = attacker.origin[ 2 ];
|
|
}
|
|
|
|
victimname = "";
|
|
if ( isdefined( self.name ) )
|
|
victimname = self.name;
|
|
|
|
cyclenum = -1;
|
|
if ( isdefined( level.current_cycle_num ) )
|
|
cyclenum = level.current_cycle_num;
|
|
|
|
hivename = "unknown";
|
|
if ( isdefined( level.current_hive_name ) )
|
|
hivename = level.current_hive_name;
|
|
|
|
/#
|
|
if ( GetDvarInt( "alien_bbprint_debug" ) > 0 )
|
|
{
|
|
attackerorigin = ( attackerx, attackery, attackerz );
|
|
|
|
IPrintLnBold( "^8bbprint: alienplayerlaststand \n" +
|
|
" cyclenum=" + cyclenum +
|
|
" hivename=" + hivename +
|
|
" attackerisagent=" + attacker_is_agent +
|
|
" attackeragenttype=" + attacker_agent_type +
|
|
" attackeralivetime=" + attacker_alive_time +
|
|
" attackerx,y,z=" + attackerorigin +
|
|
" victimx,y,z=" + self.origin +
|
|
" victimname=" + victimname +
|
|
" damage=" + iDamage );
|
|
}
|
|
#/
|
|
|
|
bbprint( "alienplayerlaststand",
|
|
"cyclenum %i hivename %s attackerisagent %i attackeragenttype %s attackeralivetime %f attackerx %f attackery %f attackerz %f victimx %f victimy %f victimz %f victimname %s damage %i",
|
|
cyclenum,
|
|
hivename,
|
|
attacker_is_agent,
|
|
attacker_agent_type,
|
|
attacker_alive_time,
|
|
attackerx,
|
|
attackery,
|
|
attackerz,
|
|
self.origin[0],
|
|
self.origin[1],
|
|
self.origin[2],
|
|
victimname,
|
|
iDamage );
|
|
|
|
// =========================== [END] blackbox print ===========================
|
|
}
|
|
|
|
waittill_any_ents_or_timeout_return( timeout, ent1, string1, ent2, string2, ent3, string3, ent4, string4, ent5, string5, ent6, string6, ent7, string7 )
|
|
{
|
|
assert( isDefined( timeout ) );
|
|
assert( isdefined( ent1 ) );
|
|
assert( isdefined( string1 ) );
|
|
|
|
self endon( "death" );
|
|
|
|
ent = SpawnStruct();
|
|
|
|
ent1 childthread waittill_string( string1, ent );
|
|
|
|
if ( ( isdefined( ent2 ) ) && ( isdefined( string2 ) ) )
|
|
ent2 childthread waittill_string( string2, ent );
|
|
|
|
if ( ( isdefined( ent3 ) ) && ( isdefined( string3 ) ) )
|
|
ent3 childthread waittill_string( string3, ent );
|
|
|
|
if ( ( isdefined( ent4 ) ) && ( isdefined( string4 ) ) )
|
|
ent4 childthread waittill_string( string4, ent );
|
|
|
|
if ( ( isdefined( ent5 ) ) && ( isdefined( string5 ) ) )
|
|
ent5 childthread waittill_string( string5, ent );
|
|
|
|
if ( ( isdefined( ent6 ) ) && ( isdefined( string6 ) ) )
|
|
ent6 childthread waittill_string( string6, ent );
|
|
|
|
if ( ( isdefined( ent7 ) ) && ( isdefined( string7 ) ) )
|
|
ent7 childthread waittill_string( string7, ent );
|
|
|
|
ent childthread _timeout( timeOut );
|
|
|
|
ent waittill( "returned", msg );
|
|
ent notify( "die" );
|
|
return msg;
|
|
}
|
|
|
|
waittill_any_ents_return( ent1, string1, ent2, string2, ent3, string3, ent4, string4, ent5, string5, ent6, string6, ent7, string7 )
|
|
{
|
|
assert( isdefined( ent1 ) );
|
|
assert( isdefined( string1 ) );
|
|
|
|
self endon( "death" );
|
|
|
|
ent = SpawnStruct();
|
|
|
|
ent1 childthread waittill_string( string1, ent );
|
|
|
|
if ( ( isdefined( ent2 ) ) && ( isdefined( string2 ) ) )
|
|
ent2 childthread waittill_string( string2, ent );
|
|
|
|
if ( ( isdefined( ent3 ) ) && ( isdefined( string3 ) ) )
|
|
ent3 childthread waittill_string( string3, ent );
|
|
|
|
if ( ( isdefined( ent4 ) ) && ( isdefined( string4 ) ) )
|
|
ent4 childthread waittill_string( string4, ent );
|
|
|
|
if ( ( isdefined( ent5 ) ) && ( isdefined( string5 ) ) )
|
|
ent5 childthread waittill_string( string5, ent );
|
|
|
|
if ( ( isdefined( ent6 ) ) && ( isdefined( string6 ) ) )
|
|
ent6 childthread waittill_string( string6, ent );
|
|
|
|
if ( ( isdefined( ent7 ) ) && ( isdefined( string7 ) ) )
|
|
ent7 childthread waittill_string( string7, ent );
|
|
|
|
ent waittill( "returned", msg );
|
|
ent notify( "die" );
|
|
return msg;
|
|
}
|
|
|
|
is_killed_by_kill_trigger( bleedOutSpawnEntity )
|
|
{
|
|
return isDefined( bleedOutSpawnEntity );
|
|
}
|
|
|
|
set_last_stand_count( player, num )
|
|
{
|
|
num = int( num );
|
|
player setcoopplayerdata( "alienSession", "last_stand_count", num );
|
|
player SetClientOmnvar( "ui_alien_selfrevive", num );
|
|
}
|
|
|
|
get_last_stand_count() { return self getcoopplayerdata( "alienSession", "last_stand_count" ); }
|
|
is_being_revived( player ) { return player.being_revived; }
|
|
player_in_laststand( player ) { return player.inLastStand; }
|
|
instant_revive( player ) { player notify( "revive_success" ); }
|
|
|
|
/#
|
|
debug_self_revive()
|
|
{
|
|
register_laststand_ammo();
|
|
wait( 3 );
|
|
return true;
|
|
}
|
|
#/ |