#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" ); // 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" ); // 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 ); // 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; } #/