diff options
Diffstat (limited to 'Northstar.Coop/scripts/vscripts/sp/sp_training.nut')
-rw-r--r-- | Northstar.Coop/scripts/vscripts/sp/sp_training.nut | 7554 |
1 files changed, 0 insertions, 7554 deletions
diff --git a/Northstar.Coop/scripts/vscripts/sp/sp_training.nut b/Northstar.Coop/scripts/vscripts/sp/sp_training.nut deleted file mode 100644 index 21a67a40..00000000 --- a/Northstar.Coop/scripts/vscripts/sp/sp_training.nut +++ /dev/null @@ -1,7554 +0,0 @@ -global function CodeCallback_MapInit - -#if DEV -global function skyboxchange -global function GetOGPilot -global function wallruntest -global function Record_ZenGarden_Wallrun -global function Record_ZenGarden_Slide -global function Record_ZenGarden_DoubleJump -global function shutdownscreentest -global function SendTrainingGauntletStats -global function FancyTeleport_EffectsAndSound -global function Training_WeaponRacks_SetSolidity -global function setfakeinstalldone - -global function Training_EnvArtColorCorrection_SetEnabled -global function SimpleScreenShake -global function GetSkitGuyInfo_ByName -global function NudgeSkitGuy -#endif - -const MARVIN_MODEL = $"models/robots/marvin/marvin.mdl" -const asset FX_POD_LASER = $"P_pod_scan_laser_FP" -const asset FX_POD_GLOWLIGHT = $"P_pod_door_glow_FP" -const asset FX_POD_SCREEN_IN = $"P_pod_screen_lasers_IN" -const asset FX_POD_SCREEN_OUT = $"P_pod_screen_lasers_OUT" -const asset FX_POD_DLIGHT_CONSOLE1 = $"P_pod_Dlight_console1" -const asset FX_POD_DLIGHT_CONSOLE2 = $"P_pod_Dlight_console2" -//const asset FX_POD_DLIGHT_BACKLIGHT_SIDE = $"P_pod_Dlight_backlight_side" -//const asset FX_POD_DLIGHT_BACKLIGHT_TOP = $"P_pod_Dlight_backlight_top" -const asset FX_FANCY_TELEPORT_ENV_PULSE = $"P_ar_holopulse_CP" -const asset FX_COCKPIT_LIGHT = $"xo_cockpit_dlight" -const asset OG_PILOT_HELMET_MODEL = $"models/Humans/heroes/mlt_hero_anderson_helmet.mdl" -const asset ANDERSON_PILOT_MODEL = $"models/humans/heroes/mlt_hero_anderson.mdl" -const asset PILOT_MODEL_BAY1 = $"models/humans/pilots/sp_medium_geist_f.mdl" -const asset PILOT_MODEL_BAY2 = $"models/humans/pilots/sp_medium_reaper_m.mdl" -const asset BUDDY_MODEL_POSED_NO_ANIMS = $"models/Titans/buddy/BT_posed.mdl" -const asset SAFETY_BATON_MODEL = $"models/industrial/safety_baton.mdl" - -const asset OG_PILOT_MODEL = $"models/humans/heroes/mlt_hero_lastimosa.mdl" -const int OG_PILOT_MODEL_HEAD_IDX_BARE = 0 -const int OG_PILOT_MODEL_HEAD_IDX_HELMET = 2 -const int OG_PILOT_MODEL_DECAL_IDX = 0 -const int OG_PILOT_MODEL_DECAL_IDX_BARE = 1 - -const string OG_WEAPON = "mp_weapon_rspn101" - -const string ANIM_OG_STANDING_IDLE = "OG_stand_upright_idle" -const string ANIM_OG_STANDING_TALK = "OG_stand_upright_talk" -const string ANIM_OG_SITTING_IDLE = "OG_sit_high_idle" -const string ANIM_OG_SITTING_TALK = "OG_sit_high_talk" -const string ANIM_OG_LEANING_IDLE = "OG_stand_lean_idle" -const string ANIM_OG_LEANING_TALK = "OG_stand_lean_talk" - -const int SCRIPTED_PATH_WALK = 0 -const int SCRIPTED_PATH_RUN = 1 - -const int MAX_RECREATED_OLD_WEAPONS = 16 - -const float TITANFALL_NAG_DURATION = 3.0 // extra time compensation for nag line playing when titanfall started - -const string TRAINING_PLAYER_SETTINGS = "pilot_solo_training" - -struct TrainingPod_dLightMapping -{ - string scriptAlias - asset fxName - string attachName - entity fxHandle -} - -struct TrainingPod_LaserEmitter -{ - entity ent - string attachName - vector ogAng - bool sweepDone = false - entity fxHandle -} - -struct TrainingPod_GlowLightRow -{ - array<string> fxSpotsL - array<string> fxSpotsR -} - -struct LoudspeakerVO_Info -{ - string scriptAlias - string soundAlias - float duration -} - -struct FiringRangeTarget -{ - entity ent - entity angleRefEnt - entity mover - bool wasDamaged - vector ogAngles -} - -struct SkitGuyInfo -{ - int id - string name - string skitAnim - entity guy - entity skitRef -} - -struct HangarTitanGroup -{ - entity ref - - entity titan - entity rack - entity marvin - entity pilot - - int titanSkin = -1 - - string titanAnim - string rackAnim - string marvinAnim - string pilotAnim - - asset pilotModel - - vector rack_ogPos - vector rack_ogAng - - float sequenceDuration - float animInitialTime = 0.0 - - bool isInited = false -} - -struct TrainingGauntletStats -{ - bool didBeatRequiredTime = false - int numRunsBeforeBeatRequiredTime = 0 - int numChallengeRuns = 0 - int numRestarts = 0 - float bestTime = -1.0 - int recommendedDifficulty = 0 -} - -struct -{ - #if DEV - bool fakeInstallDone = false - #endif - - bool gauntletMode = false - - entity player - int playerInputType - - entity ogPilot - entity ogTwin - entity anderson - entity titanTwin - entity ogHelmet - entity playerAnimWeapon - - entity ogPathMover - - entity animref_hangar - entity animref_leaveGauntlet - - entity trainingPod - array<TrainingPod_GlowLightRow> trainingPodGlowLightRows - array<entity> trainingPodGlowLightFXHandles - array<TrainingPod_dLightMapping> trainingPodDLightMappings - array<TrainingPod_LaserEmitter> trainingPodLaserEmitters - - float postWallrunVOEndTime = -1 - - float titanfallNagStartTime = -1 - vector playerTitanCallInPos - - entity envArt_colorCorrectionEnt - entity skycam_default - entity skycam_glitch - - table<string,LoudspeakerVO_Info> loudspeakerVO = {} - entity loudspeaker - - array<FiringRangeTarget> firingRangeTargets = [] - - //table<string,SkitGuyInfo> skitguys = {} - array<SkitGuyInfo> skitguys = [] - - TrainingGauntletStats trainingGauntletStats - - array<entity> scriptCreatedWeaponPickups = [] - bool weaponPickupsHaveAmmo = false - - bool displayWeaponHUD = true -} file - -void function CodeCallback_MapInit() -{ - FlagSet( "FlightPath_TitanDrop" ) - - PrecacheParticleSystem( FX_POD_LASER ) - PrecacheParticleSystem( FX_POD_GLOWLIGHT ) - PrecacheParticleSystem( FX_POD_SCREEN_IN ) - PrecacheParticleSystem( FX_POD_SCREEN_OUT ) - PrecacheParticleSystem( FX_POD_DLIGHT_CONSOLE1 ) - PrecacheParticleSystem( FX_POD_DLIGHT_CONSOLE2 ) - //PrecacheParticleSystem( FX_POD_DLIGHT_BACKLIGHT_SIDE ) - //PrecacheParticleSystem( FX_POD_DLIGHT_BACKLIGHT_TOP ) - PrecacheParticleSystem( FX_FANCY_TELEPORT_ENV_PULSE ) - PrecacheParticleSystem( FX_COCKPIT_LIGHT ) - - PrecacheModel( OG_PILOT_HELMET_MODEL ) - PrecacheModel( OG_PILOT_MODEL ) - PrecacheModel( ANDERSON_PILOT_MODEL ) - PrecacheModel( PILOT_MODEL_BAY1 ) - PrecacheModel( PILOT_MODEL_BAY2 ) - PrecacheModel( BUDDY_MODEL_POSED_NO_ANIMS ) - PrecacheModel( SAFETY_BATON_MODEL ) - PrecacheModel( MARVIN_MODEL ) - PrecacheModel( DATA_KNIFE_MODEL ) - - LoudspeakerVO_Setup() - Training_SharedInit() - - RegisterSignal( "ButtonPressedJump" ) - RegisterSignal( "ButtonPressedAttack" ) - RegisterSignal( "PodIntro_OG_StartPodAnim" ) - RegisterSignal( "PodInteriorSequenceDone" ) - RegisterSignal( "FancyTeleportStart" ) - RegisterSignal( "TargetRotate" ) - RegisterSignal( "TargetDamaged" ) - RegisterSignal( "Target_WaitForDamage_Start" ) - RegisterSignal( "StopRepeatingGhostRecorder" ) - RegisterSignal( "FiringRange_StopResettingTargets" ) - RegisterSignal( "Gauntlet_StopTeleportingPlayerAtFinishLine" ) - RegisterSignal( "FirstRun_OG_Creates_Ghost" ) - RegisterSignal( "GauntletChallenge_FirstGhostAppear" ) - RegisterSignal( "PlayerMadeSelection" ) - RegisterSignal( "TrainingPod_BeginInteriorShutdown" ) - RegisterSignal( "NPC_NewCommand" ) - RegisterSignal( "LoudspeakerVO_Stop" ) - RegisterSignal( "glitch_start" ) - - FlagInit( "PlayerPressedUse" ) - FlagInit( "PlayerReloaded" ) - FlagInit( "PodIntro_PodDoorsClosed" ) - FlagInit( "PlayerLookedAtTopTarget" ) - FlagInit( "PlayerLookedAtBottomTarget" ) - FlagInit( "PodIntro_InteriorBootSequence_Starting" ) - FlagInit( "OG_WhyWeFight_VO_Done" ) - FlagInit( "FiringRange_Approach_OG_Sequence_Done" ) - FlagInit( "ReloadTraining_PlayerPressedReload" ) - FlagInit( "PlayerSprinted" ) - FlagInit( "PlayerADSed" ) - FlagInit( "FiringRangeWeaponSwapped" ) - FlagInit( "FiringRange_AllTargetsKilled" ) - FlagInit( "OG_MovedTo_GauntletEntrance" ) - FlagInit( "Gauntlet_FirstRun_All_VO_Finished" ) - FlagInit( "Gauntlet_FirstRun_Done" ) - FlagInit( "ChallengeIntro_VO_Done" ) - FlagInit( "Gauntlet_PlayingFeedbackVO" ) - FlagInit( "PlayerUsedConversationInterface" ) - FlagInit( "GauntletExitConvo_FinishedResponse" ) - FlagInit( "TitanfallIntroConvo_FinishedResponse" ) - FlagInit( "PlayerConfirmedGauntletExit" ) - FlagInit( "PlayerLeavingGauntlet" ) - FlagInit( "PlayerStartedTitanfall" ) - FlagInit( "Titanfall_OG_FallingIn_VO_Start" ) - FlagInit( "TitanfallGlitchStart" ) - FlagInit( "PlayerWorldChangeThread" ) - FlagInit( "Glitch_WorldChanging_Zen" ) - FlagInit( "Glitch_WorldChanging_NonZen" ) - FlagInit( "PodOutroStarted" ) - FlagInit( "SimPodShutdown_LoudspeakerVO_Done" ) - FlagInit( "MeetOG_StartScene" ) - FlagInit( "CadillacMoment_MeetOG_Done" ) - FlagInit( "CadillacMoment_MeetOG_StartFadeOut" ) - FlagInit( "MeetOG_VO_Done" ) - - FlagClear( "AutomaticCheckpointsEnabled" ) - - AddClientCommandCallback( "Training_SetInputType", ClientCommand_Training_SetInputType ) - AddClientCommandCallback( "Training_PlayerPressedUse", ClientCommand_Training_PlayerPressedUse ) - AddClientCommandCallback( "Training_PlayerReloaded", ClientCommand_Training_PlayerReloaded ) - AddClientCommandCallback( "topTarget", ClientCommand_LookTarget_Top ) - AddClientCommandCallback( "bottomTarget", ClientCommand_LookTarget_Bottom ) - - AddCallback_EntitiesDidLoad( EntitiesDidLoad ) - AddPlayerDidLoad( Training_PlayerDidLoad ) - AddCallback_OnLoadSaveGame( Training_OnLoadSaveGame ) - - AddDamageCallback( "func_brush", Training_FuncBrush_OnDamaged ) - - TimerInit( "firingRangeNag", 15.0 ) - TimerInit( "installWaitComment", 60.0 ) - - AddStartPoint( "Pod Intro", Training_PodIntro, null, Training_Skipped_PodIntro ) - AddStartPoint( "Basic Movement", Training_BasicMovement, Training_Setup_BasicMovement, Training_Skipped_BasicMovement ) - AddStartPoint( "Zen Garden", Training_ZenGarden, Training_Setup_ZenGarden, Training_Skipped_ZenGarden ) - AddStartPoint( "Firing Range", Training_FiringRange, Training_Setup_FiringRange, Training_Skipped_FiringRange ) - AddStartPoint( "Gauntlet", Training_Gauntlet, Training_Setup_Gauntlet, Training_Skipped_Gauntlet ) - AddStartPoint( "Gauntlet Challenge", Training_GauntletChallenge, Training_Setup_GauntletChallenge, Training_Skipped_GauntletChallenge ) - AddStartPoint( "Titanfall", Training_Titanfall, Training_Setup_Titanfall, Training_Skipped_Titanfall ) - AddStartPoint( "Pod Outro", Training_PodOutro, Training_Setup_PodOutro, Training_Skipped_PodOutro ) - AddStartPoint( "Meet OG", Training_MeetOG, Training_Setup_MeetOG, Training_Skipped_MeetOG ) - AddStartPoint( "Gauntlet Mode", Training_GauntletModeStart, Training_Setup_GauntletMode, null ) - - #if DEV - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_FIRSTRUN", TrainingGauntlet_RecordGhostStart_FirstRun, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_WIP", TrainingGauntlet_RecordGhostStart_Challenge_WIP, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_01", TrainingGauntlet_RecordGhostStart_Challenge_01, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_02", TrainingGauntlet_RecordGhostStart_Challenge_02, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_03", TrainingGauntlet_RecordGhostStart_Challenge_03, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_04", TrainingGauntlet_RecordGhostStart_Challenge_04, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_05", TrainingGauntlet_RecordGhostStart_Challenge_05, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_06", TrainingGauntlet_RecordGhostStart_Challenge_06, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_07", TrainingGauntlet_RecordGhostStart_Challenge_07, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_08", TrainingGauntlet_RecordGhostStart_Challenge_08, null, null ) - AddStartPoint( "DEV_GHOSTREC_GAUNTLET_CHAL_09", TrainingGauntlet_RecordGhostStart_Challenge_09, null, null ) - - AddStartPoint( "Pod Intro DEV", DEV_PodIntro, null, null ) - AddStartPoint( "Pod Outro DEV", DEV_PodOutro, null, null ) - #endif -} - - -void function EntitiesDidLoad() -{ - QuickDeathTrigger_SetIsPunitive( false ) - - SetupTrainingPod() - TrainingPod_GlowLightsArraySetup() - - FiringRangeTargets_Init() - - file.animref_hangar = GetEntByScriptName( "animref_hangar" ) - file.animref_hangar.DisableHibernation() - - file.skycam_default = GetEnt( "skybox_cam_level" ) - file.skycam_glitch = GetEnt( "skybox_cam_glitch" ) -} - - -void function Training_PlayerDidLoad( entity player ) -{ - player.SetNoTarget( true ) - SetGlobalForcedDialogueOnly( true ) - - AddButtonPressedPlayerInputCallback( player, IN_JUMP, Training_ButtonPressedJump ) - AddButtonPressedPlayerInputCallback( player, IN_ATTACK, Training_ButtonPressedAttack ) - - file.envArt_colorCorrectionEnt = GetEnt( "color_correction_1" ) - - file.player = player - - EnableDemigod( player ) - - player.ForceMPAimassist() // TODO doublecheck this - - player.SetSkyCamera( file.skycam_default ) - - Training_WeaponPickups_Init( player ) - player.PreventWeaponDestroyNoAmmo() // makes it so when player swaps empty weapon for another pickup, doesn't destroy empty weapon - - thread Training_PlayerQuickdeathSFX( player ) - - DisableFriendlyHighlight() -} - - -void function Training_OnLoadSaveGame( entity player ) -{ - thread Training_OnLoadSaveGame_Think( player ) -} - -void function Training_OnLoadSaveGame_Think( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - wait 0.5 // HACK have to wait otherwise it doesn't work - SetWeaponHUDEnabled( player, file.displayWeaponHUD ) -} - - -void function Training_ButtonPressedJump( entity player ) -{ - player.Signal( "ButtonPressedJump" ) -} - -void function Training_ButtonPressedAttack( entity player ) -{ - player.Signal( "ButtonPressedAttack" ) -} - -void function Training_FuncBrush_OnDamaged( entity ent, var damageInfo ) -{ - if( !IsValid( ent ) ) - return - - entity attacker = DamageInfo_GetAttacker( damageInfo ) - - if ( ent.GetScriptName() == "firingrange_target" ) - { - if ( IsValid( attacker ) && attacker.IsPlayer() ) - { - table<string,vector> resultTable = {} - resultTable["damagePos"] <- DamageInfo_GetDamagePosition( damageInfo ) - ent.Signal( "TargetDamaged", resultTable ) - } - } -} - - -// ============================== -// ========= POD INTRO ========== -// ============================== -void function Training_Skipped_PodIntro( entity player ) -{ - player.SetExtraWeaponMods( [ "low_ammo_disable" ] ) - SetWeaponHUDEnabled( player, false ) -} - -#if DEV -// bare bones start in pod -void function DEV_PodIntro( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - TakeAllWeapons( player ) - - player.SetExtraWeaponMods( [ "low_ammo_disable" ] ) - SetWeaponHUDEnabled( player, false ) - - Training_EnvArtColorCorrection_SetEnabled( false ) - SetDoF_Hangar( player ) - - thread PodIntro_BackgroundSkits( player ) - - entity pod = file.trainingPod - - TrainingPod_PlayerSequence_DoorsOpenIdle( player, false ) - - // anim starts at a slightly different spot - player.SetOrigin( < 10564, -10235, -6056.9 > ) - player.SetAngles( < -6, 90, 0 > ) - - WaitForever() -} -#endif //DEV - - -void function Training_PodIntro( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - player.SetExtraWeaponMods( [ "low_ammo_disable" ] ) - SetWeaponHUDEnabled( player, false ) - - Training_EnvArtColorCorrection_SetEnabled( false ) - - entity pod = file.trainingPod - - OnThreadEnd( - function() : ( player, pod ) - { - if ( IsValid( player ) ) - { - player.Anim_Stop() - ClearPlayerAnimViewEntity( player ) - player.ClearParent() - player.UnforceStand() - - Training_EnvArtColorCorrection_SetEnabled( true ) - } - - if ( IsValid ( pod ) ) - { - pod.Anim_Stop() - - thread TrainingPod_ResetLaserEmitterRotation( pod ) - thread TrainingPod_KillLasers( pod ) - thread TrainingPod_KillGlowFX( pod ) - TrainingPod_KillInteriorDLights() - } - } - ) - - // NORMAL LEVEL START - SetDoF_Hangar( player ) - - ShowIntroScreen( player ) - - thread PodIntro_MeetOG( player ) - - TrainingPod_PlayerSequence_DoorsOpenIdle( player ) - - FlagWait( "IntroScreenFading" ) - wait 1.2 - Remote_CallFunction_Replay( player, "ScriptCallback_LevelIntroText" ) - wait 4.2 // matches fade time in sp_introscreen data - - thread PodIntro_BackgroundSkits( player ) - - - player.Signal( "PodIntro_OG_StartPodAnim" ) - - // time for OG to animate before starting viewmodel anim - wait 11.8 - - FirstPersonSequenceStruct playerSequence - playerSequence.blendTime = 0.25 - playerSequence.attachment = "REF" - playerSequence.firstPersonAnim = "ptpov_trainingpod_doors_close" - playerSequence.firstPersonAnimIdle = "ptpov_trainingpod_idle" - playerSequence.thirdPersonAnim = "pt_trainingpod_doors_close" - playerSequence.thirdPersonAnimIdle = "pt_trainingpod_idle" - playerSequence.viewConeFunction = TrainingPod_ViewConeLock_SemiStrict - playerSequence.renderWithViewModels = true - - FirstPersonSequenceStruct podSequence - podSequence.blendTime = 0.25 - podSequence.thirdPersonAnim = "trainingpod_doors_close" - podSequence.thirdPersonAnimIdle = "trainingpod_doors_close_idle" - podSequence.renderWithViewModels = true - - entity viewmodel = player.GetFirstPersonProxy() - - if ( !HasAnimEvent( viewmodel, "PlaySound_SimPod_DoorShut" ) ) - AddAnimEvent( viewmodel, "PlaySound_SimPod_DoorShut", PlaySound_SimPod_DoorShut ) - - // HACK this should be based on an anim event - thread TrainingPod_KillInteriorDLights_Delayed( player, 2.65 ) - - thread FirstPersonSequence( podSequence, pod ) - waitthread FirstPersonSequence( playerSequence, player, pod ) - - FlagSet( "PodIntro_PodDoorsClosed" ) - - TrainingPod_ViewConeLock_PodClosed( player ) - - waitthread LookTraining( player ) - - // "Let's see how much you remember from last time." - waitthread PlayDialogue( "og_how_much_you_remember", player ) - - // "Setting the neural link." - waitthread PlayDialogue( "og_neural_link", player ) - - // "Not quite the same as a Titan link, but it's similar." - waitthread PlayDialogue( "og_neural_link_2", player ) - - thread TrainingPod_Interior_BootSequence( player ) - - // "To learn new skills, we need to be in the right state of mind." - thread PlayDialogue( "og_simulation_starting", player, 2.5 ) - - player.WaitSignal( "PodInteriorSequenceDone" ) - printt( "POD SEQUENCE DONE" ) - - wait 2.0 // timed to match the screen effect white screen flash - - SetDoF_Default( player ) -} - -void function PlaySound_SimPod_DoorShut( entity playerFirstPersonProxy ) //Hack, needed for wargames but has unfortunate side effect for Training. -{ - entity player = playerFirstPersonProxy.GetOwner() - if ( !IsValid( player ) ) - return - - EmitSoundOnEntityOnlyToPlayer( player, player, "NPE_Scr_SimPod_DoorShut" ) - -} - -void function PodIntro_MeetOG( entity player ) -{ - entity animref = file.animref_hangar - vector animrefOrigin = animref.GetOrigin() - vector animrefAngles = animref.GetAngles() - vector btSpawnOrg = <0,0,0> // to avoid red text errors about BT spawning in solid - - entity animEnt = CreateScriptMover( animrefOrigin, animrefAngles ) - - // Spawn scene actors - entity og = Training_SpawnOGPilot( animref ) - Training_OGPilot_SetHelmetOn( og, false ) - AddAnimEvent( file.ogPilot, "pod_slap", PodIntro_OG_Slaps_Pod ) - - TitanLoadoutDef loadout = GetTitanLoadoutForCurrentMap() - entity bt = CreateAutoTitanForPlayer_FromTitanLoadout( player, loadout, btSpawnOrg, animrefAngles ) - SetSpawnOption_AISettings( bt, "npc_titan_buddy" ) - bt.kv.spawnflags = SF_NPC_ALLOW_SPAWN_SOLID - DispatchSpawn( bt ) - FreeAutoTitan( bt ) // HACK this disables the worldspace BT locator icon - TakeAllWeapons( bt ) - - array<entity> actors = [ bt, og ] - - asset btWeaponModel = GetWeaponInfoFileKeyFieldAsset_Global( "mp_titanweapon_xo16_shorty", "playermodel" ) - Assert( btWeaponModel != $"" ) - entity btWeapon = CreatePropDynamic( btWeaponModel ) - btWeapon.SetParent( bt, "PROPGUN" ) - - asset ogWeaponModel = GetWeaponInfoFileKeyFieldAsset_Global( OG_WEAPON, "playermodel" ) - Assert( ogWeaponModel != $"" ) - entity ogWeapon = CreatePropDynamic( ogWeaponModel ) - ogWeapon.SetParent( og, "PROPGUN" ) - - entity ogHelmet = CreatePropDynamic( OG_PILOT_HELMET_MODEL ) - ogHelmet.DisableHibernation() - - array<entity> props = [ btWeapon, ogWeapon, ogHelmet ] - - OnThreadEnd( - function() : ( actors, props, animEnt ) - { - if ( IsValid( file.ogPilot ) ) - DeleteAnimEvent( file.ogPilot, "pod_slap" ) - - foreach ( weapon in props ) - { - if ( IsValid( weapon ) ) - { - weapon.ClearParent() - weapon.Destroy() - } - } - - foreach ( actor in actors ) - { - if ( !IsValid( actor ) ) - continue - - actor.ClearParent() - - if ( IsInvincible( actor ) ) - ClearInvincible( actor ) - - if ( !actor.IsPlayer() ) - actor.Destroy() - } - - if ( IsValid( animEnt ) ) - animEnt.Destroy() - } - ) - - foreach ( guy in actors ) - { - MakeInvincible( guy ) - guy.SetEfficientMode( true ) - Highlight_ClearFriendlyHighlight( guy ) - } - - string anim_og_idle = "pt_OG_training_rail_sit_idle" - string anim_og_helmet_idle = "helmet_intro_scene_OG_idle" - string anim_bt_idle = "BT_intro_scene_OG_idle" - - string anim_og = "pt_pod_setup_OG" - string anim_bt = "BT_pod_setup_OG" - - thread PlayAnimTeleport( og, anim_og_idle, animEnt ) - thread PlayAnimTeleport( ogHelmet, anim_og_helmet_idle, animEnt ) - thread PlayAnimTeleport( bt, anim_bt_idle, animEnt ) - - player.WaitSignal( "PodIntro_OG_StartPodAnim" ) - - if ( !IsValid( og ) ) - return - - og.Anim_Stop() - thread PlayAnim( og, anim_og, animEnt ) - - bt.Anim_Stop() - thread PlayAnim( bt, anim_bt, animEnt ) - - float animDuration = og.GetSequenceDuration( anim_og ) - wait animDuration - 0.1 - - if ( !IsValid( og ) ) - return - - og.Anim_Stop() - thread PlayAnimTeleport( og, anim_og_idle, animEnt ) - - bt.Anim_Stop() - thread PlayAnimTeleport( bt, anim_bt_idle, animEnt ) - - // wait for look training to get started before killing the scene - FlagWaitAny( "PlayerLookedAtTopTarget", "PlayerLookedAtBottomTarget" ) -} - -void function PodIntro_OG_Slaps_Pod( entity ogPilot ) -{ - array<entity> players = GetPlayerArray() - if ( !players.len() ) - return - - entity player = players[0] - if ( !IsValid( player ) ) - return - - float shakeDuration = 0.45 - float shakeAmplitude = 0.14 - float screenBlurFrac = 0 - SimpleScreenShake( player, shakeDuration, shakeAmplitude, screenBlurFrac ) -} - -void function LookTraining( entity player ) -{ - thread LookTraining_StartNag( player, "PlayerLookedAtTopTarget", "PlayerLookedAtBottomTarget" ) - - Remote_CallFunction_Replay( player, "ScriptCallback_ShowInvertCrosshair", true ) - - // LOOKAT SECTION - Remote_CallFunction_Replay( player, "ScriptCallback_SetupLookTargets" ) - wait 0.5 - Remote_CallFunction_Replay( player, "ScriptCallback_LookTargets_WaitForLookat" ) - - DialogueGroup invertConfirmVO = GetDialogueGroup( "ogInvertConfirm" ) - - int numInverts = 0 - int maxInverts = 2 - //while ( numInverts < maxInverts ) - while ( 1 ) - { - Remote_CallFunction_Replay( player, "ScriptCallback_SetupLookTargets" ) - wait 0.5 - Remote_CallFunction_Replay( player, "ScriptCallback_LookTargets_WaitForLookat" ) - - string hintAlias = "invert_look_at_lights" - if ( numInverts > 0 ) - hintAlias = "invert_look_at_lights_again" - - // only play this VO once - if ( numInverts == 1 ) - { - // "You sure?" - thread PlayDialogue( "og_invert_confirm_3", player ) - } - - DisplayOnscreenHint( player, hintAlias ) - - printt( "Waiting for player to look at either target" ) - - FlagWaitAny( "PlayerLookedAtTopTarget", "PlayerLookedAtBottomTarget" ) - - printt( "Player looked at one of the targets" ) - - hintAlias = "invert_look_at_lights_1_left" - if ( numInverts > 0 ) - hintAlias = "invert_look_at_lights_again_1_left" - - DisplayOnscreenHint( player, hintAlias ) - - FlagWait( "PlayerLookedAtTopTarget" ) - FlagWait( "PlayerLookedAtBottomTarget" ) - - printt( "Player looked at both targets" ) - - hintAlias = "invert_look_at_lights_0_left" - if ( numInverts > 0 ) - hintAlias = "invert_look_at_lights_again_0_left" - - DisplayOnscreenHint( player, hintAlias ) - - printt( "invert waiting for OG dialogue" ) - - // "Does that feel right to you?" - // "How about now? Feel alright?" - string askAlias = DialogueGroup_GetNextLine( invertConfirmVO ) - waitthread PlayDialogue( askAlias, player ) - - printt( "invert OG dialogue done" ) - - ClearOnscreenHint( player ) - - string invertConvar = file.playerInputType == 0 ? INVERT_CONVAR_GAMEPAD : INVERT_CONVAR_MOUSE - printt( "invertConvar:", invertConvar ) - bool invertSettingBeforeMenu = GetConVarBool( invertConvar ) - - printt( "Opening invert look dialog" ) - - // THIS PAUSES THE GAME UNTIL MENU IS CLOSED - Remote_CallFunction_UI( player, "ScriptCallback_OpenInvertLookDialog" ) - wait 0.5 // let the game come back after menu is closed - - // if player didn't change setting, don't repeat - invertConvar = file.playerInputType == 0 ? INVERT_CONVAR_GAMEPAD : INVERT_CONVAR_MOUSE - printt( "invertConvar:", invertConvar ) - if ( GetConVarBool( invertConvar ) == invertSettingBeforeMenu ) - { - printt( "player didn't change setting, not repeating" ) - break - } - - printt( "invert- player changed setting, repeating to confirm" ) - - numInverts++ - - // kill lights and reset flags - Remote_CallFunction_Replay( player, "ScriptCallback_LookTargets_KillLights" ) - - FlagClear( "PlayerLookedAtTopTarget" ) - FlagClear( "PlayerLookedAtBottomTarget" ) - } - - ClearOnscreenHint( player ) - Remote_CallFunction_Replay( player, "ScriptCallback_ShowInvertCrosshair", false ) - - // "Alright, we're good to go." - waitthread PlayDialogue( "og_invert_complete", player ) - - TrainingPod_ViewConeLock_PodClosed( player ) - - TrainingPod_ViewConeLock_SemiStrict( player ) // recenter player view - Remote_CallFunction_Replay( player, "ScriptCallback_LookTargets_KillLights" ) -} - -void function LookTraining_StartNag( entity player, string flag1, string flag2 ) -{ - EndSignal( player, "OnDestroy" ) - - if ( Flag( flag1 ) || Flag( flag2 ) ) - return - - FlagEnd( flag1 ) - FlagEnd( flag2 ) - - float nagInterval = 15.0 - float nextNagTime = Time() + nagInterval - - while( 1 ) - { - wait 1 - - if ( Time() < nextNagTime ) - continue - - // "We have to calibrate the pod. It won't boot up until you look at both of those lights." - waitthread PlayDialogue( "og_pod_calibrate", player ) - - nextNagTime = Time() + nagInterval - } -} - -void function TrainingPod_PlayerSequence_DoorsOpenIdle( entity player, bool doPlayerAnim = true ) -{ - entity pod = file.trainingPod - - // Have to do this first so the anim starts centered on the ref attachment angles - string podAttach = "REF" - int attachID = pod.LookupAttachment( podAttach ) - vector podRefOrg = pod.GetAttachmentOrigin( attachID ) - vector podRefAng = pod.GetAttachmentAngles( attachID ) - player.SetOrigin( podRefOrg ) - player.SetAngles( podRefAng ) - player.ForceStand() - - player.DisableWeapon() - - // default start anim starts open - void functionref( entity ) viewConeFunction_start = TrainingPod_ViewConeLock_PodOpen - string podAnim_start = "trainingpod_doors_open_idle" - - // start open idle - FirstPersonSequenceStruct playerSequence - playerSequence.blendTime = 0.0 - playerSequence.attachment = podAttach - playerSequence.firstPersonAnimIdle = "ptpov_trainingpod_idle" - playerSequence.thirdPersonAnimIdle = "pt_trainingpod_idle" - playerSequence.viewConeFunction = viewConeFunction_start - playerSequence.renderWithViewModels = true - - FirstPersonSequenceStruct podSequence - podSequence.blendTime = 0.0 - podSequence.thirdPersonAnimIdle = podAnim_start - podSequence.renderWithViewModels = true - - thread FirstPersonSequence( podSequence, pod ) - - if ( doPlayerAnim ) - thread FirstPersonSequence( playerSequence, player, pod ) - - TrainingPod_TurnOnInteriorDLight( "console1" ) - TrainingPod_TurnOnInteriorDLight( "console2" ) - //TrainingPod_TurnOnInteriorDLight( "backlight_side_L" ) - //TrainingPod_TurnOnInteriorDLight( "backlight_side_R" ) -} - - - -// ------ POD INTRO BACKGROUND SKITS ------ -void function PodIntro_BackgroundSkits( entity player ) -{ - string endFlag = "PodIntro_PodDoorsClosed" - FlagEnd( endFlag ) - - thread PodIntro_LoudspeakerVO( player, "PodIntro_InteriorBootSequence_Starting" ) - - thread PodIntro_TitanRacks( endFlag ) - - thread PodIntro_Background_WalkingGuys() - - // ---- ANIMATING SKIT GUYS --- - // script NudgeSkitGuy( "back_console_supervisor", 0, 5, 0 ) - - // guy sitting at console in back center of room - SkitGuyInfo backConsoleGuy1 = SpawnSkitGuy( "back_console_sitting", "pt_console_idle", < 10521.1, -9679.33, -6044.1 >, < 0, 88.3541, 0 >, TEAM_MILITIA, "npc_soldier" ) - SkitGuy_PlayAnim( backConsoleGuy1 ) - SkitGuyInfo backConsoleGuy2 = SpawnSkitGuy( "back_console_supervisor", "pt_bored_interface_leanback", < 10527.6, -9656.36, -6043.97 >, < 0, -26.564, 0 >, TEAM_MILITIA, "npc_soldier_specialist_militia", "mp_weapon_g2" ) - SkitGuy_PlayAnim( backConsoleGuy2 ) - - // extra marvins working on titans 1 and 2 - SkitGuyInfo titanBay1_marvin = SpawnSkitGuy( "bay1_marvin", "mv_idle_weld", < 10711.2, -9781.04, -6080.65 >, < 0, 153.715, 0 > ) - SkitGuy_PlayAnim( titanBay1_marvin, 3.0 ) // don't play same anim at same time - SkitGuyInfo titanBay2_marvin = SpawnSkitGuy( "bay2_marvin", "mv_idle_weld", < 10316.2, -9730.23, -6079.97 >, < 0, -69.965, 0 > ) - SkitGuy_PlayAnim( titanBay2_marvin ) - - // guys looking at console in back left - SkitGuyInfo leftConsoleGuy1 = SpawnSkitGuy( "console_lean", "pt_bored_interface_leanin", < 10257.6, -9846.63, -6079.97 >, < 0, 34.5175, 0 >, TEAM_MILITIA, "npc_soldier" ) - SkitGuy_PlayAnim( leftConsoleGuy1 ) - SkitGuyInfo leftConsoleGuy2 = SpawnSkitGuy( "console_supervisor", "pt_bored_interface_leanback", < 10260.5, -9874.78, -6079.97 >, < 0, -42.534, 0 >, TEAM_MILITIA, "npc_soldier", "mp_weapon_mastiff" ) - SkitGuy_PlayAnim( leftConsoleGuy2 ) - - OnThreadEnd( - function() : () - { - DeleteAllSkitGuys() - } - ) - - WaitForever() -} - -void function PodIntro_LoudspeakerVO( entity player, string endFlag ) -{ - EndSignal( player, "OnDestroy" ) - - array<string> aliases - // "Inbound to Planet Typhon. Subspace rendezvous in approximately 20 minutes." - aliases.append( "intro_0" ) - // "Reminder to dock personnel: Titan ordnance is a Type 3 Hazardous Material." - aliases.append( "intro_2" ) - // "Running Lifeboat diagnostic test two point one. All Mark Eight lifeboats are in the green." - aliases.append( "intro_4" ) - // "3rd Militia Grenadiers - prep dropship MacAllan 17." - aliases.append( "intro_5" ) - // "Captain Cole to communications." - aliases.append( "intro_3" ) - // "Major Anderson, please report to the briefing room." - aliases.append( "intro_1" ) - - thread LoopLoudspeakerVO( aliases, endFlag, 1.0, 2.0 ) -} - -void function PodIntro_Background_WalkingGuys() -{ - // group of guys walking left to right - array<Point> path1 = [] - ScriptedPath_AddPoint( path1, < 10327.9, -10000.28, -6079.97 >, < 0, 0.918, 0 > ) - ScriptedPath_AddPoint( path1, < 10373.5, -9987.14, -6079.97 >, < 0, 0.093, 0 > ) - ScriptedPath_AddPoint( path1, < 10688.3, -9973.76, -6079.97 >, < 0, 0, 0 > ) - ScriptedPath_AddPoint( path1, < 10856.4, -9973.58, -6079.97 >, < 0, 0, 0 > ) - SkitGuyInfo walkerInfo_1 = SpawnSkitGuy( "walker_1", "", path1[0].origin, path1[0].angles, TEAM_MILITIA, "npc_soldier_specialist_militia", "mp_weapon_hemlok_smg" ) - thread ScriptedPath_Walk( walkerInfo_1, path1, 0.75 ) - - array<Point> path2 = [] - ScriptedPath_AddPoint( path2, < 10248.6, -9925.06, -6079.97 >, < 0, 6.36392, 0 > ) - ScriptedPath_AddPoint( path2, < 10373.5, -9939.14, -6079.97 >, < 0, 0.093, 0 > ) - ScriptedPath_AddPoint( path2, < 10688.3, -9973.76, -6079.97 >, < 0, 0, 0 > ) - ScriptedPath_AddPoint( path2, < 10856.4, -9973.58, -6079.97 >, < 0, 0, 0 > ) - SkitGuyInfo walkerInfo_2 = SpawnSkitGuy( "walker_2", "", path2[0].origin, path2[0].angles, TEAM_MILITIA, "npc_soldier", "mp_weapon_hemlok" ) - thread ScriptedPath_Walk( walkerInfo_2, path2, 0.85 ) -} - -void function PodIntro_TitanRacks( string endFlag ) -{ - FlagEnd( endFlag ) - - array<HangarTitanGroup> titanGroups - - HangarTitanGroup bay1 - bay1.ref = GetEntByScriptName( "animref_drop_hangar_titan_1" ) - bay1.titan = GetEntByScriptName( "hangar_titan_1" ) - bay1.rack = GetEntByScriptName( "hangar_titan_rack_1" ) - bay1.titanAnim = "bt_TDay_drop_titan4" - bay1.rackAnim = "rack_TDay_drop_rack4" - bay1.marvinAnim = "mv_TDay_drop_marvin4" - HangarTitanGroup_Init( bay1 ) - titanGroups.append( bay1 ) - - // --- BAY 2 --- - HangarTitanGroup bay2 - bay2.ref = GetEntByScriptName( "animref_drop_hangar_titan_2" ) - bay2.titan = GetEntByScriptName( "hangar_titan_2" ) - bay2.rack = GetEntByScriptName( "hangar_titan_rack_2" ) - bay2.titanAnim = "bt_TDay_drop_titan3" - bay2.rackAnim = "rack_TDay_drop_rack3" - bay2.marvinAnim = "mv_TDay_drop_marvin3" - HangarTitanGroup_Init( bay2 ) - titanGroups.append( bay2 ) - - float wait_earlyEnd = 27.0 - thread HangarTitanGroup_Animate( bay1, endFlag, wait_earlyEnd ) - thread HangarTitanGroup_Animate( bay2, endFlag, wait_earlyEnd ) - - wait wait_earlyEnd - thread PodIntro_TitanRacks( endFlag ) -} - - - -// =================================== -// ========= BASIC MOVEMENT ========== -// =================================== -void function Training_Setup_BasicMovement( entity player ) -{ - player.DisableWeapon() -} - -void function Training_Skipped_BasicMovement( entity player ) -{ - player.SetPlayerSettingsWithMods( TRAINING_PLAYER_SETTINGS, [ "disable_doublejump", "disable_wallrun" ] ) - - Objective_SetSilent( "#TRAINING_OBJ_DEFAULT" ) -} - -void function Training_BasicMovement( entity player ) -{ - entity standNearJumpRef = GetEntByScriptName( "basic_movement_og_stand_near_jump" ) - standNearJumpRef.SetOrigin( OriginToGround( standNearJumpRef.GetOrigin() + <0,0,0.5> ) ) // HACK HACK the ref node is a tiny bit in the geo which causes OG to dip when blending between anims - entity ogStart = GetEntByScriptName( "basic_movement_og_start" ) - entity og = Training_SpawnOGPilot( ogStart ) - - player.SetPlayerSettingsWithMods( TRAINING_PLAYER_SETTINGS, [ "disable_doublejump", "disable_wallrun" ] ) - player.ForceAutoSprintOff() - - entity playerStart = GetEntByScriptName( "startpoint_basic_movement" ) - waitthread PlayerAndOGTeleport_Fancy( player, playerStart.GetOrigin(), "basic_movement_og_start", playerStart.GetAngles() ) - Training_OG_Idles_Sitting( ogStart, "OG_base_move_A_idle" ) - - thread BasicMovement_DelayedWeaponDeploy( player, 1.5 ) - Objective_SetSilent( "#TRAINING_OBJ_DEFAULT" ) - - // "Ah. Much better." - waitthread Training_OG_ScriptedAnim( ogStart, "OG_base_move_A" ) - thread Training_OG_Idles_Sitting( ogStart, "OG_base_move_B_idle" ) - - CheckPoint_Silent() - - thread OnscreenHint_DisplayUntilFlag( player, "move_hint", "BasicMovement_PlayerMovedForward", 10.0 ) - - FlagWait( "BasicMovement_PlayerMovedForward" ) - - if ( !Flag( "BasicMovement_PlayerJumped" ) ) - { - // "Technically, I'm not supposed to be training you. But in you, I see potential. - waitthread Training_OG_ScriptedAnim( ogStart, "OG_base_move_B1") - } - - if ( !Flag( "BasicMovement_PlayerJumped" ) ) - { - // "Besides, we're at war. Who's got time for classes, eh?" - waitthread Training_OG_ScriptedAnim( ogStart, "OG_base_move_B2") - thread Training_OG_Idles_Sitting( ogStart ) - } - - if ( !Flag( "BasicMovement_PlayerJumped" ) && player.IsOnGround() ) - { - DisplayOnscreenHint( player, "jump_hint" ) - - // "Here you go, up and over." - waitthread Training_OG_ScriptedAnim( ogStart, "OG_base_move_C" ) - waitthread Training_OG_Moves( standNearJumpRef ) - } - - if ( !Flag( "BasicMovement_PlayerJumped" ) ) - { - // "Cmon, schedule's tight today." - // "Here you go, up and over." - array<string> jumpNags = [ "og_jump_nag_2", "og_jump_nag" ] - - thread Training_OG_NagPlayerUntilFlag( player, jumpNags, 20.0, standNearJumpRef, "BasicMovement_PlayerJumped" ) - } - - FlagWait( "BasicMovement_PlayerJumped" ) - - ClearOnscreenHint( player ) - - waitthread BasicMovement_Sprint( player ) -} - -void function BasicMovement_Sprint( entity player ) -{ - thread BasicMovement_Sprint_OG_Moves( player ) - - //player.ForceAutoSprintOn() - - FlagClear( "PlayerSprinted" ) - thread BasicMovement_PlayerSprintDetection( player ) - - // "Let's pick up the pace. Enabling jumpkit assist." - float endVOTime = Time() + 3.5 - thread PlayDialogue( "og_autosprint_on", file.ogPilot ) - - wait 2.5 // let the VO play a bit before showing the hint - - player.UnforceAutoSprint() - thread BasicMovement_SprintHint_Think( player ) - - wait endVOTime - Time() - - // HACK- Create a fake VO speaker where OG will eventually move to/from so the lines emit in worldspace for audio - entity ref = GetEntByScriptName( "basic_movement_og_mid_hallway" ) - entity tempSpeaker = CreateScriptMover( ref.GetOrigin(), <0,0,0> ) - thread HACK_MoveTempSpeaker_WithOGPathMover( player, tempSpeaker ) - - // "Jumpkits operate on the principle of relaxed stability." - EmitSoundOnEntity( tempSpeaker, "diag_sp_addtional_TR411_53_mcor_og" ) // do this instead of PlayDialogue because it will follow the ent around - wait 3.4 // HACK - - // "Once your jumpkit calibrates to your movement style, enhanced mobility becomes second nature." - EmitSoundOnEntity( tempSpeaker, "diag_sp_movement_TR121_08_01_mcor_og" ) - wait 6.0 // HACK - - tempSpeaker.Destroy() -} - -void function HACK_MoveTempSpeaker_WithOGPathMover( entity player, entity tempSpeaker ) -{ - EndSignal( player, "OnDestroy" ) - EndSignal( tempSpeaker, "OnDestroy" ) - - vector prevOrg = < -1,-1,-1 > - - while ( 1 ) - { - WaitFrame() - - vector newOrg = < -1,-1,-1 > - - // if we are doing a path move, use the pathMover origin- otherwise use OG's origin - if ( IsValid( file.ogPathMover ) ) - newOrg = file.ogPathMover.GetOrigin() - else if ( IsValid( file.ogPilot ) ) - file.ogPilot.GetOrigin() - - if ( newOrg != < -1,-1,-1 > && newOrg != prevOrg ) - { - tempSpeaker.SetOrigin( newOrg ) - prevOrg = newOrg - } - } -} - -void function BasicMovement_SprintHint_Think( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - float autosprintHintTime = 10.0 - - // player with autosprint on will already be sprinting - if ( GetAutosprintEnabled() ) - { - thread DisplayOnscreenHint( player, "autosprint_hint", autosprintHintTime ) - return - } - - // Below this point assume that autosprint is NOT enabled - if ( !Flag( "PlayerSprinted" ) ) - { - thread OnscreenHint_DisplayUntilFlag( player, "sprint_button_hint", "PlayerSprinted", 0.0, true ) - FlagWait( "PlayerSprinted" ) - - wait 1.0 - } - - DisplayOnscreenHint( player, "autosprint_available", autosprintHintTime ) -} - -void function BasicMovement_Sprint_OG_Moves( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - entity ogMidHallwayRef = GetEntByScriptName( "basic_movement_og_mid_hallway" ) - waitthread Training_OG_Moves_ToSitting( ogMidHallwayRef, "", 0.8 ) - - FlagWait( "BasicMovement_PlayerReachedMidHallway" ) - - entity og_zenGarden_start = GetEntByScriptName( "basic_movement_og_zen_start" ) - thread Training_OG_Moves( og_zenGarden_start, "OG_Beautiful_idle" ) -} - -void function BasicMovement_PlayerSprintDetection( entity player ) -{ - EndSignal( player, "OnDestroy" ) - FlagEnd( "BasicMovement_PlayerReachedOpenArea" ) - - while ( 1 ) - { - WaitFrame() - - if ( player.IsSprinting() ) - break - } - - FlagSet( "PlayerSprinted" ) -} - -void function BasicMovement_DelayedWeaponDeploy( entity player, float delay ) -{ - player.EndSignal( "OnDestroy" ) - - wait delay - player.EnableWeaponWithSlowDeploy() - thread TakeAmmoFromPlayerASAP( player ) -} - - -// ================================================= -// ========= BASIC MOVEMENT 2: ZEN GARDEN ========== -// ================================================= -void function Training_Setup_ZenGarden( entity player ) -{ - entity ogStart = GetEntByScriptName( "basic_movement_og_zen_start" ) - entity og = Training_SpawnOGPilot( ogStart ) - Training_OG_Idles( ogStart, "OG_Beautiful_idle" ) - - thread TakeAmmoFromPlayerASAP( player ) - - TeleportPlayerAndBT( "startpoint_zen_garden" ) -} - -void function Training_Skipped_ZenGarden( entity player ) -{ - player.SetPlayerSettingsWithMods( TRAINING_PLAYER_SETTINGS, [] ) - - OpenZenGardenExitDoor() -} - -void function Training_ZenGarden( entity player ) -{ - entity og = GetOGPilot() - Assert( IsValid( og ) ) - - entity ref_hillclimbFinish = GetEntByScriptName( "zengarden_hillclimb_finish_idle" ) - entity ref_exitSpot = GetEntByScriptName( "zengarden_og_exit_ref" ) - - OpenZenGardenExitDoor() - - FlagWait( "BasicMovement_PlayerReachedOpenArea" ) - - player.SetPlayerSettingsWithMods( TRAINING_PLAYER_SETTINGS, ["disable_doublejump"] ) - - CheckPoint_Silent() - - thread ZenGarden_WhyWeFight_VO( player, og ) - - waitthread Training_ZenGarden_Wallrun( player ) - - waitthread Training_ZenGarden_Crouch( player ) - - player.SetPlayerSettingsWithMods( TRAINING_PLAYER_SETTINGS, [] ) - - CheckPoint_Silent() - - waitthread Training_ZenGarden_DoubleJump( player ) - - waitthread Training_ZenGarden_HillClimb( player, ref_hillclimbFinish, ref_exitSpot ) - - if ( IsValid( level ) ) - Signal( level, "StopRepeatingGhostRecorder" ) -} - -// ZEN GARDEN SHARED BETWEEN PATHS -void function ZenGarden_WhyWeFight_VO( entity player, entity og ) -{ - entity ogStart = GetEntByScriptName( "basic_movement_og_zen_start" ) - entity firstRockRef = GetEntByScriptName( "zengarden_og_rock1_ref" ) - entity pathRef = GetEntByScriptName( "zengarden_og_path_ref" ) - entity treeRef = GetEntByScriptName( "zengarden_og_tree_ref" ) - - string stopFlag = "ZenGarden_PlayerReachedWallrunStart" - string setFlag = "OG_WhyWeFight_VO_Done" - - if ( !Flag( stopFlag ) ) - { - // "Beautiful, isn't it?" - waitthread Training_OG_ScriptedAnim( ogStart, "OG_Beautiful" ) - } - - if ( !Flag( stopFlag ) ) - { - waitthread Training_OG_Moves( firstRockRef, "", 0.25 ) - } - - if ( !Flag( stopFlag ) ) - { - // "It's inspired by my home planet of Harmony." - waitthread Training_OG_ScriptedAnim( firstRockRef, "OG_harmony_A" ) - } - - if ( !Flag( stopFlag ) ) - { - // "This is where I grew up." - waitthread Training_OG_ScriptedAnim( firstRockRef, "OG_harmony_B" ) - } - - if ( !Flag( stopFlag ) && !Flag( "ZenGarden_PlayerReachedFirstRock" ) ) - { - waitthread Training_OG_Moves( pathRef ) - } - - FlagWaitAny( stopFlag, "ZenGarden_PlayerReachedFirstRock" ) - - if ( !Flag( stopFlag ) ) - { - waitthread Training_OG_Moves_ToSitting( treeRef, "", 0.5 ) - } - - if ( !Flag( stopFlag ) ) - { - // "This is what we're fighting for, Cooper." - waitthread Training_OG_ScriptedAnim( treeRef, "OG_freedom_A" ) - } - - if ( !Flag( stopFlag ) ) - { - // "A world that's not metal and smoke." - waitthread Training_OG_ScriptedAnim( treeRef, "OG_freedom_B" ) - } - - if ( !Flag( stopFlag ) ) - { - // "The freedom to live in peace and prosperity." - waitthread Training_OG_ScriptedAnim( treeRef, "OG_freedom_C" ) - } - - FlagSet( setFlag ) -} - -void function Training_ZenGarden_Wallrun( entity player ) -{ - entity wallrunRef = GetEntByScriptName( "basic_movement_og_zen_wallrun_idle" ) - entity recorderRef = GetEntByScriptName( "basic_movement_wallrun_start_ref" ) - - FlagWaitAny( "ZenGarden_PlayerReachedWallrunStart", "OG_WhyWeFight_VO_Done" ) - - FlagWait( "OG_WhyWeFight_VO_Done" ) - - waitthread Training_OG_Moves_ToSitting( wallrunRef, "OG_primed_idle", 0.5 ) - - FlagWait( "ZenGarden_PlayerReachedWallrunStart" ) - - thread GhostRecorder_RepeatUntilFlag( player, "ZenGarden_PlayerFinishedWallrun", recorderRef, $"anim_recording/training_record_zengarden_wallrun.rpak" ) - - if ( !Flag( "ZenGarden_PlayerFinishedWallrun" ) ) - thread OnscreenHint_DisplayUntilFlag( player, "wallrun_hint", "ZenGarden_PlayerFinishedWallrun" ) - - wait 1.0 // wait to see if player starts wallrunning right away - - if ( !Flag( "ZenGarden_PlayerFinishedWallrun" ) && !Flag( "ZenGarden_PlayerTouchingWallrunPanel" ) ) - { - // "Let's make sure your jump kit is primed. Basic wallrun here, give it a try." - waitthread Training_OG_ScriptedAnim( wallrunRef, "OG_primed" ) - thread Training_OG_Idles_Sitting( wallrunRef, "OG_primed_idle" ) - } - - if ( !Flag( "ZenGarden_PlayerFinishedWallrun" ) && !Flag( "ZenGarden_PlayerTouchingWallrunPanel" ) ) - wait 1.0 - - if ( !Flag( "ZenGarden_PlayerFinishedWallrun" ) && !Flag( "ZenGarden_PlayerTouchingWallrunPanel" ) ) - { - // "Same routine as last time- watch the ghost pilot, and try to follow along." - thread PlayDialogue( "og_wallrun_follow_ghost", file.ogPilot ) - waitthread Training_OG_ScriptedAnim( wallrunRef, "OG_primed_generic" ) - thread Training_OG_Idles_Sitting( wallrunRef, "OG_primed_idle" ) - } - - FlagWait( "ZenGarden_PlayerFinishedWallrun" ) - - if ( !Flag( "ZenGarden_PlayerReachedCrouchArea" ) ) - { - // "Good! Now you're moving." - file.postWallrunVOEndTime = Time() + 3.0 - thread PlayDialogue( "og_wallrun_done", player ) - wait 0.3 // min wait after - } -} - -void function Training_ZenGarden_Crouch( entity player ) -{ - entity ogIdle_crouchSpot = GetEntByScriptName( "zengarden_og_slide_idle") - entity ref_slideStart = GetEntByScriptName( "zengarden_slide_ref" ) - - if ( Flag( "ZenGarden_PlayerCrouched" ) ) - return - - waitthread Training_OG_Moves_ToSitting( ogIdle_crouchSpot, "OG_low_idle", 0.8 ) - thread GhostRecorder_RepeatUntilFlag( player, "ZenGarden_PlayerCrouched", ref_slideStart, $"anim_recording/training_record_zengarden_slide.rpak", 1.0 ) - - FlagWait( "ZenGarden_PlayerReachedCrouchArea" ) - - DisplayOnscreenHint( player, "crouch_hint", 5.0 ) - - while ( file.postWallrunVOEndTime > 0 && file.postWallrunVOEndTime - Time() > 0 ) - wait 0.1 - - if ( Flag( "ZenGarden_PlayerCrouched" ) ) - return - - // "Under here. Stay low." - waitthread Training_OG_ScriptedAnim( ogIdle_crouchSpot, "OG_low" ) - thread Training_OG_Idles_Sitting( ogIdle_crouchSpot, "OG_low_idle", true ) - - thread Training_ZenGarden_CrouchHint_WithNags( player, 10.0, ogIdle_crouchSpot, "OG_low_idle" ) - - FlagWait( "ZenGarden_PlayerCrouched" ) - - ClearOnscreenHint( player ) -} - -void function Training_ZenGarden_CrouchHint_WithNags( entity player, float nagInterval, entity idleRef, string ogIdleAnim ) -{ - player.EndSignal( "OnDestroy" ) - - string endFlag = "ZenGarden_PlayerCrouched" - string activeFlag = "ZenGarden_PlayerAtCrouchStart" - - // "Crouch underneath, and we'll keep moving." - // "You need to get low here." - array<string> nags = [ "og_crouch_nag_1", "og_crouch_nag_2" ] - - int nagIdx = 0 - float nextNagTime = Time() + nagInterval - - bool showingHint = false - - while ( !Flag( endFlag ) ) - { - FlagWait( activeFlag ) - - while ( Flag( activeFlag ) ) - { - wait 0.1 - - if ( player.IsCrouched() ) - { - if ( showingHint ) - { - showingHint = false - ClearOnscreenHint( player ) - } - - continue - } - - if ( !showingHint ) - { - DisplayOnscreenHint( player, "crouch_hint" ) - showingHint = true - } - - if ( Time() - nextNagTime >= nagInterval ) - { - thread Training_OG_Talks_Sitting( nags[nagIdx], idleRef, "", ogIdleAnim ) - nextNagTime = Time() + nagInterval - - nagIdx++ - if ( nagIdx >= nags.len() ) - nagIdx = 0 - } - } - - if ( showingHint ) - { - showingHint = false - ClearOnscreenHint( player ) - } - } -} - -void function Training_ZenGarden_DoubleJump( entity player ) -{ - entity pathRef = GetEntByScriptName( "zengarden_og_postslide_idle" ) - entity ogIdleRef = GetEntByScriptName( "zengarden_og_doublejump_idle" ) - entity recordedAnimRef = GetEntByScriptName( "zengarden_doublejump_ref" ) - - waitthread Training_OG_Moves( pathRef, "", 0.5 ) - - // "Simple double jump. Follow the ghost." - waitthread Training_OG_Talks( "og_doublejump_hint", pathRef ) - - thread GhostRecorder_RepeatUntilFlag( player, "ZenGarden_PlayerDoubleJumped", recordedAnimRef, $"anim_recording/training_record_zengarden_doublejump.rpak", 1.0 ) - - waitthread Training_OG_Moves_ToSitting( ogIdleRef, "OG_doublejump_idle", 0.5 ) - - // "We've retaken over a quarter of Frontier space since the Battle of Demeter. The Militia's better organized now. More people join everyday to fight the IMC. People like you." - waitthread Training_OG_ScriptedAnim( ogIdleRef, "OG_doublejump_A" ) - Training_OG_Idles( ogIdleRef, "OG_doublejump_B_idle" ) - - FlagWait( "ZenGarden_PlayerReachedDoubleJumpArea" ) - - if ( !Flag( "ZenGarden_PlayerDoubleJumped" ) ) - { - DisplayOnscreenHint( player, "doublejump_hint", 5.0 ) - thread OnscreenHint_NagUntilFlag( player, "doublejump_hint", "ZenGarden_PlayerDoubleJumped", 10.0, 5.0 ) - - wait 0.8 - } - - FlagWait( "ZenGarden_PlayerDoubleJumped" ) -} - -void function Training_ZenGarden_HillClimb( entity player, entity ref_hillclimbFinish, entity ref_exitSpot ) -{ - // "We used to just run and hide from them. But now we chase them." - string nextAnim = "OG_doublejump_B" - - if ( !Flag( "ZenGarden_PlayerClimbedHill" ) ) - { - waitthread Training_OG_Moves( ref_hillclimbFinish, "", 0.25 ) - //waitthread Training_OG_Talks( nextLine, ref_hillclimbFinish ) - waitthread Training_OG_ScriptedAnim( ref_hillclimbFinish, nextAnim ) - FlagWait( "ZenGarden_PlayerClimbedHill" ) - waitthread Training_OG_Moves( ref_exitSpot, ANIM_OG_LEANING_IDLE, 0.5 ) - } - else if ( !Flag( "ZenGarden_PlayerReachedExitArea" ) ) - { - waitthread Training_OG_Moves( ref_exitSpot, ANIM_OG_LEANING_IDLE, 0.5 ) - - if ( !Flag( "ZenGarden_PlayerReachedExitArea" ) ) - waitthread Training_OG_ScriptedAnim( ref_exitSpot, nextAnim ) - - if ( !Flag( "ZenGarden_PlayerReachedExitArea" ) ) - waitthread Training_OG_Moves( ref_exitSpot, ANIM_OG_LEANING_IDLE, 0.5 ) - } - - FlagWait( "ZenGarden_PlayerReachedExitArea" ) -} - - -// ================================= -// ========= FIRING RANGE ========== -// ================================= -void function Training_Setup_FiringRange( entity player ) -{ - entity ogStart = GetEntByScriptName( "firingrange_og_needguns_start_sitting" ) - entity og = Training_SpawnOGPilot( ogStart ) - Training_OG_Idles_Sitting( ogStart ) - - thread TakeAmmoFromPlayerASAP( player ) - - TeleportPlayerAndBT( "startpoint_firing_range" ) -} - -void function Training_Skipped_FiringRange( entity player ) -{ - CloseZenGardenExitDoor() - OpenGauntletDoor() - - FlagSet( "ineedguns" ) - Training_WeaponRacks_SetSolidity( true ) - - player.SetExtraWeaponMods( [ "" ] ) // turns off low_ammo_disable - SetWeaponHUDEnabled( player, true ) - - Training_SetWeaponPickupsFullAmmo() -} - -void function Training_FiringRange( entity player ) -{ - entity ref_og_needGunsStart = GetEntByScriptName( "firingrange_og_needguns_start_sitting" ) - entity ref_og_firingRangeSpot = GetEntByScriptName( "firingrange_og_spot" ) - entity ref_og_firingRangeAttractSpot = GetEntByScriptName( "firingrange_og_attract_spot" ) - - float ogMoveTime = -1 - - Training_WeaponRacks_SetSolidity( false ) - Training_SetWeaponPickupsEmptyAmmo() - - thread FiringRange_CloseZenGardenDoor_WhenPlayerReachesRange( player ) - - waitthread Training_OG_Moves_ToSitting( ref_og_needGunsStart, "OG_Weapons_idle", ogMoveTime ) - - FlagWait( "PlayerApproachingFiringRange" ) - - thread FiringRange_DetectWeaponSwitch( player ) - - waitthread FiringRange_ApproachAndEntry( player, ref_og_needGunsStart, ref_og_firingRangeAttractSpot, ref_og_firingRangeSpot ) - - waitthread FiringRange_TrainReload( player, ref_og_firingRangeSpot ) - - Training_WeaponRacks_SetSolidity( true ) - thread FiringRange_InfiniteAmmo_WhenNearRange( player, "PodOutroStarted" ) - thread FiringRange_ResetTargets_Think( player ) - - thread Training_OG_Idles( ref_og_firingRangeSpot, "OG_firingrange_idle" ) - - waitthread FiringRange_TrainADS( player, ref_og_firingRangeSpot ) - - waitthread FiringRange_PlayerMustDamageAllTargets( player, ref_og_firingRangeSpot, true, false ) - - Training_SetWeaponPickupsFullAmmo() - - if ( !Flag( "FiringRangeWeaponSwapped" ) ) - { - waitthread FiringRange_TrainWeaponSwap( player, ref_og_firingRangeSpot ) - - FlagWait( "PlayerNearFiringRange" ) // if player moved away to get a weapon, wait for them to come back - wait 0.25 // extra wait for player to see the targets reset - - waitthread FiringRange_PlayerMustDamageAllTargets( player, ref_og_firingRangeSpot, false ) - } - - OpenGauntletDoor() - - CheckPoint_Silent() - - // "Good. Practice more if you want, then head to the Gauntlet." - waitthread Training_OG_ScriptedAnim( ref_og_firingRangeSpot, "OG_firingrange_ending" ) - - array<string> moveToGauntletNags = [ "og_moving_to_gauntlet_nag_1", "og_moving_to_gauntlet_nag_2", "og_moving_to_gauntlet_nag_3" ] - - if ( Flag( "PlayerNearFiringRange" ) ) - { - entity ref_og_midway2Gauntlet = GetEntByScriptName( "og_between_firingrange_and_gauntlet" ) - thread Training_OG_NagPlayerUntilFlag_Sitting( player, moveToGauntletNags, 45.0, ref_og_midway2Gauntlet, "OG_MovedTo_GauntletEntrance" ) - - waitthread Training_OG_Moves_ToSitting( ref_og_midway2Gauntlet ) - - FlagWaitClear( "PlayerNearFiringRange" ) - } - - FlagSet( "OG_MovedTo_GauntletEntrance" ) - - entity ref_og_gauntletEntrance = GetEntByScriptName( "og_gauntlet_entrance_attract_spot" ) - thread Training_OG_NagPlayerUntilFlag( player, moveToGauntletNags, 45.0, ref_og_gauntletEntrance, "PlayerInGauntletEntryway" ) - - waitthread Training_OG_Moves( ref_og_gauntletEntrance ) -} - -void function FiringRange_CloseZenGardenDoor_WhenPlayerReachesRange( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - vector doorFarEdge = < -6368, -952, 48 > // HACK this is the bottom edge of the door farthest from the firing range - - while ( 1 ) - { - WaitFrame() - - if ( !Flag( "PlayerNearFiringRange" ) ) - continue - - if ( PlayerCanSeePos( player, doorFarEdge, true, 90 ) ) - continue - - break - } - - CloseZenGardenExitDoor() -} - -void function FiringRange_ApproachAndEntry( entity player, entity ref_og_needGunsStart, entity ref_og_firingRangeAttractSpot, entity ref_og_firingRangeSpot ) -{ - thread FiringRange_Approach_OG_Sequence( player, ref_og_needGunsStart ) - - FlagWait( "FiringRange_Approach_OG_Sequence_Done" ) - - if ( !Flag( "PlayerNearFiringRange" ) ) - { - // "Time to hit the range." - waitthread Training_OG_ScriptedAnim( ref_og_needGunsStart, "OG_Weapons_D" ) - } - - if ( !Flag( "PlayerNearFiringRange" ) ) - { - // "I'm over here at the range, Cooper." - thread Training_OG_NagPlayerUntilFlag( player, [ "og_firingrange_attract_nag" ], 40.0, ref_og_firingRangeAttractSpot, "PlayerNearFiringRange" ) - - waitthread Training_OG_Moves( ref_og_firingRangeAttractSpot ) - } - - FlagWait( "PlayerNearFiringRange" ) - - waitthread Training_OG_Moves( ref_og_firingRangeSpot, "OG_firingrange_idle" ) -} - -void function FiringRange_Approach_OG_Sequence( entity player, entity ref_og_needGunsStart ) -{ - EndSignal( player, "OnDestroy" ) - - if ( !Flag( "PlayerNearFiringRange" ) ) - Training_OG_Idles_Sitting( ref_og_needGunsStart ) - - if ( Flag( "PlayerNearFiringRange" ) ) - { - // player is rushing forward - FlagSet( "ineedguns" ) - thread FiringRange_INeedGuns_SFX( player, 0.0 ) - } - else - { - FlagSetDelayed( "ineedguns", 2.0 ) - thread FiringRange_INeedGuns_SFX( player, 2.0 ) - } - - if ( !Flag( "PlayerNearFiringRange" ) ) - { - // "In combat, things never go as you expect." - waitthread Training_OG_ScriptedAnim( ref_og_needGunsStart, "OG_Weapons_A" ) - } - - if ( !Flag( "PlayerNearFiringRange" ) ) - { - // "You must be ready to use any weapon you can find on the field." - waitthread Training_OG_ScriptedAnim( ref_og_needGunsStart, "OG_Weapons_B" ) - } - - if ( !Flag( "PlayerNearFiringRange" ) ) - { - // "These are just a few of the weapons I've come across out there." - waitthread Training_OG_ScriptedAnim( ref_og_needGunsStart, "OG_Weapons_C" ) - } - - FlagSet( "FiringRange_Approach_OG_Sequence_Done" ) -} - -void function FiringRange_INeedGuns_SFX( entity player, float delayTime ) -{ - EndSignal( player, "OnDestroy" ) - - - entity centerEmitter = GetEntByScriptName( "ref_firingrange_rack_sfx_center" ) - entity backCenterEmitter = GetEntByScriptName( "ref_firingrange_rack_sfx_backcenter" ) - entity leftEmitter = GetEntByScriptName( "ref_firingrange_rack_sfx_left" ) - entity rightEmitter = GetEntByScriptName( "ref_firingrange_rack_sfx_right" ) - - entity moverCenter = CreateScriptMover( centerEmitter.GetOrigin(), centerEmitter.GetAngles() ) - entity moverBackCenter = CreateScriptMover( backCenterEmitter.GetOrigin(), backCenterEmitter.GetAngles() ) - entity moverLeft = CreateScriptMover( leftEmitter.GetOrigin(), leftEmitter.GetAngles() ) - entity moverRight = CreateScriptMover( rightEmitter.GetOrigin(), rightEmitter.GetAngles() ) - array<entity> movers = [ moverCenter, moverBackCenter, moverLeft, moverRight ] - - OnThreadEnd( - function() : ( movers ) - { - foreach ( mover in movers ) - { - if( !IsValid( mover ) ) - continue - - mover.Destroy() - } - } - ) - - if ( delayTime > 0.0 ) - wait delayTime - - EmitSoundOnEntity( moverCenter, "training_scr_center_racks" ) - EmitSoundOnEntity( moverBackCenter, "training_scr_back_racks" ) - EmitSoundOnEntity( moverLeft, "training_scr_left_racks" ) - EmitSoundOnEntity( moverRight, "training_scr_right_racks" ) - - wait 15.0 // wait before cleaning up movers -} - -void function FiringRange_DetectWeaponSwitch( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - entity ogWeapon = WaitForPlayerActiveWeapon( player ) - string ogWeaponName = ogWeapon.GetWeaponClassName() - - while ( 1 ) - { - entity weapon = WaitForPlayerActiveWeapon( player ) - string weaponName = weapon.GetWeaponClassName() - - if ( weaponName != "" && weaponName != ogWeaponName ) - { - FlagSet( "FiringRangeWeaponSwapped" ) - break - } - - wait 0.5 - } -} - -void function FiringRange_TrainReload( entity player, entity ogIdleSpot ) -{ - FlagClear( "PlayerReloaded" ) - - SetWeaponHUDEnabled( player, true ) - - player.SetExtraWeaponMods( [ "" ] ) // turns off low_ammo_disable - thread TakeAmmoFromPlayerASAP( player ) - - thread TrainReload_GivePlayerAmmoAfterButtonPressed( player ) - - // "Load your weapon." - // "Swap in a fresh mag." - array<string> reloadNags = [ "og_reload_hint", "og_reload_nag" ] - - wait 1.1 // let pro players reload before prompting - - int nagIdx = 0 - - if ( !Flag( "PlayerReloaded" ) ) - { - thread OnscreenHint_DisplayUntilFlag( player, "reload_hint", "PlayerReloaded" ) - - float nagInterval = 15 - float lastNagTime = -100 - - while ( !Flag( "PlayerReloaded" ) ) - { - wait 0.1 - - if ( Time() - lastNagTime >= nagInterval ) - { - waitthread Training_OG_Talks( reloadNags[nagIdx], ogIdleSpot, "OG_firingrange_talk", "OG_firingrange_idle", true ) - lastNagTime = Time() - - nagIdx++ - if ( nagIdx >= reloadNags.len() ) - nagIdx = 0 - } - } - } -} - -void function TrainReload_GivePlayerAmmoAfterButtonPressed( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - FlagWait( "PlayerReloaded" ) - - FlagSet( "ReloadTraining_PlayerPressedReload" ) - - player.SetActiveWeaponPrimaryAmmoTotal( 50 ) -} - -void function FiringRange_InfiniteAmmo_WhenNearRange( entity player, string endFlag ) -{ - player.EndSignal( "OnDestroy" ) - FlagEnd( endFlag ) - - while ( 1 ) - { - wait 0.5 - - if ( !Flag( "PlayerNearFiringRange" ) ) - continue - - entity weapon = player.GetActiveWeapon() - - if ( weapon == null ) - continue - - int currAmmo = player.GetWeaponAmmoStockpile( weapon ) - int magSize = weapon.GetWeaponSettingInt( eWeaponVar.ammo_clip_size ) - int maxAmmo = weapon.GetWeaponSettingInt( eWeaponVar.ammo_stockpile_max ) - - // let player reload before restocking - if ( currAmmo > (maxAmmo-magSize + 1) ) - continue - - printt( "firing range restock ammo" ) - - RestockPlayerAmmo_Silent( player ) - } -} - -void function FiringRange_TrainADS( entity player, entity ref_og_firingRangeSpot ) -{ - thread FlagSetWhenPlayerADS( player, "PlayerADSed" ) - - FlagWaitWithTimeout( "PlayerADSed", 2.5 ) // give player time to ADS before hinting - - if ( !Flag( "PlayerADSed" ) ) - { - // "Aim down the sights when engaging more distant targets." - // "You can focus more tightly on your targets if you aim down the sights." - array<string> adsNags = [ "og_ads_nag_1", "og_ads_nag_2" ] - thread Training_OG_NagPlayerUntilFlag( player, adsNags, 10.0, ref_og_firingRangeSpot, "PlayerADSed", "OG_firingrange_talk", "OG_firingrange_idle" ) - - thread OnscreenHint_DisplayUntilFlag( player, "ads_hint", "PlayerADSed" ) - - // "To get more precision, aim down the sights of your weapon." - waitthread Training_OG_Talks( "og_ads_hint", ref_og_firingRangeSpot, "OG_firingrange_talk", "OG_firingrange_idle", true ) - } - - FlagWait( "PlayerADSed" ) -} - -void function FiringRange_TrainWeaponSwap( entity player, entity ref_og_firingRangeSpot ) -{ - Signal( player, "FiringRange_StopResettingTargets" ) - - if ( !Flag( "FiringRangeWeaponSwapped" ) ) - { - DisplayOnscreenHint( player, "weapon_pickup_hint", 5.0 ) - thread OnscreenHint_NagUntilFlag( player, "weapon_pickup_hint", "FiringRangeWeaponSwapped", 10.0, 5.0 ) - - // "Use a different weapon this time. Grab another one off the rack." - thread Training_OG_Talks( "og_weaponswap_hint", ref_og_firingRangeSpot, "OG_firingrange_talk", "OG_firingrange_idle", true ) - - // "Switch to a different weapon." - array<string> weaponSwapNags = [ "og_weaponswap_nag" ] - waitthread Training_OG_NagPlayerUntilFlag( player, weaponSwapNags, 10.0, ref_og_firingRangeSpot, "FiringRangeWeaponSwapped", "OG_firingrange_talk", "OG_firingrange_idle" ) - } -} - -void function FiringRange_PlayerMustDamageAllTargets( entity player, entity ref_og_firingRangeSpot, bool firstTime, bool resetTargetsAtStart = true ) -{ - EndSignal( player, "OnDestroy" ) - - FlagClear( "FiringRange_AllTargetsKilled" ) - thread FiringRange_ResetTargets_Think( player, resetTargetsAtStart ) - - thread OnscreenHint_DisplayUntilFlag( player, "firingrange_dmg_targets_hint", "FiringRange_AllTargetsKilled" ) - - wait 2.0 - - // "Gotta take 'em all out before we can move on." - // "Just aim, take a breath, and squeeze the trigger." - // "In the real world, the targets don't just stand still. They shoot back." - DialogueGroup nags = GetDialogueGroup( "shootTargetsNag" ) - - int numTargetsKilled = FiringRange_GetNumDamagedTargets() - - while ( !Flag( "FiringRange_AllTargetsKilled" ) ) - { - wait 1.0 - - // don't nag player if they recently damaged a target - if ( FiringRange_GetNumDamagedTargets() > numTargetsKilled ) - { - numTargetsKilled = FiringRange_GetNumDamagedTargets() - TimerReset( "firingRangeNag" ) - - continue - } - - if ( !TimerCheck( "firingRangeNag" ) ) - continue - - string nagLine = DialogueGroup_GetNextLine( nags ) - waitthread Training_OG_Talks( nagLine, ref_og_firingRangeSpot, "OG_firingrange_talk", "OG_firingrange_idle", true ) - - TimerReset( "firingRangeNag" ) - } -} - -void function FiringRangeTargets_Init() -{ - string targetScriptName = "firingrange_target" - array<entity> targetEnts = GetEntArrayByScriptName( targetScriptName ) - Assert( targetEnts.len(), "Couldn't get firing range targets with script_name " + targetScriptName ) - - foreach ( ent in targetEnts ) - { - ent.SetTakeDamageType( DAMAGE_EVENTS_ONLY ) - ent.SetDamageNotifications( true ) - - entity angleRefEnt = ent.GetLinkEnt() - Assert( IsValid( angleRefEnt ), "Firing range target needs an angle reference entity linked" ) - angleRefEnt.SetParent( ent ) - - FiringRangeTarget target - target.ent = ent - target.angleRefEnt = angleRefEnt - target.ogAngles = ent.GetAngles() - target.mover = CreateScriptMover( ent.GetOrigin(), ent.GetAngles() ) - ent.SetParent( target.mover ) - - file.firingRangeTargets.append( target ) - } -} - -int function FiringRange_GetNumDamagedTargets() -{ - int numDamaged = 0 - - foreach ( target in file.firingRangeTargets ) - if ( target.wasDamaged ) - numDamaged++ - - return numDamaged -} - -void function FiringRange_ResetAllTargets() -{ - foreach ( target in file.firingRangeTargets ) - FiringRangeTarget_Reset( target ) -} - -void function FiringRangeTarget_Reset( FiringRangeTarget target ) -{ - if ( !IsValid( target.ent ) ) - return - - target.wasDamaged = false - - thread FiringRangeTarget_RotateBack( target ) -} - -void function FiringRange_ResetTargets_Think( entity player, bool resetTargetsAtStart = true ) -{ - Signal( player, "FiringRange_StopResettingTargets" ) - EndSignal( player, "FiringRange_StopResettingTargets" ) - EndSignal( player, "OnDestroy" ) - - FlagEnd( "PodOutroStarted" ) - - array<FiringRangeTarget> firingRangeTargets = file.firingRangeTargets - - bool firstLoop = true - float targetResetWait = 1.75 - - while ( 1 ) - { - bool resetTargets = true - if ( firstLoop && !resetTargetsAtStart ) - resetTargets = false - - if ( resetTargets ) - FiringRange_ResetAllTargets() - - foreach ( target in firingRangeTargets ) - thread FiringRangeTarget_WaitForDamage( target ) - - // wait for all targets to take damage - while ( 1 ) - { - wait 0.2 - - bool allDamaged = true - foreach ( target in firingRangeTargets ) - { - if ( !target.wasDamaged ) - { - allDamaged = false - break - } - } - - if ( allDamaged ) - break - } - - FlagSet( "FiringRange_AllTargetsKilled" ) - - wait targetResetWait - - if ( firstLoop ) - firstLoop = false - } -} - -void function FiringRangeTarget_WaitForDamage( FiringRangeTarget target ) -{ - Signal( target.ent, "Target_WaitForDamage_Start" ) - EndSignal( target.ent, "Target_WaitForDamage_Start" ) - EndSignal( target.ent, "OnDestroy" ) - - bool first = true - while ( 1 ) - { - table result = WaitSignal( target.ent, "TargetDamaged" ) - vector damagePos = expect vector( result.damagePos ) - - if ( first ) - { - thread FiringRangeTarget_FirstDamage( target, damagePos ) - first = false - } - } - - return -} - -string function FiringRangeTarget_GetDamageSide( FiringRangeTarget target, vector damagePos ) -{ - vector upEntPos = target.angleRefEnt.GetOrigin() - vector upEntAngles = target.angleRefEnt.GetAngles() - - vector facingVec = AnglesToForward( upEntAngles ) - vector vecToDamage = Normalize( damagePos - upEntPos ) - float dot2Damage = DotProduct( vecToDamage, facingVec ) - printt( "damage dot product:", dot2Damage ) - - #if DEV - //float debugDrawTime = 3.0 - //DebugDrawAngles( damagePos, upEntAngles, debugDrawTime ) - //DebugDrawLine( upEntPos, upEntPos + (facingVec * 200), 200, 200, 0, true, debugDrawTime ) - #endif - - vector frontFacingVec = AnglesToRight( upEntAngles ) - bool isOnLeft = IsPointInFrontofLine( damagePos, upEntPos, frontFacingVec ) - - string returnStr = "left" - if ( isOnLeft ) - { - printt( "LEFT SIDE" ) - } - else - { - printt( "RIGHT SIDE" ) - returnStr = "right" - } - - return returnStr -} - -void function FiringRangeTarget_FirstDamage( FiringRangeTarget target, vector damagePos ) -{ - //Assert( !target.wasDamaged, "Target not expected to be damaged yet" ) - if ( target.wasDamaged ) - return - - target.wasDamaged = true - - if ( IsAlive( file.player ) ) - EmitSoundOnEntity( file.player, "training_scr_hit_target" ) - - // rotate left by default - float rotateAngY = 179.9 - if ( FiringRangeTarget_GetDamageSide( target, damagePos ) == "right" ) - rotateAngY *= -1 - - vector newAngles = target.ogAngles + Vector( 0, rotateAngY, 0 ) - thread FiringRangeTarget_Rotate( target, newAngles ) -} - -void function FiringRangeTarget_Rotate( FiringRangeTarget target, vector targetAngles ) -{ - Signal( target.mover, "TargetRotate" ) - EndSignal( target.mover, "TargetRotate" ) - EndSignal( target.mover, "OnDestroy" ) - - float rotateTime = 0.14 - float accelTime = 0 - float decelTime = 0.1 - target.mover.NonPhysicsRotateTo( targetAngles, rotateTime, accelTime, decelTime ) - - wait rotateTime -} - -void function FiringRangeTarget_RotateBack( FiringRangeTarget target ) -{ - if ( target.ent.GetAngles() == target.ogAngles ) - return - - EmitSoundAtPosition( TEAM_UNASSIGNED, target.ent.GetOrigin(), "training_scr_range_target_spin" ) - - waitthread FiringRangeTarget_Rotate( target, target.ogAngles ) -} - - -void function FlagSetWhenPlayerADS( entity player, string setFlag ) -{ - player.EndSignal( "OnDestroy" ) - - while ( player.GetZoomFrac() < 0.9 ) - wait 0.1 - - FlagSet( setFlag ) -} - - - -// ============================= -// ========= GAUNTLET ========== -// ============================= -void function Training_Setup_Gauntlet( entity player ) -{ - entity ogStart = GetEntByScriptName( "og_gauntlet_entrance_attract_spot" ) - entity og = Training_SpawnOGPilot( ogStart ) - Training_OG_Idles( ogStart ) - - TeleportPlayerAndBT( "startpoint_gauntlet_entrance" ) -} - -void function Training_Skipped_Gauntlet( entity player ) -{ - FlagSet( "Gauntlet_FirstRun_Done" ) - thread TrainingGauntlet_RemindPlayerAboutMobility( player ) - thread TrainingGauntlet_CrouchHint( player ) - thread TrainingGauntlet_SetsDifficulty( player ) -} - -void function Training_Gauntlet( entity player ) -{ - entity og = GetOGPilot() - - entity ref_og_gauntletStartPos = GetEntByScriptName( "og_near_gauntlet_start_pos" ) - GauntletInfo trainingGauntlet = GetTrainingGauntlet() - - // HACK - vector resultsBoardCenterPos = < -4899.15, 666.269, 107.187 > - - if ( !Flag( "PlayerInGauntletEntryway" ) && !trainingGauntlet.isActive && !PlayerCanSeePos( player, resultsBoardCenterPos, true, 90 ) ) - DisableGauntlet( trainingGauntlet ) // let a rushing player start the gauntlet - - if ( !trainingGauntlet.isActive ) - FlagWait( "PlayerInGauntletEntryway" ) - - if ( !trainingGauntlet.isActive ) - CheckPoint_Silent() - - waitthread Training_OG_Moves( ref_og_gauntletStartPos, ANIM_OG_LEANING_IDLE ) - - thread Training_Gauntlet_FirstRunDialogue( player, trainingGauntlet, ref_og_gauntletStartPos ) - wait 1.0 - - EnableGauntlet( trainingGauntlet ) - thread Training_Gauntlet_FirstRunGhostPlaybackStart( player, trainingGauntlet ) - thread TrainingGauntlet_TeleportPlayerAtFinishLine( player ) - thread TrainingGauntlet_RemindPlayerAboutMobility( player, "Gauntlet_FirstRun_All_VO_Finished" ) - thread TrainingGauntlet_CrouchHint( player ) - thread TrainingGauntlet_SetsDifficulty( player ) - - thread Training_Gauntlet_WaitForRequiredTime( player, ref_og_gauntletStartPos ) - FlagWait( "Gauntlet_FirstRun_Done" ) - - if ( !trainingGauntlet.isActive ) - CheckPoint_Silent() - - Gauntlet_StopGhostPlayback( trainingGauntlet ) - - waitthread Training_Gauntlet_PostFirstRunDialogue( player, trainingGauntlet ) -} - - -void function Training_Gauntlet_FirstRunDialogue( entity player, GauntletInfo gauntlet, entity ogIdleSpot ) -{ - player.EndSignal( "OnDestroy" ) - - if ( !gauntlet.isActive ) - { - // "Alright. Got a new gauntlet for you to run today." - waitthread Training_OG_ScriptedAnim( ogIdleSpot, "OG_gauntlet_start_A" ) - } - - if ( !gauntlet.isActive ) - { - // "Par time is a minute-forty-five." - waitthread Training_OG_ScriptedAnim( ogIdleSpot, "OG_gauntlet_start_B" ) - } - - if ( !gauntlet.isActive ) - { - // "Gotta do better than that to continue." - waitthread Training_OG_ScriptedAnim( ogIdleSpot, "OG_gauntlet_start_C" ) - } - - Objective_Set( "#TRAINING_OBJ_GAUNTLET_FIRSTRUN" ) - - //if ( gauntlet.isActive ) - // Training_Gauntlet_OG_Creates_FirstRun_Ghost( file.ogPilot ) - - AddAnimEvent( file.ogPilot, "create_ghost", Training_Gauntlet_OG_Creates_FirstRun_Ghost ) - - // "Follow the ghost, or find your own path." - waitthread Training_OG_ScriptedAnim( ogIdleSpot, "OG_gauntlet_start_D" ) - thread Training_OG_Idles( ogIdleSpot, "OG_gauntlet_start_endidle" ) - - DeleteAnimEvent( file.ogPilot, "create_ghost" ) - - float minDelayEnd = 5.0 + Time() - DialogueGroup firstRunGauntletLore = GetDialogueGroup( "firstRunGauntletLore" ) - while ( !Flag( "Gauntlet_FirstRun_Done" ) && !firstRunGauntletLore.allPlayed ) - { - wait 1 - - if ( !gauntlet.isActive ) - continue - - if ( Time() < minDelayEnd ) - continue - - string line = DialogueGroup_GetNextLine( firstRunGauntletLore ) - PlayDialogue( line, player ) - } - - FlagSet( "Gauntlet_FirstRun_All_VO_Finished" ) -} - -void function Training_Gauntlet_OG_Creates_FirstRun_Ghost( entity og ) -{ - entity player = file.player - if ( !IsValid( player ) ) - return - - player.Signal( "FirstRun_OG_Creates_Ghost" ) -} - -void function TrainingGauntlet_RemindPlayerAboutMobility( entity player, string waitFlag = "" ) -{ - EndSignal( player, "OnDestroy" ) - FlagEnd( "PlayerLeavingGauntlet" ) - - GauntletInfo trainingGauntlet = GetTrainingGauntlet() - - //if ( waitFlag != "" && !Flag( waitFlag ) ) - // FlagWait( waitFlag ) - - float nagInterval = 300 // 5 minutes - float nextNagTime = -1 - - float minSampleTime = 15.0 - float lowWallrunningFrac = 0.05 - - bool hasSprinted = false - - FlagWait( "Gauntlet_FirstRun_All_VO_Finished" ) - - while ( !Flag( "PlayerLeavingGauntlet" ) ) - { - if ( !trainingGauntlet.isActive ) - WaitSignal( player, "Gauntlet_RunStarted" ) - - float startTime = Time() - float samplePoints = 0 - float samplesWallrunning = 0 - - while ( trainingGauntlet.isActive ) - { - wait 0.1 - - if ( player.IsSprinting() && !hasSprinted ) - hasSprinted = true - - samplePoints++ - if ( player.IsWallRunning() ) - samplesWallrunning++ - - if ( (Time() - startTime) < minSampleTime ) - continue - - float wallrunningFrac = samplesWallrunning / samplePoints - printt( "wallrunningFrac:", wallrunningFrac ) - - // Has player done all the stuff we would want to remind them about? - if ( wallrunningFrac >= lowWallrunningFrac && hasSprinted ) - break - - if ( Time() >= nextNagTime ) - { - if ( !hasSprinted ) - thread TrainingGauntlet_SprintNag( player ) - else if ( wallrunningFrac < lowWallrunningFrac ) - thread TrainingGauntlet_WallrunNag( player, trainingGauntlet ) - - nextNagTime = Time() + nagInterval - } - - break - } - - if ( trainingGauntlet.isActive ) - WaitSignal( player, "Gauntlet_RunStopped" ) - } -} - -void function TrainingGauntlet_SprintNag( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - float hintDuration = 10.0 - float hintEndTime = Time() + hintDuration - DisplayOnscreenHint( player, "sprint_button_hint", hintDuration ) - - EndSignal( player, "DisplayingOnscreenHint" ) - - while ( Time() < hintEndTime && !player.IsSprinting() ) - WaitFrame() - - ClearOnscreenHint( player ) -} - -void function TrainingGauntlet_WallrunNag( entity player, GauntletInfo trainingGauntlet ) -{ - EndSignal( player, "OnDestroy" ) - - //printt( "playing mobility nag" ) - - DisplayOnscreenHint( player, "gauntlet_wallrun_hint", 8.0 ) - - DialogueGroup gauntletHints_wallrun = GetDialogueGroup( "gauntletHints_wallrun" ) - string line = DialogueGroup_GetNextLine( gauntletHints_wallrun ) - waitthread PlayDialogue( line, player ) - - if ( !trainingGauntlet.isActive ) - return - - waitthread PlayDialogue( "og_gauntlet_hint_wallrun_capper", player ) -} - -void function TrainingGauntlet_CrouchHint( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - string checkFlag = "Gauntlet_PlayerInCrouchHintZone" - string nagTimer = "gauntlet_crouchHint" - - TimerInit( nagTimer, 2.5 ) - - float waitTime = 1.0 - bool hintShowing = false - - while ( 1 ) - { - wait waitTime - - if ( !Flag( checkFlag ) ) - continue - - TimerReset( nagTimer ) - - while ( Flag( checkFlag ) ) - { - wait waitTime - - if ( !TimerCheck( "gauntlet_crouchHint" ) ) - continue - - if ( !hintShowing ) - { - DisplayOnscreenHint( player, "crouch_hint" ) - hintShowing = true - } - } - - if ( hintShowing ) - { - ClearOnscreenHint( player ) - hintShowing = false - } - } -} - -void function Training_Gauntlet_PostFirstRunDialogue( entity player, GauntletInfo gauntlet ) -{ - player.EndSignal( "OnDestroy" ) - player.EndSignal( "Gauntlet_RunStarted" ) - - entity ref_og_gauntletResults = GetEntByScriptName( "og_ref_gauntlet_results_display" ) - - Objective_SetSilent( "#TRAINING_OBJ_DEFAULT" ) - - waitthread Training_OG_Moves( ref_og_gauntletResults, "", 1.0 ) - - AddAnimEvent( file.ogPilot, "highlight_results_board_tip", Gauntlet_PostFirstRun_SetRandomTip ) - - // "Nice run! See the results board on the wall? You set a new Best Time." - // "Everyone has different strengths and weaknesses, so be sure to run this a few times with different weapons." - // "Look at the results board for more tips on how to improve." - waitthread Training_OG_ScriptedAnim( ref_og_gauntletResults, "OG_Gauntlet_return" ) - - DeleteAnimEvent( file.ogPilot, "highlight_results_board_tip" ) -} - -// update tip while OG is talking about the tips -void function Gauntlet_PostFirstRun_SetRandomTip( entity og ) -{ - entity player = file.player - if ( !IsValid( player ) ) - return - - GauntletInfo gauntlet = GetTrainingGauntlet() - Remote_CallFunction_Replay( player, "ScriptCallback_GauntletResultsDisplay_SetRandomTip", gauntlet.id ) -} - -void function Training_Gauntlet_FirstRunGhostPlaybackStart( entity player, GauntletInfo gauntlet ) -{ - if ( !gauntlet.isActive ) - WaitSignal( player, "Gauntlet_RunStarted", "FirstRun_OG_Creates_Ghost" ) - - thread Gauntlet_StartGhostPlayback( gauntlet, GHOST_NAME_FIRSTRUN, "#GAUNTLET_GHOST_NAME_FIRSTRUN" ) -} - -void function Training_Gauntlet_WaitForRequiredTime( entity player, entity ogIdleSpot ) -{ - player.EndSignal( "OnDestroy" ) - - GauntletInfo gauntlet = GetTrainingGauntlet() - - // "The first run of the day is always the toughest." - // "Too slow! I know you can do better. Give it another try." - DialogueGroup firstRunFailedGroup = GetDialogueGroup( "firstRunFailed" ) - - int failCount = 0 - while ( 1 ) - { - // keep setting this here because by default the gauntlet updates its random tip after each finished run - Remote_CallFunction_Replay( player, "ScriptCallback_TrainingGauntlet_ResultsDisplay_SetTip", gauntlet.id, 0 ) - - player.WaitSignal( "Gauntlet_RunStopped" ) - - wait 0.1 // HACK let the gauntlet struct get updated before checking it - - TrainingGauntletStats_PostRunUpdate( player, gauntlet, 0 ) - - if ( !gauntlet.runFinished ) - continue - - failCount++ - - if ( gauntlet.bestTime <= TRAINING_GAUNTLET_MAX_TIME_TO_PROGRESS || failCount == NUM_GAUNTLET_FAILS_BEFORE_FORCED_PROGRESS ) - { - if ( gauntlet.bestTime <= TRAINING_GAUNTLET_MAX_TIME_TO_PROGRESS ) - printt( "Gauntlet moving on: beat required time" ) - else if ( failCount == NUM_GAUNTLET_FAILS_BEFORE_FORCED_PROGRESS ) - printt( "Gauntlet moving on: forced progress after", NUM_GAUNTLET_FAILS_BEFORE_FORCED_PROGRESS, "failures" ) - - break - } - - wait 0.5 // let player get settled before VO starts - - EmitSoundOnEntityOnlyToPlayer( player, player, "training_scr_gaunlet_fail_01" ) - - string firstRunFailedLine = DialogueGroup_GetNextLine( firstRunFailedGroup ) - thread Training_OG_Talks_Leaning( firstRunFailedLine, ogIdleSpot, "", "", true ) - - Objective_Remind() - //DisplayOnscreenHint( player, "gauntlet_first_run_progression_hint", 9.0 ) - - if ( failCount == 2 ) - thread DoSprintEnableDialogForGauntletIfNeeded_Thread( player, 3.5 ) - } - - TrainingGauntletPostRun_TryAchievements( player, gauntlet ) - - FlagSet( "Gauntlet_FirstRun_Done" ) -} - -void function DoSprintEnableDialogForGauntletIfNeeded_Thread( entity player, float waitTime ) -{ - EndSignal( player, "OnDestroy" ) - wait waitTime - - if ( GetAutosprintEnabled() ) - return - - Remote_CallFunction_UI( player, "ScriptCallback_OpenAutosprintDialogForGauntlet" ) -} - -void function TrainingGauntlet_TeleportPlayerAtFinishLine( entity player ) -{ - Signal( player, "Gauntlet_StopTeleportingPlayerAtFinishLine" ) - EndSignal( player, "Gauntlet_StopTeleportingPlayerAtFinishLine" ) - EndSignal( player, "OnDestroy" ) - - entity startEnt = GetEntByScriptName( "results_room_teleport_refA" ) - entity endEnt = GetEntByScriptName( "results_room_teleport_refB" ) - vector startPos = startEnt.GetOrigin() - vector endPos = endEnt.GetOrigin() - - while ( 1 ) - { - player.WaitSignal( "Gauntlet_PlayerHitFinishTrig" ) - - vector currentPos = player.GetOrigin() - float offsetX = currentPos.x - startPos.x - float offsetY = currentPos.y - startPos.y - float offsetZ = currentPos.z - startPos.z - - float newPosX = endPos.x + offsetX - float newPosY = endPos.y + offsetY - float newPosZ = endPos.z + offsetZ - - vector newPos = < newPosX, newPosY, newPosZ > - - player.SetOrigin( newPos ) - } -} - - -void function TrainingGauntlet_SetsDifficulty( entity player ) -{ - if ( Flag( "PlayerLeavingGauntlet" ) ) - return - - FlagEnd( "PlayerLeavingGauntlet" ) - - player.EndSignal( "OnDestroy" ) - - GauntletInfo gauntlet = GetTrainingGauntlet() - - bool diffSetOnce = false - - while ( 1 ) - { - WaitSignal( player, "Gauntlet_RunStopped" ) - - if ( file.gauntletMode ) - return - - wait 0.2 // HACK let the gauntlet struct and file variables get set up after the run - - // extra wait for player to finish seeing their time, etc. - wait 2.0 - - if ( !gauntlet.runFinished ) - continue - - if ( !gauntlet.lastRunBestTime ) - continue - - int prevDiff = -1 - if ( diffSetOnce ) - prevDiff = GetConVarInt( "sp_difficulty" ) - - Training_SetDifficultyForGauntletTime( gauntlet.bestTime ) - if ( GetConVarInt( "sp_difficulty" ) > prevDiff ) - Training_AnnounceDifficultyForGauntletTime( player, 8.0 ) - - if ( !diffSetOnce ) - diffSetOnce = true - } -} - -void function Training_SetDifficultyForGauntletTime( float time ) -{ - float time = file.trainingGauntletStats.bestTime - if ( time == -1 ) - time = TRAINING_GAUNTLET_MAX_TIME_TO_PROGRESS - - int difficulty = DIFFICULTY_EASY - //if ( time <= REC_DIFF_GAUNTLET_TIME_MASTER ) - // difficulty = DIFFICULTY_MASTER - // else if - if ( time <= REC_DIFF_GAUNTLET_TIME_HARD ) - difficulty = DIFFICULTY_HARD - else if ( time <= REC_DIFF_GAUNTLET_TIME_NORMAL ) - difficulty = DIFFICULTY_NORMAL - - printt( "GetDifficultyForGauntletTime: diff", difficulty, "for time", time ) - - file.trainingGauntletStats.recommendedDifficulty = difficulty - - SetConVarInt( "sp_difficulty", difficulty ) -} - -void function Training_AnnounceDifficultyForGauntletTime( entity player, float displayTime = 5.0 ) -{ - string hintAlias = "hint_diff_" - hintAlias += file.trainingGauntletStats.recommendedDifficulty.tostring() - DisplayOnscreenHint( player, hintAlias, displayTime ) -} - - -// ====================================================== -// ========= GAUNTLET CHALLENGE (post 1st run) ========== -// ====================================================== -void function Training_Setup_GauntletChallenge( entity player ) -{ - entity ogStart = GetEntByScriptName( "og_ref_gauntlet_results_display" ) - entity og = Training_SpawnOGPilot( ogStart ) - Training_OG_Idles( ogStart ) - - TeleportPlayerAndBT( "playerstart_gauntlet_challenge" ) -} - -void function Training_Skipped_GauntletChallenge( entity player ) -{ -} - -void function Training_GauntletChallenge( entity player ) -{ - GauntletInfo gauntlet = GetTrainingGauntlet() - - thread TrainingGauntlet_TeleportPlayerAtFinishLine( player ) - - entity ref_og_gauntletLeaderboardPos = GetEntByScriptName( "og_near_leaderboard" ) - - // in gauntlet mode OG spawns here before player fade finishes, no need to move him - if ( !file.gauntletMode ) - waitthread Training_OG_Moves( ref_og_gauntletLeaderboardPos, "" ) - - Gauntlet_ShowLeaderboard( gauntlet ) - - thread GauntletChallenge_GhostsThink( player, gauntlet, "GauntletChallenge_FirstGhostAppear", "PlayerLeavingGauntlet" ) - thread GauntletChallenge_IntroDialogue( player, gauntlet, ref_og_gauntletLeaderboardPos ) - thread GauntletChallege_RestartGauntletHint( player, gauntlet ) - - FlagWait( "ChallengeIntro_VO_Done" ) - - bool installRuiStarted = false - if ( !Training_IsGameFullyInstalled() ) - Remote_CallFunction_Replay( player, "ScriptCallback_ShowInstallProgress", true ) - - entity ref_og_gauntletExitPos = GetEntByScriptName( "og_gauntlet_exit_pos" ) - thread Training_GauntletChallenge_DialogueThink( player, gauntlet, ref_og_gauntletExitPos ) - thread Training_OG_Moves( ref_og_gauntletExitPos, "OG_all_done_idle" ) - - wait 1.0 - thread Training_LeaveGauntletThink( player, ref_og_gauntletExitPos ) - - FlagWait( "PlayerConfirmedGauntletExit" ) - - Remote_CallFunction_Replay( player, "ScriptCallback_ShowInstallProgress", false ) - - Objective_SetSilent( "#TRAINING_OBJ_DEFAULT" ) - - DisableGauntlet( gauntlet ) - - FlagWait( "PlayerLeavingGauntlet" ) - - Signal( player, "Gauntlet_StopTeleportingPlayerAtFinishLine" ) - - if ( file.gauntletMode ) - { - thread Training_PodOutro( player ) - WaitForever() // stall normal progression - } - else - { - thread DisableWeaponDelayed( player, 0.3 ) // disable weapon so crosshairs aren't visible during white screen - - entity destEnt = GetEntByScriptName( "startpoint_titanfall" ) - waitthread PlayerAndOGTeleport_Fancy( player, destEnt.GetOrigin(), "og_titanfall_start_pos", destEnt.GetAngles() ) - - CheckPoint_Silent() - } -} - -void function DisableWeaponDelayed( entity player, float delay ) -{ - EndSignal( player, "OnDestroy" ) - - if ( delay > 0 ) - wait delay - - player.DisableWeapon() -} - -void function GauntletChallege_RestartGauntletHint( entity player, GauntletInfo gauntlet ) -{ - EndSignal( player, "OnDestroy" ) - - float displayTime = 5.0 - float delayTime = 2.5 - - const int RUNS_BETWEEN_REMINDERS = 3 - int runsSinceLastReminder = 3 // do reminder on first run - - while ( 1 ) - { - if ( !gauntlet.isActive ) - WaitSignal( player, "Gauntlet_RunStarted" ) - - float displayEndTime = -1 - - // check if we should remind after run starts - if ( runsSinceLastReminder >= RUNS_BETWEEN_REMINDERS ) - { - thread OnscreenHint_DisplayAfterDelay( player, "gauntlet_restart_hint", displayTime, delayTime ) - displayEndTime = Time() + displayTime + delayTime - } - - // wait for run to stop - table result = WaitSignal( player, "Gauntlet_RunStopped", "Gauntlet_ForceRestart" ) - string signal = expect string( result.signal ) - - // clear initial hint if player cancelled the run before it would auto clear - if ( displayEndTime != -1 && Time() < displayEndTime ) - ClearOnscreenHint( player ) - - // player went back through the starting gate? - if ( signal == "Gauntlet_RunStopped" && !gauntlet.runFinished ) - { - // Don't care about how many runs between reminders here- if player does this it means they don't really get it yet - thread DisplayOnscreenHint( player, "gauntlet_restart_hint", displayTime ) - runsSinceLastReminder = 0 - } - // player used menu to restart? - else if ( signal == "Gauntlet_ForceRestart" ) - { - runsSinceLastReminder = 0 // reset the counter when force restarted - } - - if ( runsSinceLastReminder >= RUNS_BETWEEN_REMINDERS ) - runsSinceLastReminder = 0 - if ( gauntlet.runFinished ) // player restarted from menu or went back through the gate - runsSinceLastReminder++ - } -} - -void function GauntletChallenge_IntroDialogue( entity player, GauntletInfo gauntlet, entity ogRef ) -{ - if ( file.gauntletMode ) - { - thread GauntletChallengeModeOnly_IntroDialogue( player, gauntlet, ogRef ) - return - } - - player.EndSignal( "OnDestroy" ) - - if ( !gauntlet.isActive ) - { - // "Now that you're warmed up: if you want a REAL challenge, you can race against other Pilot ghosts." - waitthread Training_OG_ScriptedAnim( ogRef, "OG_Leaderboard_A" ) - } - - player.Signal( "GauntletChallenge_FirstGhostAppear" ) - - if ( !gauntlet.isActive ) - { - // "Word of warning, though- the Pilots who recorded these ghosts are the best in the SRS. - waitthread Training_OG_ScriptedAnim( ogRef, "OG_Leaderboard_B" ) - } - - if ( !gauntlet.isActive ) - { - // "If you can beat them, you'll be halfway to being a real Pilot." - waitthread Training_OG_ScriptedAnim( ogRef, "OG_Leaderboard_C" ) - } - - if ( !gauntlet.isActive ) - { - // "Go ahead and run the Gauntlet as much as you want." - waitthread Training_OG_ScriptedAnim( ogRef, "OG_Leaderboard_D" ) - } - - // "When you're done, I've got something special to show you." - waitthread Training_OG_ScriptedAnim( ogRef, "OG_Leaderboard_E" ) - - if ( !Training_IsGameFullyInstalled() ) - { - Objective_Set( "#TRAINING_OBJ_GAUNTLET_CHALLENGE_INSTALLING" ) - thread ChangeGauntletObjective_OnInstallComplete( player ) - } - else - { - Objective_Set( "#TRAINING_OBJ_GAUNTLET_CHALLENGE" ) - } - - FlagSet( "ChallengeIntro_VO_Done" ) -} - -void function GauntletChallengeModeOnly_IntroDialogue( entity player, GauntletInfo gauntlet, entity ogRef ) -{ - player.EndSignal( "OnDestroy" ) - - SetSignalDelayed( player, "GauntletChallenge_FirstGhostAppear", 0.25 ) - - wait 1.5 // let player teleport and fade in before starting to talk - - if ( !gauntlet.isActive ) - { - // "Go ahead and run the Gauntlet as much as you want." - waitthread Training_OG_ScriptedAnim( ogRef, "OG_Leaderboard_D", true ) - } - - // "When you're done, I've got something special to show you." - //waitthread Training_OG_ScriptedAnim( ogRef, "OG_Leaderboard_E" ) - - Objective_Set( "#TRAINING_OBJ_GAUNTLET_CHALLENGE" ) - - FlagSet( "ChallengeIntro_VO_Done" ) -} - -void function ChangeGauntletObjective_OnInstallComplete( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - while ( !Training_IsGameFullyInstalled() ) - wait 1.0 - - Objective_Set( "#TRAINING_OBJ_GAUNTLET_CHALLENGE" ) -} - -void function GauntletChallenge_GhostsThink( entity player, GauntletInfo gauntlet, string signalWait, string endFlag ) -{ - if ( Flag( endFlag ) ) - return - - player.EndSignal( "OnDestroy" ) - gauntlet.signalEnt.EndSignal( "OnDestroy" ) - - FlagEnd( endFlag ) - - if ( !gauntlet.isActive ) - WaitSignal( player, "Gauntlet_RunStarted", signalWait ) - - thread Gauntlet_ChallengeLeaderboardGhosts( player, gauntlet, "PlayerLeavingGauntlet" ) -} - -void function Training_GauntletChallenge_DialogueThink( entity player, GauntletInfo gauntlet, entity ogSpot ) -{ - player.EndSignal( "OnDestroy" ) - - FlagWait( "ChallengeIntro_VO_Done" ) - - DialogueGroup clearedLeaderboard = GetDialogueGroup( "clearedLeaderboard" ) - DialogueGroup defeatedGhost = GetDialogueGroup( "defeatedGhost" ) - DialogueGroup notBestTime = GetDialogueGroup( "notBestTime" ) - DialogueGroup newBestTime = GetDialogueGroup( "newBestTime" ) - - while ( 1 ) - { - FlagClear( "Gauntlet_PlayingFeedbackVO" ) - - WaitSignal( player, "Gauntlet_RunStopped" ) - - wait 0.1 // HACK let the gauntlet struct get updated before checking - - TrainingGauntletStats_PostRunUpdate( player, gauntlet, 1 ) - - if ( !gauntlet.runFinished ) - continue - - TrainingGauntletPostRun_TryAchievements( player, gauntlet ) - - FlagSet( "Gauntlet_PlayingFeedbackVO" ) - - string feedbackLine = "" - - // SPECIAL- defeated a Hero Ghost - if ( gauntlet.lastRunDefeatedGhost && !gauntlet.allGhostsDefeated ) - { - array<GauntletGhost> leaderboard = Gauntlet_GetLeaderboard( gauntlet ) - GauntletGhost playerGhost = Gauntlet_GetPlayerGhost( gauntlet ) - - array<string> heroFileNames = [ GHOST_NAME_ALIAS_LASTIMOSA, GHOST_NAME_ALIAS_ANDERSON, GHOST_NAME_ALIAS_BRIGGS ] - - GauntletGhost loserGhost - foreach ( ghost in leaderboard ) - { - if ( playerGhost.duration <= ghost.duration && heroFileNames.contains( ghost.fileName ) ) - { - loserGhost = ghost - break - } - } - - switch ( loserGhost.fileName ) - { - case GHOST_NAME_ALIAS_LASTIMOSA: - // "Hey - that was my best time! I must be getting slow." - feedbackLine = "og_gauntlet_unlocked_leaderboard_entry_og" - break - - case GHOST_NAME_ALIAS_ANDERSON: - // "Heh. Can't wait to tell Anderson about that. Son of a bitch..." - feedbackLine = "og_gauntlet_unlocked_leaderboard_entry_anderson" - break - - case GHOST_NAME_ALIAS_BRIGGS: - // "You just beat Commander Briggs. Might not stay that way for long though, she's very competitive." - feedbackLine = "og_gauntlet_unlocked_leaderboard_entry_briggs" - break - } - - if ( feedbackLine != "" ) - waitthread Training_OG_Talks( feedbackLine, ogSpot, "OG_all_done_talk", "OG_all_done_idle", true ) - } - - // SPECIAL - cleared leaderboard - if ( gauntlet.allGhostsDefeated && !clearedLeaderboard.allPlayed ) - { - while ( !clearedLeaderboard.allPlayed && !gauntlet.isActive ) - { - feedbackLine = DialogueGroup_GetNextLine( clearedLeaderboard ) - waitthread Training_OG_Talks( feedbackLine, ogSpot, "OG_all_done_talk", "OG_all_done_idle", true ) - } - } - - // If we played a line by now, it was Special, so we don't want the generic ones below. - if ( feedbackLine != "" ) - continue - - // LAST RUN: DEFEATED GHOST (GENERIC) - if ( gauntlet.lastRunDefeatedGhost && !gauntlet.allGhostsDefeated ) - { - feedbackLine = DialogueGroup_GetNextLine( defeatedGhost ) - } - // LAST RUN: BEAT BEST TIME - else if ( gauntlet.lastRunBestTime ) - { - feedbackLine = DialogueGroup_GetNextLine( newBestTime ) - } - // LAST RUN: FAILED TO BEAT BEST TIME - else - { - feedbackLine = DialogueGroup_GetNextLine( notBestTime ) - } - - Assert( feedbackLine != "" ) - waitthread Training_OG_Talks( feedbackLine, ogSpot, "OG_all_done_talk", "OG_all_done_idle", true ) - } -} - -void function TrainingGauntletPostRun_TryAchievements( entity player, GauntletInfo gauntlet ) -{ - Assert( gauntlet.runFinished ) - - GauntletGhost andersonGhost = Gauntlet_GetGhostByFileName( gauntlet, GHOST_NAME_ALIAS_ANDERSON ) - if ( gauntlet.lastRunTime < andersonGhost.duration ) - { - // Achievement - Beat Pilot Anderson's gauntlet ghost recorder time - UnlockAchievement( player, achievements.GAUNTLET_BEAT_ANDERSON ) - } - - GauntletGhost playerGhost = Gauntlet_GetPlayerGhost( gauntlet ) - int playerLeaderboardPos = Gauntlet_GetLeaderboardPosition_ForGhostID( gauntlet, playerGhost.id ) - if ( playerLeaderboardPos <= 2 ) - { - // Achievement - Get a top-3 spot on the Gauntlet scoreboard - UnlockAchievement( player, achievements.GAUNTLET_TOPTHREE ) - } -} - -void function Training_LeaveGauntletThink( entity player, entity ogSpot ) -{ - string gauntletExitConversation = "Gauntlet_Exit" - if ( file.gauntletMode ) - gauntletExitConversation = "Gauntlet_Exit_TechTest" - - GauntletInfo trainingGauntlet = GetTrainingGauntlet() - - // NOTE conversation callbacks need this defined - file.animref_leaveGauntlet = ogSpot - AddConversationCallback( gauntletExitConversation, ConvoCallback_TrainingExit ) - AddConversationCallback( "Titanfall_Intro", ConvoCallback_TitanfallIntro) - - int numTimesInitiated = 0 - - while ( !Flag( "PlayerConfirmedGauntletExit" ) ) - { - FlagWait( "Gauntlet_PlayerInExitZone" ) - - FlagWaitClear( "Gauntlet_PlayingFeedbackVO" ) - - if ( !Flag( "Gauntlet_PlayerInExitZone" ) ) - continue - - if ( !Training_IsGameFullyInstalled() ) - { - waitthread Gauntlet_GameNotFullyInstalled_Response( player, ogSpot ) - wait 0.1 // HACK make sure we always wait before continuing - continue - } - - numTimesInitiated++ - - // All done with the gauntlet? - waitthread Training_OG_ScriptedAnim( ogSpot, "OG_all_done", true ) - Training_OG_Idles( ogSpot, "OG_all_done_idle", true ) - - // if player rushed to the gauntlet during the anim, don't wait for conversation - if ( trainingGauntlet.isActive ) - continue - - // hint if player can't figure out how to conversate - bool displayedOnscreenHint = false - if ( numTimesInitiated > 1 && !Flag( "PlayerUsedConversationInterface" ) ) - { - thread OnscreenHint_DisplayAfterDelay( player, "conversation_hint", 5.0, 1.5 ) - displayedOnscreenHint = true - } - - // interactive dialogue: Gauntlet Exit - FlagClear( "GauntletExitConvo_FinishedResponse" ) - thread PlayerConversation( gauntletExitConversation, player, file.ogPilot ) - - table result = WaitSignal( player, "ConversationEnded", "PlayerMadeSelection", "Gauntlet_RunStarted" ) - string sig = expect string( result.signal ) - - // bug 202299: Also check flag for player confirmed gauntlet exit - // - player can confirm exit, but if player starts a gauntlet run just before the response line ends, convo can "cancel" causing a prog break here - if ( sig == "Gauntlet_RunStarted" ) - { - // HACK- wait a bit to make sure player didn't confirm exit before the conversation ended due to gauntlet run starting - wait 0.5 - - if ( !Flag( "PlayerConfirmedGauntletExit" ) ) - { - StopConversationNow( player ) - continue - } - } - - /* - #if DEV - if ( sig == "Gauntlet_RunStarted" && Flag( "PlayerConfirmedGauntletExit" ) ) - printt( "BUG CONDITION DEFEATED" ) - #endif - */ - - if ( sig == "PlayerMadeSelection" ) - FlagSet( "PlayerUsedConversationInterface" ) - - if ( displayedOnscreenHint ) - ClearOnscreenHint( player ) - - // wait for callback function to finish doing its thing - FlagWait( "GauntletExitConvo_FinishedResponse" ) - - if ( Flag( "PlayerConfirmedGauntletExit" ) ) - break - - FlagWaitClear( "Gauntlet_PlayerInExitZone" ) - - StopConversationNow( player ) - } - - if ( file.gauntletMode ) - { - GauntletMode_Finished( player ) - } - else - { - // interactive dialogue: Titanfall Intro - FlagClear( "TitanfallIntroConvo_FinishedResponse" ) - waitthread PlayerConversation( "Titanfall_Intro", player, file.ogPilot ) - - FlagWait( "TitanfallIntroConvo_FinishedResponse" ) - } - - wait 0.2 - - FlagSet( "PlayerLeavingGauntlet" ) -} - -void function Gauntlet_GameNotFullyInstalled_Response( entity player, entity ogRef ) -{ - EndSignal( player, "OnDestroy" ) - - float progress = GetGameFullyInstalledProgress() - printt( "Game is not fully installed- cannot continue past Gauntlet. Progress:", progress, "/ 1.0" ) - - DisplayOnscreenHint( player, "gauntlet_install_hint" ) - - OnThreadEnd( - function() : ( player ) - { - if ( IsValid( player ) ) - ClearOnscreenHint( player ) - } - ) - - if ( TimerCheck( "installWaitComment" ) ) - { - DialogueGroup installWait = GetDialogueGroup( "installWait" ) - string line = DialogueGroup_GetNextLine( installWait ) - waitthread Training_OG_Talks( line, ogRef, "OG_all_done_talk", "OG_all_done_idle", true ) - - TimerReset( "installWaitComment" ) - } - - while ( Flag( "Gauntlet_PlayerInExitZone" ) && !Training_IsGameFullyInstalled() ) - { - wait 0.25 - } -} - -void function ConvoCallback_TrainingExit( int choice ) -{ - EndSignal( file.player, "OnDestroy" ) - - OnThreadEnd( - function() : ( ) - { - if ( IsValid( file.player ) ) - FlagSet( "GauntletExitConvo_FinishedResponse" ) - } - ) - - printt( "TRAINING EXIT CALLBACK: player chose", choice ) - Assert( choice >= 0 && choice <= 2, "Nothing set up for Training Exit convo choice " + choice ) - - // prompt timed out - if ( choice == 0 ) - return - - Signal( file.player, "PlayerMadeSelection" ) - - // player chooses to stay - if ( choice == 2 ) - { - waitthread Training_OG_ScriptedAnim( file.animref_leaveGauntlet, "OG_all_done_respond", true ) - Training_OG_Idles( file.animref_leaveGauntlet, "OG_all_done_idle", true ) - return - } - - // player chooses to leave - FlagSet( "PlayerConfirmedGauntletExit" ) - printt( "PLAYER CONFIRMED GAUNTLET EXIT" ) - - // Good. You're gonna like this. - // It's time you learned the other half of being a Pilot: the Titan. Let's go call one in. - string anim = "OG_gonna_like_this" - if ( file.gauntletMode ) - { - // Good. You're gonna like this. - // Let's get back to the real world. - anim = "OG_gonna_like_this_tech_test_end" - } - - waitthread Training_OG_ScriptedAnim( file.animref_leaveGauntlet, anim, true ) - Training_OG_Idles( file.animref_leaveGauntlet, "OG_gonna_like_this_endidle", true ) -} - -void function ConvoCallback_TitanfallIntro( int choice ) -{ - EndSignal( file.player, "OnDestroy" ) - - OnThreadEnd( - function() : ( ) - { - if ( IsValid( file.player ) ) - FlagSet( "TitanfallIntroConvo_FinishedResponse" ) - } - ) - - printt( "TITANFALL INTRO CALLBACK: player chose", choice ) - Assert( choice >= 0 && choice <= 2, "Nothing set up for Titanfall Intro convo choice " + choice ) - - // It's only a simulation, Cooper. It's not the real thing. - // But first- We're gonna need a little more space - string responseAnim = "OG_gonna_like_this_respond_A" - if ( choice == 2 ) - { - // That's the spirit. - // But first- We're gonna need a little more space - responseAnim = "OG_gonna_like_this_respond_B" - } - - thread Training_OG_ScriptedAnim( file.animref_leaveGauntlet, responseAnim, true ) - float duration = GetOGPilot().GetSequenceDuration( responseAnim ) - wait duration - 1.0 - - //Training_OG_Idles( file.animref_leaveGauntlet, "OG_gonna_like_this_endidle", true ) -} - - -// runType: 0 = before beating required time; 1 = in challenge mode -void function TrainingGauntletStats_PostRunUpdate( entity player, GauntletInfo gauntlet, int runType ) -{ - Assert( !gauntlet.isActive, "Can't update gauntlet stats reliably while gauntlet is active." ) - - // restarted gauntlet from menu - if ( !gauntlet.runFinished ) - { - file.trainingGauntletStats.numRestarts++ - printt( "training gauntlet stats updated: numRestarts", file.trainingGauntletStats.numRestarts ) - - SendTrainingGauntletStats( player ) - return - } - - if ( gauntlet.lastRunBestTime ) - { - file.trainingGauntletStats.bestTime = gauntlet.bestTime - printt( "training gauntlet stats updated: bestTime", file.trainingGauntletStats.bestTime ) - } - - if ( runType == 0 ) - { - file.trainingGauntletStats.numRunsBeforeBeatRequiredTime++ - printt( "training gauntlet stats updated: numRunsBeforeBeatRequiredTime", file.trainingGauntletStats.numRunsBeforeBeatRequiredTime ) - - if ( gauntlet.bestTime > TRAINING_GAUNTLET_MAX_TIME_TO_PROGRESS ) - { - // failed to get required time - SendTrainingGauntletStats( player ) - return - } - else - { - file.trainingGauntletStats.didBeatRequiredTime = true - printt( "training gauntlet stats updated: didBeatRequiredTime", file.trainingGauntletStats.didBeatRequiredTime ) - } - } - else if ( runType == 1 ) - { - file.trainingGauntletStats.numChallengeRuns++ - printt( "training gauntlet stats updated: numChallengeRuns", file.trainingGauntletStats.numChallengeRuns ) - } - - SendTrainingGauntletStats( player ) -} - - -void function SendTrainingGauntletStats( entity player ) -{ - printt("======== TRAINING GAUNTLET STATS =========" ) - printt( "numRestarts:", file.trainingGauntletStats.numRestarts ) - printt( "numRunsBeforeBeatRequiredTime:", file.trainingGauntletStats.numRunsBeforeBeatRequiredTime ) - printt( "didBeatRequiredTime:", file.trainingGauntletStats.didBeatRequiredTime ) - printt( "numChallengeRuns:", file.trainingGauntletStats.numChallengeRuns ) - printt( "bestTime:", file.trainingGauntletStats.bestTime ) - printt("========= END TRAINING GAUNTLET STATS ==========" ) - SendTrainingGauntletStatsToBackend( - player, - file.trainingGauntletStats.didBeatRequiredTime ? file.trainingGauntletStats.numRunsBeforeBeatRequiredTime : 0, - file.trainingGauntletStats.numChallengeRuns, - file.trainingGauntletStats.bestTime - ) -} - - -bool function Training_IsGameFullyInstalled() -{ - #if DEV - if ( INSTALL_DELAY_TEST ) - return file.fakeInstallDone - #endif - - return IsGameFullyInstalled() -} - -#if DEV -void function setfakeinstalldone( bool isDone ) -{ - file.fakeInstallDone = isDone -} -#endif - - -// =================================== -// ============ TITANFALL ============ -// =================================== -void function Training_Setup_Titanfall( entity player ) -{ - entity ogRef_titanfall = GetEntByScriptName( "og_titanfall_start_pos" ) - entity og = Training_SpawnOGPilot( ogRef_titanfall ) - Training_OG_Idles_Sitting( ogRef_titanfall, "OG_first_titan_idle" ) - - player.DisableWeapon() // player weapon is disabled before teleport to Titanfall area starts - - TeleportPlayerAndBT( "startpoint_titanfall" ) -} - -void function Training_Skipped_Titanfall( entity player ) -{ - player.SetExtraWeaponMods( ["training_low_ammo_disable"] ) - SetWeaponHUDEnabled( player, false ) -} - -void function Training_Titanfall( entity player ) -{ - thread Titanfall_EnableWeaponDelayed( player, 0.9 ) - - thread TakeAmmoFromPlayerASAP( player ) - thread Titanfall_SpecialWeaponRemove( player ) - - entity og = GetOGPilot() - entity ogRef_titanfall = GetEntByScriptName( "og_titanfall_start_pos" ) - Training_OG_Idles_Sitting( ogRef_titanfall, "OG_first_titan_idle" ) - - vector twinRefSpawnOrg = TitanfallGlitch_WorldChange_GetOtherWorldPos( ogRef_titanfall.GetOrigin(), true ) - entity ogRef_titanfall_twin = CreateScriptMover( twinRefSpawnOrg, ogRef_titanfall.GetAngles() ) - entity ogTwin = Training_SpawnOGTwin( ogRef_titanfall_twin ) - Training_NPC_Idles_Sitting( ogTwin, ogRef_titanfall_twin, "OG_first_titan_idle" ) - - OnThreadEnd( - function() : ( player, ogTwin, ogRef_titanfall_twin ) - { - if ( IsValid( player ) ) - player.UnfreezeControlsOnServer() - - if ( IsValid( ogTwin ) ) - ogTwin.Destroy() - - if ( IsValid( ogRef_titanfall_twin ) ) - ogRef_titanfall_twin.Destroy() - } - ) - - //testglitch() - //wait 1000000 - - thread Titanfall_BT_Think( player, 6.5 ) - - wait 2.0 - - // "That's my partner, BT. He's a Vanguard-class." - // "Homegrown Militia technology." - // "The first Titan chassis we designed ourselves. One we didn't have to steal from the IMC." - waitthread Training_OG_ScriptedAnim( ogRef_titanfall, "OG_Partner_BT", true ) - Training_OG_Idles_Sitting( ogRef_titanfall, "OG_first_titan_idle", true ) - - wait 1.1 // take a breath between lines - - thread Training_EnableTitanfallAndNag( player, ogRef_titanfall, 25.0 ) - - // "Go ahead Rifleman, call in your first Titan." - Titanfall_ResetHintVOTimer() // in case player calls in Titan during this line - waitthread Training_OG_ScriptedAnim( ogRef_titanfall, "OG_First_Titan", true ) - Training_OG_Idles_Sitting( ogRef_titanfall, "OG_first_titan_idle", true ) - - FlagWait( "PlayerStartedTitanfall" ) - // Don't start OG's next line until the nag is done, to avoid overlap - wait Titanfall_GetHintVORemainingDuration() - - // "Look up, to the sky- there he is." - waitthread Training_OG_ScriptedAnim( ogRef_titanfall, "OG_Look_Up", true ) - Training_OG_Idles_Sitting( ogRef_titanfall, "OG_first_titan_idle", true ) - - thread Titanfall_QuickdeathCustomResetPlayerPos( player, file.playerTitanCallInPos, "PodOutroStarted" ) - - // wait for titan to appear - while ( !GetPlayerTitanInMap( player ) ) - wait 0.1 - - entity titan = GetPlayerTitanInMap( player ) - - // "glitch" interrupts titan drop - FlagWait( "TitanfallGlitchStart" ) - - PlayMusic( "music_training_01_glitch" ) - - // Glitch ends when this function ends - float totalGlitchTime = 2.9 - float glitchEndTime = Time() + totalGlitchTime - - wait 1.0 - player.FreezeControlsOnServer() - - thread Training_OG_ScriptedAnim( ogRef_titanfall, "OG_Pulling_You_Out", true ) - - wait glitchEndTime - Time() - - if ( IsValid( titan ) ) - titan.Destroy() - - if ( IsValid( file.titanTwin ) ) - file.titanTwin.Destroy() -} - -void function Titanfall_EnableWeaponDelayed( entity player, float delay ) -{ - EndSignal( player, "OnDestroy" ) - - if ( delay > 0 ) - wait delay - - player.EnableWeapon() - player.SetExtraWeaponMods( ["training_low_ammo_disable"] ) - SetWeaponHUDEnabled( player, false ) -} - -void function Titanfall_SpecialWeaponRemove( entity player ) -{ - array<entity> weapons = player.GetMainWeapons() - int numWeaponsStart = weapons.len() - - foreach ( equippedWeapon in weapons ) - { - string equippedWeaponClassName = equippedWeapon.GetWeaponClassName() - if ( equippedWeaponClassName == "mp_weapon_lstar" ) // LSTAR display blinks annoyingly if ammo is gone - { - // give player a weapon if we are going to take their only weapon - if ( numWeaponsStart <= 1 ) - player.GiveWeapon( "mp_weapon_semipistol" ) - - player.TakeWeapon( equippedWeaponClassName ) - - break - } - } -} - -void function Titanfall_BT_Think( entity player, float getUpDelay = 0.0 ) -{ - EndSignal( player, "OnDestroy" ) - - entity spawnRef = GetEntByScriptName( "titanfall_bt_spawn_ref" ) - vector spawnOrg = spawnRef.GetOrigin() - vector spawnAng = spawnRef.GetAngles() - - // create BT - TitanLoadoutDef loadout = GetTitanLoadoutForPlayer( player ) - entity bt = CreateNPCTitan( loadout.setFile, player.GetTeam(), spawnOrg, spawnAng, loadout.setFileMods ) - bt.ai.titanSpawnLoadout = loadout - bt.kv.spawnflags = SF_NPC_ALLOW_SPAWN_SOLID - DispatchSpawn( bt ) - - entity animref = CreateScriptMover( spawnOrg, spawnAng ) - - OnThreadEnd( - function() : ( bt, animref ) - { - if ( IsValid( bt ) ) - bt.Destroy() - - if ( IsValid( animref ) ) - animref.Destroy() - } - ) - - bt.EnableNPCFlag( NPC_IGNORE_FRIENDLY_SOUND ) - bt.SetEfficientMode( true ) - bt.SetTouchTriggers( false ) - bt.SetNoTarget( true ) - bt.UnsetUsable() - bt.SetInvulnerable() - bt.EnableRenderAlways() - - bt.SetTitle( "#NPC_BT_NAME" ) - ShowName( bt ) - - DisableTitanfallForLifetimeOfEntityNearOrigin( bt, bt.GetOrigin(), TITANHOTDROP_DISABLE_ENEMY_TITANFALL_RADIUS ) - - // HACK this anim pops if it's played off of the animref, - // but looks good if played off BT before using the animref for the rest - thread PlayAnim( bt, "bt_training_scripted_kneel_idle", bt ) - - if ( getUpDelay > 0 ) - wait getUpDelay - - waitthread PlayAnim( bt, "bt_training_scripted_kneel2stand", animref ) - thread PlayAnim( bt, "bt_training_scripted_stand_idle", animref ) - - FlagWait( "PodOutroStarted" ) -} - -void function Titanfall_QuickdeathCustomResetPlayerPos( entity player, vector titanCallInPos, string endFlag ) -{ - FlagEnd( endFlag ) - - entity resetEnt = GetEntByScriptName( "ref_titanfall_quickdeath_reset" ) - vector resetPos = resetEnt.GetOrigin() - - while ( 1 ) - { - WaitSignal( player, "QuickDeath" ) - - vector angToCallInPos = VectorToAngles( titanCallInPos - resetPos ) - float viewTiltUpAngX = -10.0 // goose the view up a little - vector viewAng = <viewTiltUpAngX, angToCallInPos.y, 0> - - player.p.quickDeathOrigin = resetPos - player.p.quickDeathAngles = viewAng - } -} - -void function Training_EnableTitanfallAndNag( entity player, entity ogRef, float nagDelay ) -{ - EndSignal( player, "OnDestroy" ) - - SetGlobalNetBool( "trainingTitanfallEnabled", true ) - AddClientCommandCallback( "ClientCommand_TrainingRequestedTitanfall", Training_RequestTitanfall ) - - float onscreenHintDisplayTime = nagDelay * 0.5 - thread OnscreenHint_DisplayAfterDelay( player, "titanfall_hint", onscreenHintDisplayTime, 3.5 ) // extra delay on first screen prompt so pros can call it in - - Objective_SetSilent( "#TRAINING_OBJ_CALL_TITAN" ) - - // "Titan's ready. Call it in." - // "Titan's ready to drop. On your mark." - array<string> titanfallNags = [ "og_titanfall_nag_1", "og_titanfall_nag_2" ] - - DialogueGroup callInTitan = GetDialogueGroup( "callInTitan" ) - while ( !Flag( "PlayerStartedTitanfall" ) ) - { - FlagWaitWithTimeout( "PlayerStartedTitanfall", nagDelay ) - if ( Flag( "PlayerStartedTitanfall" ) ) - break - - thread OnscreenHint_DisplayAfterDelay( player, "titanfall_hint", onscreenHintDisplayTime, 2.5 ) - - string line = DialogueGroup_GetNextLine( callInTitan ) - Titanfall_ResetHintVOTimer() - waitthread Training_OG_Talks_Sitting( line, ogRef, "OG_first_titan_talk", "OG_first_titan_idle" ) - } - - Objective_SetSilent( "#TRAINING_OBJ_DEFAULT" ) - ClearOnscreenHint( player ) -} - - -// CUSTOM HOTDROP -bool function Training_RequestTitanfall( entity player, array<string> args ) -{ - Training_ReplacementTitan( player ) //Separate function because other functions will call ReplacementTitan - return true -} - -bool function Training_ReplacementTitan( entity player ) -{ - Assert( IsAlive( player ) ) - - Assert ( !GetPlayerTitanInMap( player ) ) - - Point spawnPoint = GetTitanReplacementPoint( player, false ) - vector origin = spawnPoint.origin - vector angles = spawnPoint.angles - - file.playerTitanCallInPos = origin - - FlagSet( "PlayerStartedTitanfall" ) - SetGlobalNetBool( "trainingTitanfallEnabled", false ) - - thread Training_CreateTitanForPlayerAndHotdrop( player, origin, angles ) - - return true -} - -#if DEV -void function testglitch() -{ - thread Training_CreateTitanForPlayerAndHotdrop( GetPlayerArray()[0], <2048, -2852, -349>, <0,0,0> ) -} -#endif - -void function Training_CreateTitanForPlayerAndHotdrop( entity player, vector spawnOrg, vector spawnAng ) -{ - Assert( IsValid( player ) ) - OnThreadEnd( - function() : ( player ) - { - if ( !IsValid( player ) ) - return - - player.ClearHotDropImpactTime() - } - ) - - player.EndSignal( "OnDestroy" ) - - vector origin = spawnOrg - vector angles - if ( spawnAng != < 0.0, 0.0, 0.0 > ) - angles = spawnAng - else - angles = VectorToAngles( FlattenVector( player.GetViewVector() ) * -1 ) // face the player - - printt( "Dropping replacement titan at " + origin + " with angles " + angles ) - - player.Signal( "CalledInReplacementTitan" ) - - int playerTeam = player.GetTeam() - - // spawn the Titan that will drop - TitanLoadoutDef loadout = GetTitanLoadoutForPlayer( player ) - entity titan = CreateAutoTitanForPlayer_FromTitanLoadout( player, loadout, origin, angles ) - DispatchSpawn( titan ) - titan.EndSignal( "OnDeath" ) - - titan.SetSkin( 2 ) // "Sarah Briggs" Vanguard skin - titan.SetTitle( "#NPC_BT_SPARE_NAME" ) - HideName( titan ) - TakeAllWeapons( titan ) - titan.SetEfficientMode( true ) - titan.SetTouchTriggers( false ) - titan.SetNoTarget( true ) - titan.UnsetUsable() // Disable titan embark - - titan.Hide() - - OnThreadEnd( - function() : ( titan ) - { - if ( !IsValid( titan ) ) - return - - // removed so that model highlight always works for you autotitan - // titan.DisableRenderAlways() - } - ) - - // based on "at_hotdrop_drop_2knee_turbo" - string animation = "bt_hotdrop_glitch_descent" - string postButtonPressSFX = "training_scr_titan_glitch_button_press" - string hotdropToGlitchSFX = "training_anim_glitch_scene" - - EmitSoundOnEntity( player, postButtonPressSFX ) - - float hotDropAnimDuration = titan.GetSequenceDuration( animation ) - - float extraSpawnDelay = 1.5 // bit of extra padding time for "Look up, to the sky" VO to sink in - extraSpawnDelay += Titanfall_GetHintVORemainingDuration() - - // Glitched hotdrop anim created by trimming the end from normal hotdrop anim (glitch starts just before the Titan hits the ground) - // - add this little bit back so the timer looks "correct" (longer than actual anim duration) - float arrivalTimerDuration = 0.7 - arrivalTimerDuration += (hotDropAnimDuration + extraSpawnDelay) // now add the rest of the normal delays before arrival - thread Training_DrawReplacementTitanLocation( player, origin, arrivalTimerDuration ) - - wait extraSpawnDelay - - titan.Show() - ShowName( titan ) - - Attachment result = titan.Anim_GetAttachmentAtTime( animation, "OFFSET", (hotDropAnimDuration - 0.1) ) - vector maxs = titan.GetBoundingMaxs() - vector mins = titan.GetBoundingMins() - int mask = titan.GetPhysicsSolidMask() - origin = ModifyOriginForDrop( origin, mins, maxs, result.position, mask ) - - titan.SetInvulnerable() //Make Titan invulnerable until bubble shield is up. Cleared in OnTitanHotdropImpact - titan.EnableRenderAlways() - - int teamNum = TEAM_UNASSIGNED - if ( IsValid( player ) ) - teamNum = player.GetTeam() - - vector fwdToPlayer = player.GetOrigin() - origin - vector facingAngles = VectorToAngles( fwdToPlayer ) - vector facingAngles2D = <facingAngles.x, facingAngles.y, 0> - angles = facingAngles2D - - //FadeOutSoundOnEntity( player, postButtonPressSFX, 1.0 ) - EmitSoundOnEntity( player, hotdropToGlitchSFX ) - - thread PlayAnimTeleport( titan, animation, origin, angles ) - wait hotDropAnimDuration - 0.1 - - titan.SetTouchTriggers( true ) - - thread TitanfallGlitch( player, titan, origin, angles ) -} - -void function Titanfall_ResetHintVOTimer() -{ - file.titanfallNagStartTime = Time() -} - -float function Titanfall_GetHintVORemainingDuration() -{ - if ( file.titanfallNagStartTime == -1 ) - return 0 - - float duration = TITANFALL_NAG_DURATION - (Time() - file.titanfallNagStartTime) - if ( duration < 0 ) - duration = 0 - - return duration -} - -bool function Titanfall_IsHintVOStillPlaying() -{ - return Titanfall_GetHintVORemainingDuration() >= 0 -} - -void function TitanfallGlitch( entity player, entity titan, vector origin, vector angles ) -{ - if ( Flag( "PodOutroStarted" ) ) - return - FlagEnd( "PodOutroStarted" ) - - player.EndSignal( "OnDestroy" ) - titan.EndSignal( "OnDestroy" ) - - titan.Signal( "glitch_start" ) - FlagSet( "TitanfallGlitchStart" ) - - if ( IsValid( file.titanTwin ) ) - file.titanTwin.Destroy() - - entity titanTwin = CreatePropScript( BUDDY_MODEL, titan.GetOrigin(), titan.GetAngles() ) - file.titanTwin = titanTwin - vector twinOrigin = TitanfallGlitch_WorldChange_GetOtherWorldPos( origin, true ) - - array<entity> sceneTitans = [ titan, titanTwin ] - - // idle on last frame of descent anim - titanTwin.Anim_Stop() - titan.Anim_Stop() - string endIdleAnim = GetDefaultTitanfallGlitchAnim() - thread PlayAnimTeleport( titanTwin, endIdleAnim, twinOrigin, angles ) - thread PlayAnimTeleport( titan, endIdleAnim, origin, angles ) - - // DEPRECATED no more glitchy anims - // do this on the hotdropping titan to blend out of the hotdrop better (but makes the proxy on the client out of sync) - // - in the future, need to play all the hotdrop anims on the proxy as well, to let it blend the same - //thread PlayAnim( titan, endIdleAnim, origin, angles, 0.1 ) - - // START GLITCH SEQUENCE - - // setup for client extra flicker - titan.Hide() - titanTwin.Hide() - int eHandle_titan = titan.GetEncodedEHandle() - int eHandle_twin = titanTwin.GetEncodedEHandle() - Remote_CallFunction_Replay( player, "ScriptCallback_TitanfallGlitch_ExtraFlicker", eHandle_titan ) - Remote_CallFunction_Replay( player, "ScriptCallback_TitanfallGlitch_ExtraFlicker", eHandle_twin, true ) - SetGlobalNetBool( "titanGlitch_extraFlicker", true ) // makes him flicker until the world starts changing - - // DEPRECATED Not doing the huge anim moves might work better for the glitch moment, trying it out - //thread TitanfallGlitch_CycleTitanGlitchAnims_OnWorldChange( player, titan, titanTwin, origin, twinOrigin, angles ) - - float screenFXTime = 4.5 - float screenFXStartDelay = 0.1 - thread StartGlitchScreenFX_Delayed( player, screenFXTime, screenFXStartDelay ) - - // FIRST IMPACT - float firstShakeDuration = 3.0 - - float shakeAmplitude = 14.0 - float screenBlurFrac = 0.25 - SimpleScreenShake( player, firstShakeDuration, shakeAmplitude, screenBlurFrac ) - - // juice it with extra rumble - // note- this is not juicing it as much as I would expect... even cranking the amplitude doesn't really work that well - float rumbleAmplitude = 50.0 - float rumbleFrequency = 170 - float rumbleDuration = 4.5 - CreateShakeRumbleOnly( player.GetOrigin(), rumbleAmplitude, rumbleFrequency, rumbleDuration ) - - // let the titan idle for a moment - float postDescentIdleTime = 1.0 - wait postDescentIdleTime - - float firstShakeDuration_remaining = firstShakeDuration - postDescentIdleTime - // DEPRECATED trying without world changes - //thread TitanfallGlitch_PlayerWorldChange( player, firstShakeDuration_remaining * 0.9, 0.0 ) - - wait firstShakeDuration_remaining - - /* DEPRECATED don't need smaller shakes now that the scene only lasts a short time - printt( "FIRST IMPACT DONE") - - // LOOPING SMALLER IMPACTS - float shakeDuration_min = 2.5 - float shakeDuration_max = 3.0 - shakeAmplitude = 5.5 - screenBlurFrac = 0.6 - while ( 1 ) - { - float shakeDuration = RandomFloatRange( shakeDuration_min, shakeDuration_max ) - - SimpleScreenShake( player, shakeDuration, shakeAmplitude, screenBlurFrac ) - thread TitanfallGlitch_PlayerWorldChange( player, shakeDuration * 0.85, shakeDuration * 0.1 ) - - wait shakeDuration - } - */ -} - -void function StartGlitchScreenFX_Delayed( entity player, float screenFXTime, float delay ) -{ - if ( Flag( "PodOutroStarted" ) ) - return - FlagEnd( "PodOutroStarted" ) - - EndSignal( player, "OnDestroy" ) - - if ( delay > 0 ) - wait delay - - Remote_CallFunction_Replay( player, "ScriptCallback_PodGlitch_PlayerScreenFX", screenFXTime ) -} - -const float GLITCH_WORLD_CHANGE_WAIT_MIN = 0.1 -const float GLITCH_WORLD_CHANGE_WAIT_MAX = 0.35 -const float GLITCH_WORLD_CHANGE_MINWAIT_FOR_EXTRA_FLICKER = 0.25 - -void function TitanfallGlitch_CycleTitanGlitchAnims_OnWorldChange( entity player, entity mainTitan, entity titanTwin, vector origin, vector twinOrigin, vector angles, float delay = 0.0 ) -{ - player.EndSignal( "OnDestroy" ) - mainTitan.EndSignal( "OnDestroy" ) - titanTwin.EndSignal( "OnDestroy" ) - - array<entity> sceneTitans = [ mainTitan, titanTwin ] - - OnThreadEnd( - function() : ( player, sceneTitans ) - { - if ( IsValid( player ) ) - { - FlagClear( "PlayerWorldChangeThread" ) - SetGlobalNetBool( "titanGlitch_extraFlicker", false ) - } - - foreach ( titan in sceneTitans ) - if ( IsValid( titan ) ) - titan.Show() - } - ) - - if ( delay > 0 ) - wait delay - - array<string> titanAnims = GetTitanfallGlitchAnims() - array<string> twinAnims = GetTitanfallGlitchTwinAnims() - Assert( titanAnims.len() == twinAnims.len() ) - int animIdx = GetGlobalNetInt( "titanfallGlitchAnimIdx" ) - - while ( 1 ) - { - table result = WaitSignal( player, "Glitch_WorldChanging_Zen", "Glitch_WorldChanging_NonZen" ) - string signal = expect string( result.signal ) - - float worldChangeDuration = expect float( result.postChangeWait ) - - //printt( "titan anim:", titanAnims[animIdx] ) - - mainTitan.Anim_Stop() - titanTwin.Anim_Stop() - thread PlayAnimTeleport( mainTitan, titanAnims[animIdx], origin, angles ) - thread PlayAnimTeleport( titanTwin, twinAnims[animIdx], twinOrigin, angles ) - - animIdx++ - if ( animIdx >= titanAnims.len() ) - animIdx = 0 - - SetGlobalNetInt( "titanfallGlitchAnimIdx", animIdx ) - - // update flicker settings & show/hide server versions of the titans - if ( signal == "Glitch_WorldChanging_Zen" ) - { - // only do extra flicker if a longer world change pause is happening - if ( worldChangeDuration >= GLITCH_WORLD_CHANGE_MINWAIT_FOR_EXTRA_FLICKER ) - { - SetGlobalNetBool( "titanGlitch_extraFlicker", true ) - - foreach ( titan in sceneTitans ) - titan.Hide() - } - } - else if ( signal == "Glitch_WorldChanging_NonZen" ) - { - SetGlobalNetBool( "titanGlitch_extraFlicker", false ) - - foreach ( titan in sceneTitans ) - titan.Show() - } - else - { - Assert( false, "Couldn't find signal: " + signal ) - } - } -} - - -void function TitanfallGlitch_PlayerWorldChange( entity player, float duration, float delay = 0.0 ) -{ - if ( Flag( "PodOutroStarted" ) ) - return - FlagEnd( "PodOutroStarted" ) - - EndSignal( player, "OnDestroy" ) - - if ( delay > 0 ) - wait delay - - FlagWaitClear( "PlayerWorldChangeThread" ) - FlagSet( "PlayerWorldChangeThread" ) - - OnThreadEnd( - function() : ( player ) - { - if ( IsValid( player ) ) - FlagClear( "PlayerWorldChangeThread" ) - } - ) - - bool isInZenWorld = true - - float endTime = Time() + duration - - float minWait = GLITCH_WORLD_CHANGE_WAIT_MIN - float maxWait = GLITCH_WORLD_CHANGE_WAIT_MAX - - while ( 1 ) - { - // at end time, make sure player pos resets back to zen world before breaking - if ( Time() >= endTime && isInZenWorld ) - break - - vector newpos = TitanfallGlitch_WorldChange_GetOtherWorldPos( player.GetOrigin(), isInZenWorld ) - - float postChangeWait - string changeSignal - entity newSkyCam - - if ( isInZenWorld ) - { - // Switch to non zen world - changeSignal = "Glitch_WorldChanging_NonZen" - postChangeWait = minWait // always wait min time in non zen world - - newSkyCam = file.skycam_glitch - isInZenWorld = false - } - else - { - // Switch back to zen world - postChangeWait = RandomFloatRange( minWait, maxWait ) - changeSignal = "Glitch_WorldChanging_Zen" - - newSkyCam = file.skycam_default - isInZenWorld = true - } - - table<string,float> extraInfo = {} - extraInfo["postChangeWait"] <- postChangeWait - Signal( player, changeSignal, extraInfo ) - - player.SetSkyCamera( newSkyCam ) - player.SetOrigin( newpos ) - - wait postChangeWait - } -} - - -vector function TitanfallGlitch_WorldChange_GetOtherWorldPos( vector currentPos, bool startInZenWorld ) -{ - entity zenEnt = GetEntByScriptName( "titan_glitch_swap_ref1" ) - entity nonZenEnt = GetEntByScriptName( "titan_glitch_swap_ref2" ) - Assert( zenEnt && nonZenEnt ) - vector zenPos = zenEnt.GetOrigin() - vector nonZenPos = nonZenEnt.GetOrigin() - - float offsetX - float offsetY - float offsetZ - float newPosX - float newPosY - float newPosZ - - if ( startInZenWorld ) - { - offsetX = currentPos.x - zenPos.x - offsetY = currentPos.y - zenPos.y - offsetZ = currentPos.z - zenPos.z - - newPosX = nonZenPos.x + offsetX - newPosY = nonZenPos.y + offsetY - newPosZ = nonZenPos.z + offsetZ - } - else - { - offsetX = currentPos.x - nonZenPos.x - offsetY = currentPos.y - nonZenPos.y - offsetZ = currentPos.z - nonZenPos.z - - newPosX = zenPos.x + offsetX - newPosY = zenPos.y + offsetY - newPosZ = zenPos.z + offsetZ - } - - vector newPos = < newPosX, newPosY, newPosZ > - return newPos -} - - -void function Training_DrawReplacementTitanLocation( entity player, vector origin, float delay ) -{ - float endTime = Time() + delay - - player.SetHotDropImpactDelay( endTime ) - Remote_CallFunction_Replay( player, "ServerCallback_ReplacementTitanSpawnpoint", origin.x, origin.y, origin.z, endTime ) - player.WaitSignal( "OnDeath" ) -} - - -// =================================== -// ============ POD OUTRO ============ -// =================================== -void function Training_Setup_PodOutro( entity player ) -{ -} - -void function Training_Skipped_PodOutro( entity player ) -{ - Training_EnvArtColorCorrection_SetEnabled( false ) - SetDoF_Hangar( player ) - - Objective_Clear() - - FlagSet( "PodOutroStarted" ) - FlagSet( "SimPodShutdown_LoudspeakerVO_Done" ) -} - -#if DEV -// bare bones start in pod -void function DEV_PodOutro( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - TakeAllWeapons( player ) - - player.SetExtraWeaponMods( [ "low_ammo_disable" ] ) - SetWeaponHUDEnabled( player, false ) - - Training_EnvArtColorCorrection_SetEnabled( false ) - SetDoF_Hangar( player ) - - thread MeetOG_BackgroundSkits( player ) - - entity pod = file.trainingPod - - TrainingPod_PlayerSequence_DoorsOpenIdle( player, false ) - - // anim starts at a slightly different spot - player.SetOrigin( < 10564, -10235, -6056.9 > ) - player.SetAngles( < -6, 90, 0 > ) - - WaitForever() -} -#endif //DEV - -void function Training_PodOutro( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - Objective_Clear() - CheckPoint_Silent() - - entity pod = file.trainingPod - - FlagSet( "PodOutroStarted" ) - - OnThreadEnd( - function() : ( player, pod ) - { - if ( IsValid( player ) ) - { - //StopSoundOnEntity( player, "NPE_Scr_SimPod_End" ) - - // Not sure if we need any of this - //player.Anim_Stop() - //ClearAnimViewEntity( player ) - //player.ClearParent() - //player.UnforceStand() - } - - if ( IsValid ( pod ) ) - { - // Not sure if we need any of this - //pod.Anim_Stop() - //thread TrainingPod_ResetLaserEmitterRotation( pod ) - //thread TrainingPod_KillLasers( pod ) - //thread TrainingPod_KillGlowFX( pod ) - //TrainingPod_KillInteriorDLights() - } - } - ) - - // Have to do this first so the anim starts centered on the ref attachment angles - string podAttach = "REF" - int attachID = pod.LookupAttachment( podAttach ) - vector podRefOrg = pod.GetAttachmentOrigin( attachID ) - vector podRefAng = pod.GetAttachmentAngles( attachID ) - player.SetOrigin( podRefOrg ) - player.SetAngles( podRefAng ) - - player.ForceStand() - - TakeAllWeapons( player ) - - // start closed idle - FirstPersonSequenceStruct playerSequence - playerSequence.blendTime = 0.0 - playerSequence.attachment = podAttach - playerSequence.firstPersonAnimIdle = "ptpov_trainingpod_idle" - playerSequence.thirdPersonAnimIdle = "pt_trainingpod_idle" - playerSequence.viewConeFunction = TrainingPod_ViewConeLock_Strict // so player can't move camera under the pod shutdown screen - playerSequence.renderWithViewModels = true - - FirstPersonSequenceStruct podSequence - podSequence.blendTime = 0.0 - podSequence.thirdPersonAnimIdle = "trainingpod_doors_close_idle" - podSequence.renderWithViewModels = true - - thread FirstPersonSequence( playerSequence, player, pod ) - thread FirstPersonSequence( podSequence, pod ) - - thread CadillacMoment_MeetOG( player ) - - //thread PodOutro_ScreenShake( player ) - - Training_EnvArtColorCorrection_SetEnabled( false ) - SetDoF_Hangar( player ) - - // show the "pod shutdown screen" - float shutdownScreenWait = 7.0 - float screenFadeWait = 7.0 - ScreenFade( player, 0, 0, 0, 255, 0, screenFadeWait, FFADE_OUT | FFADE_STAYOUT ) - Remote_CallFunction_Replay( player, "ScriptCallback_SimPodShutdownScreen", shutdownScreenWait ) - - thread SimPodShutdown_Dialogue( player ) - - // HACK, need to wait a bit so player moves into pod before initing shutdown sequence - // - otherwise, interior emitter angle setup math vs player eye position will crash the game - float waitForPlayerToBeMoved = 1.0 - wait waitForPlayerToBeMoved - - float shutdownSequence_waitBeforeAnimStart = 10.0 - thread TrainingPod_Interior_ShutdownSequence( player, shutdownSequence_waitBeforeAnimStart ) - - wait screenFadeWait - waitForPlayerToBeMoved - - // HACK reparent the emitters so they look correct, I didn't expect to have to do this - TrainingPod_SnapLaserEmittersToAttachPoints() - - // Transition screen FX - thread PlayFXOnEntity( FX_POD_SCREEN_OUT, player ) - - float fadeInFromShutdownScreenTime = 0.2 - ScreenFade( player, 0, 0, 0, 255, fadeInFromShutdownScreenTime, 1, FFADE_IN | FFADE_PURGE ) - wait fadeInFromShutdownScreenTime - - TrainingPod_ViewConeLock_PodClosed( player ) - - // start shutdown sequence - // HACK- eventually one sound will cover the whole sequence - thread HACK_DelayedShutdownSequenceSFX( player, 3.0 ) - - player.Signal( "TrainingPod_BeginInteriorShutdown" ) - wait shutdownSequence_waitBeforeAnimStart - - FirstPersonSequenceStruct playerSequence_podOpens - playerSequence_podOpens.blendTime = 0.25 - playerSequence_podOpens.attachment = podAttach - playerSequence_podOpens.firstPersonAnim = "ptpov_trainingpod_doors_open" - playerSequence_podOpens.firstPersonAnimIdle = "ptpov_trainingpod_idle" - playerSequence_podOpens.thirdPersonAnim = "pt_trainingpod_doors_open" - playerSequence_podOpens.thirdPersonAnimIdle = "pt_trainingpod_idle" - playerSequence_podOpens.viewConeFunction = TrainingPod_ViewConeLock_SemiStrict - playerSequence_podOpens.renderWithViewModels = true - - FirstPersonSequenceStruct podSequence_podOpens - podSequence_podOpens.blendTime = 0.25 - podSequence_podOpens.thirdPersonAnim = "trainingpod_doors_open" - podSequence_podOpens.thirdPersonAnimIdle = "trainingpod_doors_open_idle" - podSequence_podOpens.renderWithViewModels = true - - thread TrainingPod_TurnOnInteriorDLights_Delayed( player, 1.5 ) - - thread FirstPersonSequence( podSequence_podOpens, pod ) - thread FirstPersonSequence( playerSequence_podOpens, player, pod ) - - wait 2.1 // wait until scene starts animating for Meet OG -} - -void function HACK_DelayedShutdownSequenceSFX( entity player, float delayTime ) -{ - EndSignal( player, "OnDestroy" ) - - wait delayTime - EmitSoundOnEntityOnlyToPlayerWithSeek( player, player, "NPE_Scr_SimPod_End", 0.7 ) -} - -void function PodOutro_ScreenShake( entity player ) -{ - if ( Flag( "MeetOG_StartScene" ) ) - return - FlagEnd( "MeetOG_StartScene" ) - - player.EndSignal( "OnDestroy" ) - - float shakeDuration = 2.0 - float shakeAmplitude = 0.2 - float screenBlurFrac = 0.0 - float shakeDelayMin = 1.75 - float shakeDelayMax = 2.25 - while ( 1 ) - { - SimpleScreenShake( player, shakeDuration, shakeAmplitude, screenBlurFrac ) - wait shakeDuration - (shakeDuration * 0.25) // HACK shake dies down - wait RandomFloatRange( shakeDelayMin, shakeDelayMax ) - } -} - -void function SimPodShutdown_LoudspeakerVO( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - wait 4.0 // wait for "I'm pulling you out" - - // "Powering down all non-essential systems." - waitthread PlayLoudspeakerVO( "outro_01_1" ) - - // "Prepare for Typhon atmospheric entry in less than three minutes." - //waitthread PlayLoudspeakerVO( "outro_01" ) - - wait 7.0 - - // "All personnel to battle stations." - waitthread PlayLoudspeakerVO( "outro_01_2" ) - - // "This is not a drill." - waitthread PlayLoudspeakerVO( "outro_01_3" ) - - FlagSet( "SimPodShutdown_LoudspeakerVO_Done" ) -} - -void function SimPodShutdown_Dialogue( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - thread SimPodShutdown_LoudspeakerVO( player ) - - Assert( IsValid( file.ogPilot ), "Can't find scene entity ogPilot" ) - - // "Alright Rifleman, sounds like it's about to hit the fan." - waitthread PlayDialogue( "og_hit_the_fan", file.ogPilot ) - - // "I'm pulling you out." - waitthread PlayDialogue( "og_pulling_you_out", file.ogPilot ) - - wait 2.0 - - // "Cooper! Ready up!" - waitthread PlayDialogue( "grunt_closed_pod_yell_at_player", file.ogPilot ) // HACK play it off OG until the animation idle is legit - - // "Easy Cole, he just left VR. Needs a minute to decompress. He'll be ready to go... trust me." - waitthread PlayDialogue( "og_closed_pod_respond_to_grunt", file.ogPilot ) - - // "Yes sir." - waitthread PlayDialogue( "grunt_yes_sir", file.ogPilot ) -} - -#if DEV -void function shutdownscreentest( float duration = 5.0 ) -{ - entity player = file.player - EndSignal( player, "OnDestroy" ) - - float fadeTime = 0.2 - - ScreenFade( player, 0, 0, 0, 255, fadeTime, duration, FFADE_OUT | FFADE_STAYOUT ) - Remote_CallFunction_Replay( player, "ScriptCallback_SimPodShutdownScreen", duration ) - wait duration - ScreenFade( player, 0,0,0, 255, fadeTime, fadeTime, FFADE_IN | FFADE_PURGE ) -} -#endif - - - -// ================================= -// ============ MEET OG ============ -// ================================= -void function Training_Setup_MeetOG( entity player ) -{ - TakeAllWeapons( player ) - - thread CadillacMoment_MeetOG( player ) - TrainingPod_PlayerSequence_DoorsOpenIdle( player ) - - wait 0.2 -} - -void function Training_Skipped_MeetOG( entity player ) -{ - // settings for checkpoints after the normal level progression - SetDoF_Default( player ) - player.SetExtraWeaponMods( [] ) // turn off low_ammo_disable - SetWeaponHUDEnabled( player, true ) -} - -void function Training_MeetOG( entity player ) -{ - thread MeetOG_BackgroundSkits( player ) - - FlagSet( "MeetOG_StartScene" ) - - thread MeetOG_ControllerRumble( player ) - - FlagWait( "CadillacMoment_MeetOG_StartFadeOut" ) - - UnlockAchievement( player, achievements.COMPLETE_TRAINING ) - - // Free SP trial? Load Beacon next. - if( Script_IsRunningTrialVersion() ) - { - thread FreeTrial_OutroPopup( player, 2.5 ) - PickStartPoint( "sp_beacon", "Level Start" ) - } - else - { - thread OutroDifficultyPopup( player, 2.5 ) - - // load next level - // NOTE this does a screen fade already - PickStartPoint( "sp_crashsite", "LevelStart" ) - } - - // don't ever progress from here to the dev functions beyond - WaitForever() -} - -void function FreeTrial_OutroPopup( entity player, float delay ) -{ - EndSignal( player, "OnDestroy" ) - wait delay - - Remote_CallFunction_UI( player, "ScriptCallback_Training_FreeTrialMessage" ) -} - -void function OutroDifficultyPopup( entity player, float delay ) -{ - EndSignal( player, "OnDestroy" ) - wait delay - - Remote_CallFunction_UI( player, "ScriptCallback_Training_SelectSPDifficulty" ) -} - -// can't do screen shake for this part because it looks bad (not connected) when player view is 1P animating while parented to the pod -void function MeetOG_ControllerRumble( entity player ) -{ - player.EndSignal( "OnDestroy" ) - FlagEnd( "CadillacMoment_MeetOG_StartFadeOut" ) - - float shakeDuration = 2.8 - float shakeAmplitudeMin = 13.5 - float shakeAmplitudeMax = 14.5 - float frequency = 155 - float shakeDelayMin = 4.0 - float shakeDelayMax = 7.0 - while ( 1 ) - { - float amplitude = RandomFloatRange( shakeAmplitudeMin, shakeAmplitudeMax ) - - //vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 - CreateAirShakeRumbleOnly( player.GetOrigin(), amplitude, frequency, shakeDuration ) - printt( "Shake Rumble:", amplitude ) - wait shakeDuration * 0.75 // HACK shake dies down pretty early - - wait RandomFloatRange( shakeDelayMin, shakeDelayMax ) - } -} - -void function CadillacMoment_MeetOG( entity player ) -{ - thread MeetOG_LoudspeakerVO( player ) - - int friendlyTeam = player.GetTeam() - - entity animref = file.animref_hangar - vector animrefOrigin = animref.GetOrigin() - vector animrefAngles = animref.GetAngles() - vector btSpawnOrg = <0,0,0> // to avoid red text errors about BT spawning in solid - - entity animEnt = CreateScriptMover( animrefOrigin, animrefAngles ) - - // Spawn scene actors - entity og = Training_SpawnOGPilot( animref ) - Training_OGPilot_SetHelmetOn( og, false ) - SetTeam( og, TEAM_SPECTATOR ) // turn off his glowy bits so they're accentuated when helmet turns on later - - entity anderson = CreateSoldier( friendlyTeam, animrefOrigin, animrefAngles ) - DispatchSpawn( anderson ) - anderson.SetModel( ANDERSON_PILOT_MODEL ) - anderson.SetTitle( "#TRAINING_ANDERSON_NAME" ) - //ShowName( anderson ) - HideName( anderson ) - - entity redshirt = CreateSoldier( friendlyTeam, animrefOrigin, animrefAngles ) - DispatchSpawn( redshirt ) - redshirt.SetModel( TEAM_MIL_GRUNT_MODEL_LMG ) - redshirt.SetTitle( "#CPT_COLE" ) - //ShowName( redshirt ) - HideName( redshirt ) - - TitanLoadoutDef loadout = GetTitanLoadoutForCurrentMap() - entity bt = CreateAutoTitanForPlayer_FromTitanLoadout( player, loadout, btSpawnOrg, animrefAngles ) - SetSpawnOption_AISettings( bt, "npc_titan_buddy" ) - bt.kv.spawnflags = SF_NPC_ALLOW_SPAWN_SOLID - DispatchSpawn( bt ) - FreeAutoTitan( bt ) // HACK this disables the worldspace BT locator icon - TakeAllWeapons( bt ) - - array<entity> actors = [ player, bt, og, anderson, redshirt ] - - // Setup scene props - - entity ogHelmet = CreatePropDynamic( OG_PILOT_HELMET_MODEL ) - ogHelmet.DisableHibernation() - file.ogHelmet = ogHelmet - - string knifeTag = "KNIFE" - int knifeTagID = og.LookupAttachment( knifeTag ) - entity dataKnife = CreatePropScript( DATA_KNIFE_MODEL, og.GetAttachmentOrigin( knifeTagID ), og.GetAttachmentAngles( knifeTagID ) ) - dataKnife.DisableHibernation() - dataKnife.SetParent( og, knifeTag, false, 0.0 ) - - asset btWeaponModel = GetWeaponInfoFileKeyFieldAsset_Global( "mp_titanweapon_xo16_shorty", "playermodel" ) - Assert( btWeaponModel != $"" ) - entity btWeapon = CreatePropDynamic( btWeaponModel ) - btWeapon.SetParent( bt, "PROPGUN" ) - - string gruntRifleName = "mp_weapon_rspn101" - string andersonWeaponName = "mp_weapon_car" - asset gruntRifleModel = GetWeaponInfoFileKeyFieldAsset_Global( gruntRifleName, "playermodel" ) - asset andersonWeaponModel = GetWeaponInfoFileKeyFieldAsset_Global( andersonWeaponName, "playermodel" ) - asset ogWeaponModel = GetWeaponInfoFileKeyFieldAsset_Global( OG_WEAPON, "playermodel" ) - Assert( gruntRifleModel != $"" ) - Assert( andersonWeaponModel != $"" ) - Assert( ogWeaponModel != $"" ) - - entity ogWeapon = CreatePropDynamic( ogWeaponModel ) - ogWeapon.DisableHibernation() - ogWeapon.SetParent( og, "PROPGUN" ) - - entity andersonWeapon = CreatePropDynamic( andersonWeaponModel ) - andersonWeapon.DisableHibernation() - andersonWeapon.SetParent( anderson, "PROPGUN" ) - - entity redshirtWeapon = CreatePropDynamic( gruntRifleModel ) - redshirtWeapon.DisableHibernation() - redshirtWeapon.SetParent( redshirt, "PROPGUN" ) - - array<entity> props = [ btWeapon, redshirtWeapon, andersonWeapon, ogWeapon, ogHelmet, dataKnife ] - - OnThreadEnd( - function() : ( actors, props, animEnt ) - { - foreach ( weapon in props ) - { - if ( IsValid( weapon ) ) - { - weapon.ClearParent() - weapon.Destroy() - } - } - - foreach ( actor in actors ) - { - if ( IsValid( actor ) ) - actor.ClearParent() - - if ( IsInvincible( actor ) ) - ClearInvincible( actor ) - - if ( !actor.IsPlayer() ) - actor.Destroy() - } - - if ( IsValid( animEnt ) ) - animEnt.Destroy() - } - ) - - foreach ( guy in actors ) - { - if ( guy.IsPlayer() ) - continue - - MakeInvincible( guy ) - guy.SetEfficientMode( true ) - Highlight_ClearFriendlyHighlight( guy ) - } - - string anim_og = "pt_intro_scene_OG" - string anim_og_helmet = "helmet_intro_scene_OG" - string anim_bt = "BT_intro_scene_OG" - string anim_anderson = "pt_intro_scene_Anderson" - string anim_redshirt = "pt_intro_scene_grunt" - - string anim_og_idle = "pt_intro_scene_OG_idle" - string anim_og_helmet_idle = "helmet_intro_scene_OG_idle" - string anim_bt_idle = "BT_intro_scene_OG_idle" - string anim_anderson_idle = "pt_intro_scene_Anderson_idle" - string anim_redshirt_idle = "pt_intro_scene_grunt_idle" - - thread PlayAnimTeleport( og, anim_og_idle, animEnt ) - thread PlayAnimTeleport( ogHelmet, anim_og_helmet_idle, animEnt ) - thread PlayAnimTeleport( bt, anim_bt_idle, animEnt ) - thread PlayAnimTeleport( anderson, anim_anderson_idle, animEnt ) - thread PlayAnimTeleport( redshirt, anim_redshirt_idle, animEnt ) - - FlagWait( "MeetOG_StartScene" ) - printt( "STARTING ANIMS: MEET OG" ) - - foreach ( guy in actors ) - guy.Anim_Stop() - - AddAnimEvent( og, "helmet_on", AnimEventCallback_MeetOG_HelmetTurnsOn ) - - thread PlayAnimTeleport( og, anim_og, animEnt ) - thread PlayAnimTeleport( ogHelmet, anim_og_helmet, animEnt ) - thread PlayAnimTeleport( bt, anim_bt, animEnt ) - thread PlayAnimTeleport( anderson, anim_anderson, animEnt ) - thread PlayAnimTeleport( redshirt, anim_redshirt, animEnt ) - - player.Anim_Stop() - - // give player weapon for the toss moment - entity fpProxy = player.GetFirstPersonProxy() - int attachID = fpProxy.LookupAttachment( "PROPGUN" ) - asset playerWeaponModel = GetWeaponInfoFileKeyFieldAsset_Global( "mp_weapon_vinson", "playermodel" ) - entity playerWeapon = CreatePropDynamic( playerWeaponModel, fpProxy.GetAttachmentOrigin( attachID ), fpProxy.GetAttachmentAngles( attachID ) ) - file.playerAnimWeapon = playerWeapon - playerWeapon.DisableHibernation() - playerWeapon.SetParent( fpProxy, "PROPGUN", false, 0.0 ) - - AddAnimEvent( player, "gun_catch", AnimEventCallback_MeetOG_PlayerCatchesWeapon ) - - FirstPersonSequenceStruct playerSequence_meetOG - - float viewAnimDelay = 4.0 - //playerSequence_meetOG.setInitialTime = viewAnimDelay // DEPRECATED animators will adjust so start position is good again} - playerSequence_meetOG.blendTime = 0.0 - playerSequence_meetOG.teleport = false - playerSequence_meetOG.attachment = "REF" - playerSequence_meetOG.firstPersonAnim = "pov_intro_scene_player" - playerSequence_meetOG.thirdPersonAnim = "pt_intro_scene_player" - playerSequence_meetOG.viewConeFunction = TrainingPod_ViewConeLock_SemiStrict - playerSequence_meetOG.renderWithViewModels = true - - // HACK delay sequence so it transitions better from previous anim - TrainingPod_ViewConeLock_SemiStrict( player ) // set this to cover any time between viewmodel anims - thread FirstPersonSequence_Delayed( viewAnimDelay, playerSequence_meetOG, player, animEnt ) - //thread FirstPersonSequence( playerSequence_meetOG, player, animEnt ) - - // gradual DOF racking during the scene - RackDoF_NearDepth( player, 0, 22, 12.0 ) - RackDoF_FarDepth( player, 350, 950, 20.0 ) - - // find longest anim duration - array<string> sceneAnims = [ anim_og, anim_bt, anim_anderson, anim_redshirt ]//, "pt_intro_scene_player" ] - float sceneDuration = -1 - foreach ( anim in sceneAnims ) - { - entity animActor = og - if ( anim.find( "BT_") != null ) - animActor = bt - else if ( anim.find( "_player") != null ) - animActor = player - - float duration = animActor.GetSequenceDuration( anim ) - if ( duration > sceneDuration ) - sceneDuration = duration - } - Assert( sceneDuration > 0 ) - - float fadeTime = SP_LEVEL_TRANSITION_FADETIME - - wait sceneDuration - fadeTime - FlagSet( "CadillacMoment_MeetOG_StartFadeOut" ) - - wait fadeTime - FlagSet( "CadillacMoment_MeetOG_Done" ) -} - -void function FirstPersonSequence_Delayed( float delay, FirstPersonSequenceStruct sequence, entity player, entity animEnt ) -{ - EndSignal( player, "OnDestroy" ) - - if ( delay > 0 ) - wait delay - - thread FirstPersonSequence( sequence, player, animEnt ) -} - -void function MeetOG_LoudspeakerVO( entity player ) -{ - EndSignal( player, "OnDestroy" ) - FlagWait( "SimPodShutdown_LoudspeakerVO_Done" ) - - array<string> aliases - // "Incoming hostile ship - Designation: IMS Malta. Battle stations." - aliases.append( "outro_08" ) - // "Caution - Fuel leak in Cargo Bay eighty - five. Activating airlock procedures." - aliases.append( "outro_12" ) - // "Titan bays two through five, drop clearance confirmed." - aliases.append( "outro_03" ) - // "All available medical personnel, report to Med Central for tasking." - aliases.append( "outro_05" ) - // "We need all Riflemen to docking bay four. Dropships standing by." - aliases.append( "outro_07" ) - // "Infantry teams Stork three, Elk four, Shark six, Badger one, prepare for emergency atmospheric drop sequence" - aliases.append( "outro_04" ) - // "Titan mech team - Rabbit six, prep the Vanguards." - aliases.append( "outro_06" ) - // "Infantry teams 2nd Militia Fusiliers, Raptor three, target the IMS Malta." - aliases.append( "outro_11" ) - // "Special Recon Squad deploy from Drop Bay thirty-seven - now." - aliases.append( "outro_10" ) - - thread LoopLoudspeakerVO( aliases ) -} - -void function AnimEventCallback_MeetOG_PlayerCatchesWeapon( entity player ) -{ - Assert( IsValid( file.playerAnimWeapon ) ) - file.playerAnimWeapon.RenderWithViewModels( true ) - - thread MeetOG_PlayerCatchesWeapon_RackNearDOF( player ) -} - -void function MeetOG_PlayerCatchesWeapon_RackNearDOF( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - wait 0.7 - - RackDOF_NearDepth_ToDefault( player, 1.5 ) - - wait 2.0 - - RackDoF_NearDepth( player, 0, 22, 1.25 ) -} - - -// ------ OG HELMET TURNING ON ------ -void function AnimEventCallback_MeetOG_HelmetTurnsOn( entity og ) -{ - thread MeetOG_HelmetTurnsOn( og ) -} - -// script MeetOG_HelmetTurnsOn( GetOGPilot() ) -void function MeetOG_HelmetTurnsOn( entity og ) -{ - entity og = file.ogPilot - entity ogHelmet = file.ogHelmet - EndSignal( og, "OnDestroy" ) - EndSignal( ogHelmet, "OnDestroy" ) - - // setting his team to friendly makes the helmet light up - if ( og.GetTeam() == TEAM_MILITIA ) - SetTeam( og, TEAM_SPECTATOR ) - - ogHelmet.Hide() - Training_OGPilot_SetHelmetOn( og, true ) - wait 0.2 - - SetTeam( og, TEAM_MILITIA ) - wait 0.1 - SetTeam( og, TEAM_SPECTATOR ) - wait 0.4 - SetTeam( og, TEAM_MILITIA ) - wait 0.1 - SetTeam( og, TEAM_SPECTATOR ) - wait 0.1 - SetTeam( og, TEAM_MILITIA ) -} - -#if DEV -void function MeetOG_HelmetTurnsOff( entity og ) -{ - entity og = file.ogPilot - entity ogHelmet = file.ogHelmet - - if ( og.GetTeam() == TEAM_SPECTATOR ) - SetTeam( og, TEAM_MILITIA ) - - ogHelmet.Show() - Training_OGPilot_SetHelmetOn( og, false ) -} -#endif - - -// ------ POD OUTRO BACKGROUND SKITS ------ -void function MeetOG_BackgroundSkits( entity player, float delay = 0.0 ) -{ - string endFlag = "CadillacMoment_MeetOG_Done" - FlagEnd( endFlag ) - - if ( delay > 0 ) - wait delay - - printt( "!!!! Pod Outro Background Skits START !!!!" ) - - thread PodOutro_TitanRacks( endFlag ) - - thread PodOutro_Background_Runners( player ) - thread PodOutro_Foreground_Runners( player ) - - thread PodOutro_Background_ATC_Marvins() - - OnThreadEnd( - function() : () - { - DeleteAllSkitGuys() - } - ) - - WaitForever() -} - -void function PodOutro_TitanRacks( string endFlag ) -{ - FlagEnd( endFlag ) - - array<HangarTitanGroup> hangarTitanGroups - - OnThreadEnd( - function() : ( hangarTitanGroups ) - { - foreach ( group in hangarTitanGroups ) - HangarTitanGroup_Cleanup( group ) - } - ) - - float wait_earlyEnd = 24.0 - bool cleanupAfterAnim = false - - // --- BAY 1 --- - HangarTitanGroup bay1 - entity rack_bay1 = GetEntByScriptName( "hangar_titan_rack_1" ) - bay1.ref = rack_bay1 - bay1.rack = rack_bay1 - bay1.titan = GetEntByScriptName( "hangar_titan_1" ) - bay1.titanAnim = "bt_rack_prep_titan2" - bay1.rackAnim = "rack_rack_prep_rack2" - bay1.marvinAnim = "mv_rack_prep_marvin2" - bay1.pilotAnim = "pt_rack_prep_pilot2" - bay1.pilotModel = PILOT_MODEL_BAY1 - HangarTitanGroup_Init( bay1 ) - hangarTitanGroups.append( bay1 ) - thread HangarTitanGroup_Animate( bay1, endFlag, -1, cleanupAfterAnim ) - - - // --- BAY 2 --- - //thread PodOutro_TitanBoot( endFlag, 15.0 ) - - HangarTitanGroup bay2 - entity rack_bay2 = GetEntByScriptName( "hangar_titan_rack_2" ) - bay2.ref = rack_bay2 - bay2.rack = rack_bay2 - bay2.titan = GetEntByScriptName( "hangar_titan_2" ) - bay2.titanAnim = "bt_rack_prep_titan1" - bay2.rackAnim = "rack_rack_prep_rack1" - bay2.marvinAnim = "mv_rack_prep_marvin1" - bay2.pilotAnim = "pt_rack_prep_pilot1" - bay2.pilotModel = PILOT_MODEL_BAY2 - HangarTitanGroup_Init( bay2 ) - hangarTitanGroups.append( bay2 ) - waitthread HangarTitanGroup_Animate( bay2, endFlag, -1, cleanupAfterAnim ) -} - -void function PodOutro_TitanBoot( string endFlag, float delay ) -{ - FlagEnd( endFlag ) - - entity refTitan = GetEntByScriptName( "hangar_titan_2" ) - refTitan.Hide() - - vector refOrg = refTitan.GetOrigin() - vector refAng = refTitan.GetAngles() - refOrg += < -20, 40, 0> // HACK - refOrg = OriginToGround( refOrg ) - - entity animref = CreateScriptRef( refOrg, refAng ) - - entity titan = CreatePropScript( BUDDY_MODEL, refOrg, refAng ) - titan.DisableHibernation() - - AddAnimEvent( titan, "hatch_closed", TitanBoot_HatchClosed ) - entity cockpitLightFX = PlayFXOnEntity( FX_COCKPIT_LIGHT, titan, "HIJACK" ) - - SkitGuyInfo titanInfo = AddSkitGuy_Manually( "bootup_titan", titan ) - - SkitGuyInfo titanPilotInfo = SpawnSkitGuy( "bootup_pilot", "", animref.GetOrigin(), animref.GetAngles(), TEAM_MILITIA, "npc_soldier" ) - entity titanPilot = titanPilotInfo.guy - titanPilot.SetParent( titan, "HIJACK", false, 0.0 ) - titanPilot.MarkAsNonMovingAttachment() - - SkitGuyInfo crewInfo = SpawnSkitGuy( "bootup_crew", "", animref.GetOrigin(), animref.GetAngles(), TEAM_MILITIA, "npc_soldier_bish" ) - entity crew = crewInfo.guy - - OnThreadEnd( - function() : ( titanPilotInfo, crewInfo, titanInfo, cockpitLightFX, animref, refTitan ) - { - if ( IsValid_ThisFrame( cockpitLightFX ) ) - { - EntFireByHandle( cockpitLightFX, "Stop", "", 0, null, null ) - cockpitLightFX.ClearParent() - cockpitLightFX.Destroy() - } - - if ( IsAlive( titanInfo.guy ) ) - StopSoundOnEntity( titanInfo.guy, "Wargames_MCOR_TitanActivate" ) - - if ( IsValid( animref ) ) - animref.Destroy() - - DeleteSkitGuy( titanPilotInfo ) - DeleteSkitGuy( crewInfo ) - DeleteSkitGuy( titanInfo ) - - if ( IsValid( refTitan ) ) - refTitan.Show() - } - ) - - EmitSoundOnEntity( titan, "Wargames_MCOR_TitanActivate" ) - - string pilotAnim = "pt_titan_activation_pilot" - string pilotAnim_idle = "pt_titan_activation_pilot_idle" - string titanAnim = "at_titan_activation_training_meetOG" - string titanAnim_idle = "at_titan_activation_idle" - string titanAnim_endIdle = "at_titan_activation_training_meetOG_end_idle" - string crewAnim = "pt_titan_activation_crew" - string crewAnim_idle = "pt_titan_activation_crew_idle" - - if ( delay > 0 ) - { - thread PlayAnim( crew, crewAnim_idle, animref, null, 0.0 ) - thread PlayAnim( titan, titanAnim_idle, animref, null, 0.0 ) - titanPilot.Anim_ScriptedPlay( pilotAnim_idle ) - titanPilot.Anim_EnableUseAnimatedRefAttachmentInsteadOfRootMotion() - - wait delay - - titanPilot.Anim_Stop() - crew.Anim_Stop() - titan.Anim_Stop() - } - - titanPilot.Anim_ScriptedPlay( pilotAnim ) - titanPilot.Anim_EnableUseAnimatedRefAttachmentInsteadOfRootMotion() - thread PlayAnim( crew, crewAnim, animref, null, DEFAULT_SCRIPTED_ANIMATION_BLEND_TIME ) - thread PlayAnim( titan, titanAnim, animref, null, DEFAULT_SCRIPTED_ANIMATION_BLEND_TIME ) - - // end it early so he doesn't make stomping sounds when the pod is closed - //wait 15.0 - float duration = titan.GetSequenceDuration( titanAnim ) - wait duration - 0.1 - - printt( "Ending titan boot anim" ) - - thread PlayAnim( titan, titanAnim_endIdle, animref, null, DEFAULT_SCRIPTED_ANIMATION_BLEND_TIME ) - crew.Freeze() - - WaitForever() -} - -void function TitanBoot_HatchClosed( entity titan ) -{ - SkitGuyInfo info = GetSkitGuyInfo_ByName( "bootup_pilot" ) - DeleteSkitGuy( info ) -} - -void function PodOutro_Background_Runners( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - // right to left, across the whole hangar - array<Point> path1 = [] - ScriptedPath_AddPoint( path1, < 11080.5, -10017.2, -6079.97 >, < 0, 177.587, 0 > ) - ScriptedPath_AddPoint( path1, < 9619.14, -10004.8, -6079.97 >, < 0, 183.021, 0 > ) - - // right to left, starts closer to player POV - array<Point> path2 = [] - ScriptedPath_AddPoint( path2, < 11000, -9946.33, -6079.97 >, < 0, 177.587, 0 > ) - ScriptedPath_AddPoint( path2, < 9619.14, -10004.8, -6079.97 >, < 0, 183.021, 0 > ) - - wait 2.0 // wait for OG's first line to be nearly over - - printt( "BACKGROUND RUNNER GROUP 1" ) - - thread SpawnSkitGuy_AndRun( "runner_1_1", path2, 0.85, TEAM_MILITIA, "npc_soldier_specialist_militia", "mp_weapon_hemlok_smg" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_1_2", path2, 0.85, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - - wait 6.5 // wait until OG hands the eye to BT - - printt( "BACKGROUND RUNNER GROUP 2" ) - - thread SpawnSkitGuy_AndRun( "runner_2_1", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_2_2", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_shotgun" ) - - wait 4.5 // wait until OG is shaking Anderson's hand - - printt( "BACKGROUND RUNNER GROUP 3" ) - - thread SpawnSkitGuy_AndRun( "runner_3_1", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_3_2", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_shotgun" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_3_3", path2, 0.8, TEAM_MILITIA, "npc_soldier_specialist_militia", "mp_weapon_hemlok_smg" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_3_4", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - - wait 4.5 // wait until OG is mounting up - - printt( "BACKGROUND RUNNER GROUP 4" ) - - thread SpawnSkitGuy_AndRun( "runner_4_1", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_4_2", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_shotgun" ) - - wait 6.5 // wait until OG thumbs up - - printt( "BACKGROUND RUNNER GROUP 5" ) - - thread SpawnSkitGuy_AndRun( "runner_5_1", path2, 0.85, TEAM_MILITIA, "npc_soldier_specialist_militia", "mp_weapon_hemlok_smg" ) - wait 1.2 - thread SpawnSkitGuy_AndRun( "runner_5_2", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_5_3", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_shotgun" ) - wait 1.5 - thread SpawnSkitGuy_AndRun( "runner_5_4", path2, 0.85, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_5_3", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_shotgun" ) - wait 1.5 - thread SpawnSkitGuy_AndRun( "runner_5_4", path2, 0.85, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - - /* - wait 5.0 - - wait 4.0 - - thread SpawnSkitGuy_AndRun( "runner_2_1", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "runner_2_2", path2, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_shotgun" ) - */ -} - -void function PodOutro_Foreground_Runners( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - // right in front of pod - array<Point> pathClose = [] - ScriptedPath_AddPoint( pathClose, < 10728.2, -10194.2, -6055.97 >, < 0, 178.246, 0 > ) - ScriptedPath_AddPoint( pathClose, < 10236.8, -10180.3, -6055.97 >, < 0, 178.41, 0 > ) - - wait 11.0 // wait for OG to hand eyeball to BT - - thread SpawnSkitGuy_AndRun( "close_runner_1", pathClose, 0.7, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.2 - thread SpawnSkitGuy_AndRun( "close_runner_2", pathClose, 0.75, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - - wait 10.0 // wait for OG to start embarking BT - - thread SpawnSkitGuy_AndRun( "close_runner_4", pathClose, 0.75, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.3 - thread SpawnSkitGuy_AndRun( "close_runner_5", pathClose, 0.8, TEAM_MILITIA, "npc_soldier_specialist_militia", "mp_weapon_g2" ) - - wait 11 // wait for grunt to hand player the weapon - - thread SpawnSkitGuy_AndRun( "close_runner_10", pathClose, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.8 - thread SpawnSkitGuy_AndRun( "close_runner_11", pathClose, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) - wait 1.0 - thread SpawnSkitGuy_AndRun( "close_runner_12", pathClose, 0.8, TEAM_MILITIA, "npc_soldier", "mp_weapon_rspn101" ) -} - -void function PodOutro_Background_ATC_Marvins() -{ - // 1, 2, 3- matches titan bay numbering (right to left) - // plain numbers = farther from camera - // "a" variants = closer to camera - //SkitGuyInfo marvin_1 = SpawnSkitGuy( "atc_marvin_1", "", < 10600, -9841.5, -6079.97 >, < 0, -20, 0 >, TEAM_MILITIA ) - //thread ATC_Marvin_Think( marvin_1, "mv_trafic_controller_A", 0.0 ) - //SkitGuyInfo marvin_1a = SpawnSkitGuy( "atc_marvin_1a", "", < 10683.8, -10077.7, -6094.65 >, < 0, 20, 0 >, TEAM_MILITIA ) - //thread ATC_Marvin_Think( marvin_1a, "mv_trafic_controller_B", 0.0 ) - SkitGuyInfo marvin_2 = SpawnSkitGuy( "atc_marvin_2", "", < 10460.6, -9861.5, -6079.97 >, < 0, -30, 0 >, TEAM_MILITIA ) - thread ATC_Marvin_Think( marvin_2, "mv_trafic_controller_B", 0.25 ) - //SkitGuyInfo marvin_2a = SpawnSkitGuy( "atc_marvin_2a", "", < 10410.6, -10075.6, -6079.97 >, < 0, 30, 0 >, TEAM_MILITIA ) - //thread ATC_Marvin_Think( marvin_2a, "mv_trafic_controller_A", 0.25 ) - SkitGuyInfo marvin_3 = SpawnSkitGuy( "atc_marvin_3", "", < 10214.8, -9891.5, -6079.97 >, < 0, -10, 0 >, TEAM_MILITIA ) - thread ATC_Marvin_Think( marvin_3, "mv_trafic_controller_A", 0.5 ) - SkitGuyInfo marvin_3a = SpawnSkitGuy( "atc_marvin_3a", "", < 10207.5, -10079.4, -6079.97 >, < 0, 10, 0 >, TEAM_MILITIA ) - thread ATC_Marvin_Think( marvin_3a, "mv_trafic_controller_B", 0.5 ) -} - -void function ATC_Marvin_Think( SkitGuyInfo marvinInfo, string anim, float skipAheadTime = 0.0 ) -{ - entity marvin = marvinInfo.guy - - EndSignal( marvin, "OnDestroy" ) - - entity batonRight = CreatePropDynamic( SAFETY_BATON_MODEL ) - batonRight.SetOrigin( marvin.GetAttachmentOrigin( marvin.LookupAttachment( "R_HAND" ) ) ) - // HACK adjust the angles since the tags are different - vector angs = marvin.GetAttachmentAngles( marvin.LookupAttachment( "R_HAND" ) ) + Vector( 0, 0, 180 ) - batonRight.SetAngles( angs ) - batonRight.SetParent( marvin, "R_HAND", true ) - - entity batonLeft = CreatePropDynamic( SAFETY_BATON_MODEL ) - batonLeft.SetParent( marvin, "L_HAND" ) - - marvin.NotSolid() // don't want other NPCs to path around the ATC marvins - - array<entity> cleanupEnts = [ batonRight, batonLeft ] - - OnThreadEnd( - function() : ( cleanupEnts ) - { - foreach ( ent in cleanupEnts ) - { - if ( IsValid( ent ) ) - { - ent.ClearParent() - ent.Destroy() - } - } - } - ) - - WaitFrame() - marvinInfo.skitAnim = anim - /* - array<string> anims = [ "mv_trafic_controller_A", "mv_trafic_controller_B" ] - while( 1 ) - { - marvin.Anim_Play( anims.getrandom() ) - marvin.SetPlaybackRate( RandomFloatRange( 0.9, 1.0 ) ) - waitthread WaittillAnimDone( marvin ) - } - */ - marvin.SetPlaybackRate( RandomFloatRange( 0.9, 1.0 ) ) - SkitGuy_PlayAnim( marvinInfo, skipAheadTime ) - - WaitForever() -} - - - -// ======================================= -// ============ GAUNTLET MODE ============ -// ======================================= -// Just runs the Gauntlet over and over. - -void function Training_Setup_GauntletMode( entity player ) -{ - Training_EnvArtColorCorrection_SetEnabled( true ) - - entity ogStart = GetEntByScriptName( "og_near_leaderboard" ) - entity og = Training_SpawnOGPilot( ogStart ) - Training_OG_Idles( ogStart, "OG_Leaderboard_D_idle" ) - - //TeleportPlayerAndBT( "playerstart_gauntlet_challenge" ) - // HACK better start position - player.SetOrigin( < -5179, 279.129, 32.0313 > ) - player.SetAngles( < 0, 80.7242, 0 > ) -} - -void function Training_GauntletModeStart( entity player ) -{ - file.gauntletMode = true - - waitthread Training_GauntletChallenge( player ) -} - -void function GauntletMode_Finished( entity player ) -{ - Assert( file.gauntletMode ) - - float fadeTime = 3.0 - ScreenFade( player, 0, 0, 0, 255, fadeTime, -1, FFADE_OUT | FFADE_STAYOUT ) - wait fadeTime - - // Dump player back to menu - ClientCommand( player, "disconnect" ) - - WaitForever() // defensive- don't want any extra stuff happening right before level transition -} - - - -#if DEV -// =============================================== -// ============ RECORD GAUNTLET GHOSTS =========== -// =============================================== -void function TrainingGauntlet_RecordGhostStart_FirstRun( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_FIRSTRUN ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_WIP( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_WIP ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_01( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_01 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_02( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_02 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_03( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_03 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_04( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_04 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_05( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_05 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_06( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_06 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_07( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_07 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_08( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_08 ) -} - -void function TrainingGauntlet_RecordGhostStart_Challenge_09( entity player ) -{ - TrainingGauntlet_RecordGhost_CommonStart( player, GetTrainingGauntlet(), GHOST_NAME_CHAL_09 ) -} - - -void function TrainingGauntlet_RecordGhost_CommonStart( entity player, GauntletInfo gauntlet, string ghostFileName ) -{ - thread TrainingGauntlet_TeleportPlayerAtFinishLine( player ) - - TeleportPlayerAndBT( "gauntlet_startpoint" ) - - Gauntlet_Player_GhostRecordOrPlayback( player, gauntlet, ghostFileName ) - - while ( 1 ) - wait 5 -} -#endif //DEV - - - -// ============================================ -// ============ TRAINING POD STUFF ============ -// ============================================ -void function SetupTrainingPod() -{ - file.trainingPod = GetEntByScriptName( "training_pod" ) - file.trainingPod.DisableHibernation() - - TrainingPod_SetupInteriorDLights() - - array<string> laserAttachNames = [ "fx_laser_L", "fx_laser_R" ] - - foreach ( attachName in laserAttachNames ) - { - entity emitterEnt = CreateScriptMover( file.trainingPod.GetOrigin() ) - int attachID = file.trainingPod.LookupAttachment( attachName ) - vector attachAng = file.trainingPod.GetAttachmentAngles( attachID ) - - TrainingPod_LaserEmitter emitter - emitter.ent = emitterEnt - emitter.attachName = attachName - emitter.ogAng = attachAng - - file.trainingPodLaserEmitters.append( emitter ) - } - - // HACK we do this later as well to reset the emitter positions, so it's a separate function - TrainingPod_SnapLaserEmittersToAttachPoints() - - //file.trainingPod.SetAngles( Vector( 0, 109, 0 ) ) // these angles are a little better for seeing the room -} - -void function TrainingPod_SetupInteriorDLights() -{ - entity pod = file.trainingPod - - TrainingPod_dLightMapping m1 - m1.scriptAlias = "console1" - m1.fxName = FX_POD_DLIGHT_CONSOLE1 - m1.attachName = "light_console1" - file.trainingPodDLightMappings.append( m1 ) - - TrainingPod_dLightMapping m2 - m2.scriptAlias = "console2" - m2.fxName = FX_POD_DLIGHT_CONSOLE2 - m2.attachName = "light_console2" - file.trainingPodDLightMappings.append( m2 ) - - //TrainingPod_dLightMapping m3 - //m3.scriptAlias = "backlight_side_L" - //m3.fxName = FX_POD_DLIGHT_BACKLIGHT_SIDE - //m3.attachName = "light_back1" - //file.trainingPodDLightMappings.append( m3 ) - - //TrainingPod_dLightMapping m4 - //m4.scriptAlias = "backlight_side_R" - //m4.fxName = FX_POD_DLIGHT_BACKLIGHT_SIDE - //m4.attachName = "light_back2" - //file.trainingPodDLightMappings.append( m4 ) - - //TrainingPod_dLightMapping m5 - //m5.scriptAlias = "backlight_top" - //m5.fxName = FX_POD_DLIGHT_BACKLIGHT_TOP - //m5.attachName = "light_backtop" - //file.trainingPodDLightMappings.append( m5 ) -} - -void function TrainingPod_TurnOnInteriorDLights_Delayed( entity player, float delay ) -{ - player.EndSignal( "OnDestroy" ) - - wait delay - - TrainingPod_TurnOnInteriorDLight( "console1" ) - TrainingPod_TurnOnInteriorDLight( "console2" ) -} - -void function TrainingPod_TurnOnInteriorDLight( string scriptAlias ) -{ - entity pod = file.trainingPod - - int idx - TrainingPod_dLightMapping thisMapping - foreach ( mappingIdx, mapping in file.trainingPodDLightMappings ) - { - if ( mapping.scriptAlias == scriptAlias ) - { - thisMapping = mapping - idx = mappingIdx - break - } - } - - Assert ( thisMapping.scriptAlias != "", "Couldn't find pod dlight mapping for alias " + scriptAlias ) - - entity fxHandle = PlayLoopFXOnEntity( thisMapping.fxName, pod, thisMapping.attachName ) - file.trainingPodDLightMappings[ idx ].fxHandle = fxHandle -} - -void function TrainingPod_KillInteriorDLights_Delayed( entity player, float delay ) -{ - player.EndSignal( "OnDestroy" ) - - wait delay - - TrainingPod_KillInteriorDLights() -} - -void function TrainingPod_KillInteriorDLights() -{ - foreach ( idx, mapping in file.trainingPodDLightMappings ) - { - if ( !IsValid_ThisFrame( mapping.fxHandle ) ) - continue - - KillFX( mapping.fxHandle ) - - file.trainingPodDLightMappings[ idx ].fxHandle = null - } -} - -void function TrainingPod_SnapLaserEmittersToAttachPoints() -{ - foreach ( TrainingPod_LaserEmitter emitter in file.trainingPodLaserEmitters ) - { - int attachID = file.trainingPod.LookupAttachment( emitter.attachName ) - vector attachOrg = file.trainingPod.GetAttachmentOrigin( attachID ) - vector attachAng = file.trainingPod.GetAttachmentAngles( attachID ) - - emitter.ent.ClearParent() - emitter.ent.SetOrigin( attachOrg ) // HACK set this to ANYTHING (even 0, 0, 0) and the position is correct, otherwise it's offset from the attachpoint when parented - emitter.ent.SetParent( file.trainingPod, emitter.attachName ) - } -} - -void function TrainingPod_Interior_BootSequence( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - entity pod = file.trainingPod - - TrainingPod_InteriorFX_CommonSetup( pod ) - - FlagSet( "PodIntro_InteriorBootSequence_Starting" ) - - EmitSoundOnEntity( player, "NPE_Scr_SimPod_PowerUp" ) - - // Transition screen FX - thread PlayFXOnEntity_Delayed( player, FX_POD_SCREEN_IN, player, 2.35 ) - - // GLOW LIGHTS - TrainingPod_GlowLightsTurnOn() - - // LASERS - float longestSweepTime = -1 - foreach ( emitter in file.trainingPodLaserEmitters ) - { - float sweepTime = RandomFloatRange( 2.9, 3.15 ) - if ( sweepTime > longestSweepTime ) - longestSweepTime = sweepTime - - thread LaserSweep( player, sweepTime, emitter, pod, "top" ) - } - - wait longestSweepTime - - player.Signal( "PodInteriorSequenceDone" ) -} - -void function TrainingPod_InteriorFX_CommonSetup( entity pod ) -{ - if ( file.trainingPodLaserEmitters.len() ) - { - TrainingPod_KillLasers( pod ) - TrainingPod_ResetLaserEmitterRotation( pod ) - } - - TrainingPod_KillGlowFX( pod ) -} - -// NOTE startPosition is actually inverted from what I think it should be. Tag orientation issue, maybe? -void function LaserSweep( entity player, float totalTime, TrainingPod_LaserEmitter emitter, entity pod, string startPosition = "bottom" ) -{ - //float startTime = Time() - - player.EndSignal( "OnDestroy" ) - emitter.ent.EndSignal( "OnDeath" ) - - emitter.sweepDone = false - - //printt( "emitter og angles:", emitter.GetAngles() ) - - vector vecToPlayerEye = ( player.EyePosition() + Vector( 0, 0, 7 ) ) - emitter.ent.GetOrigin() // eye position offset is a HACK, not sure why I need to do that here. - vector centerAng = VectorToAngles( vecToPlayerEye ) - vector topAng = centerAng + Vector( -270, 0, 0 ) - vector bottomAng = centerAng + Vector( -90, 0, 0 ) - - //vector topAng = emitter.GetAngles() + < 90, -8, 0 > - //vector bottomAng = emitter.GetAngles() + < -90, 8, 0 > - - //printt( "==== starting at:", startPosition ) - //printt( "topAng:", topAng ) - //printt( "bottomAng:", bottomAng ) - //printt( "centerAng:", centerAng ) - - vector lastBigSweepAng - - if ( startPosition == "bottom") - { - emitter.ent.SetAbsAngles( bottomAng ) - lastBigSweepAng = bottomAng - } - else - { - emitter.ent.SetAbsAngles( topAng ) - lastBigSweepAng = topAng - } - //printt( "setting start angles to:", lastBigSweepAng ) - - entity fxHandle = PlayLoopFXOnEntity( FX_POD_LASER, emitter.ent ) - emitter.fxHandle = fxHandle - - int numBigSweeps = 2 - float finalCenterTime = totalTime * 0.15 - float bigSweepTime = ( totalTime - finalCenterTime ) / numBigSweeps - - float bigSweep_AccelTime = 0 - float bigSweep_DecelTime = bigSweepTime * 0.2 - - // do the big sweeps - vector nextBigSweepAng - for ( int i = 0; i < numBigSweeps; i++ ) - { - nextBigSweepAng = topAng - if ( lastBigSweepAng == topAng ) - nextBigSweepAng = bottomAng - - //printt( "rotating to", nextBigSweepAng ) - - emitter.ent.NonPhysicsRotateTo( nextBigSweepAng, bigSweepTime, bigSweep_AccelTime, bigSweep_DecelTime ) - - float waitTime = bigSweepTime - if ( i < numBigSweeps - 1 ) - waitTime = bigSweepTime - 0.1 - - wait waitTime - - lastBigSweepAng = nextBigSweepAng - } - - // finish with centering move - //printt( "centering to", centerAng ) - - float finalCenter_AccelTime = 0 - float finalCenter_DecelTime = finalCenterTime * 0.2 - - emitter.ent.NonPhysicsRotateTo( centerAng, finalCenterTime, finalCenter_AccelTime, finalCenter_DecelTime ) - wait finalCenterTime - - emitter.sweepDone = true - //printt( "laser sweep done, total time", Time() - startTime, "should have been", totalTime ) -} - -void function TrainingPod_KillLasers( entity pod, bool doEndCap = false ) -{ - foreach ( emitter in file.trainingPodLaserEmitters ) - { - if ( IsValid_ThisFrame( emitter.fxHandle ) ) - { - if ( !doEndCap ) - { - //printt( "killing laser FX", emitter.fxHandle ) - KillFX( emitter.fxHandle ) - } - else - { - //printt( "killing laser FX with endcap", emitter.fxHandle ) - KillFXWithEndcap( emitter.fxHandle ) - } - } - - emitter.fxHandle = null - } -} - -void function TrainingPod_ResetLaserEmitterRotation( entity pod ) -{ - if ( !file.trainingPodLaserEmitters.len() ) - return - - foreach ( emitter in file.trainingPodLaserEmitters ) - { - //reset to start position - emitter.ent.NonPhysicsRotateTo( emitter.ogAng, 0.05, 0.0, 0.0 ) - } -} - -void function TrainingPod_GlowLightsArraySetup() -{ - array<TrainingPod_GlowLightRow> rows - - // rows are set up bottom to top - // lights are set up outside to in (in = door close seam; opposite for each side) - // process two rows per loop (one for each door side) - - TrainingPod_GlowLightRow row1 - row1.fxSpotsL = [ "fx_glow_L_door012", "fx_glow_L_door013" ] - row1.fxSpotsR = [ "fx_glow_R_door014", "fx_glow_R_door013" ] - rows.append( row1 ) - - TrainingPod_GlowLightRow row2 - row2.fxSpotsL = [ "fx_glow_L_door014", "fx_glow_L_door011" ] - row2.fxSpotsR = [ "fx_glow_R_door012", "fx_glow_R_door011" ] - rows.append( row2 ) - - TrainingPod_GlowLightRow row3 - row3.fxSpotsL = [ "fx_glow_L_door09", "fx_glow_L_door010" ] - row3.fxSpotsR = [ "fx_glow_R_door09", "fx_glow_R_door010" ] - rows.append( row3 ) - - TrainingPod_GlowLightRow row4 - row4.fxSpotsL = [ "fx_glow_L_door07", "fx_glow_L_door08" ] - row4.fxSpotsR = [ "fx_glow_R_door07", "fx_glow_R_door08" ] - rows.append( row4 ) - - TrainingPod_GlowLightRow row5 - row5.fxSpotsL = [ "fx_glow_L_door05", "fx_glow_L_door06" ] - row5.fxSpotsR = [ "fx_glow_R_door05", "fx_glow_R_door06" ] - rows.append( row5 ) - - TrainingPod_GlowLightRow row6 - row6.fxSpotsL = [ "fx_glow_L_door03", "fx_glow_L_door04" ] - row6.fxSpotsR = [ "fx_glow_R_door03", "fx_glow_R_door04" ] - rows.append( row6 ) - - TrainingPod_GlowLightRow row7 - row7.fxSpotsL = [ "fx_glow_L_door01", "fx_glow_L_door02" ] - row7.fxSpotsR = [ "fx_glow_R_door01", "fx_glow_R_door02" ] - rows.append( row7 ) - - file.trainingPodGlowLightRows = rows -} - -void function TrainingPod_GlowLightsTurnOn( bool instantOn = false ) -{ - //float startTime = Time() - - entity pod = file.trainingPod - - foreach ( TrainingPod_GlowLightRow row in file.trainingPodGlowLightRows ) - { - float loopTime = Time() - - array<string> group1 = [ row.fxSpotsL[0], row.fxSpotsR[0] ] - array<string> group2 = [ row.fxSpotsL[1], row.fxSpotsR[1] ] - table< int, array < string > > lightgroups - lightgroups[0] <- group1 - lightgroups[1] <- group2 - - foreach ( idx, group in lightgroups ) - { - foreach ( attachName in group ) - { - entity fxHandle = PlayLoopFXOnEntity( FX_POD_GLOWLIGHT, pod, attachName ) - file.trainingPodGlowLightFXHandles.append( fxHandle ) - } - - if ( !instantOn ) - wait 0.1 - } - - /* - // both sides have same number of lights - int numLights = 2 - for ( int i = 0; i < numLights; i++ ) - { - foreach ( var side in row ) - { - string attachName = side[ i ] - entity fxHandle = PlayLoopFXOnEntity( FX_POD_GLOWLIGHT, pod, attachName ) - file.trainingPodGlowLightFXHandles.append( fxHandle ) - } - - if ( lightWait > 0 ) - wait lightWait - } - - if ( rowWait > 0) - wait rowWait - */ - } - - //printt( "glow lights turn on took", Time() - startTime, "secs" ) -} - -void function TrainingPod_KillGlowFX( entity pod ) -{ - foreach ( fxHandle in file.trainingPodGlowLightFXHandles ) - { - if ( !IsValid_ThisFrame( fxHandle ) ) - continue - - KillFX( fxHandle ) - } - - file.trainingPodGlowLightFXHandles = [] -} - -void function TrainingPod_Interior_ShutdownSequence( entity player, float shutdownTime ) -{ - player.EndSignal( "OnDestroy" ) - - entity pod = file.trainingPod - - TrainingPod_InteriorFX_CommonSetup( pod ) - - // TURN ON GLOW LIGHTS - TrainingPod_GlowLightsTurnOn( true ) - - // TURN ON LASERS - TrainingPod_LasersInstantOn( player, pod ) - - player.WaitSignal( "TrainingPod_BeginInteriorShutdown" ) - - thread TrainingPod_LasersShutDown( player, pod, shutdownTime * 0.6 ) - thread TrainingPod_GlowLightsShutDown( player, pod, shutdownTime ) - - wait shutdownTime - printt( "interior shutdown done" ) -} - -void function TrainingPod_LasersInstantOn( entity player, entity pod ) -{ - foreach ( emitter in file.trainingPodLaserEmitters ) - { - float dist = Distance( player.EyePosition(), emitter.ent.GetOrigin() ) - Assert( dist <= 30, "player is usually about 20 units away when we try to set the laser angles. If very far away, the math will crash the game. Dist: " + dist ) - - vector vecToPlayerEye = ( player.EyePosition() + Vector( 0, 0, 7 ) ) - emitter.ent.GetOrigin() // eye position offset is a HACK, not sure why I need to do that here. - vector centerAng = VectorToAngles( vecToPlayerEye ) - emitter.ent.NonPhysicsRotateTo( centerAng, 0.1, 0.0, 0.0 ) // SETANGLES DOES NOT WORK! You have to rotate it for the FX to follow. - - emitter.fxHandle = PlayLoopFXOnEntity( FX_POD_LASER, emitter.ent ) - } -} - -void function TrainingPod_LasersShutDown( entity player, entity pod, float shutdownTime ) -{ - player.EndSignal( "OnDestroy" ) - - foreach ( emitter in file.trainingPodLaserEmitters ) - { - vector vecToPlayerEye = ( player.EyePosition() + Vector( 0, 0, 7 ) ) - emitter.ent.GetOrigin() // eye position offset is a HACK, not sure why I need to do that here. - vector centerAng = VectorToAngles( vecToPlayerEye ) - emitter.ent.NonPhysicsRotateTo( centerAng, 0.1, 0.0, 0.0 ) // SETANGLES DOES NOT WORK! You have to rotate it for the FX to follow. - } - - wait shutdownTime * 0.25 - - float moveDownTime = shutdownTime * 0.75 - float accelTime = moveDownTime * 0.25 - float decelTime = moveDownTime * 0.1 - - foreach ( TrainingPod_LaserEmitter emitter in file.trainingPodLaserEmitters ) - { - vector finalAng = emitter.ent.GetAngles() + Vector( 30, 0, 0 ) // not sure why adding pitch makes them appear to drop down - emitter.ent.NonPhysicsRotateTo( finalAng, moveDownTime, accelTime, decelTime ) - } - - wait moveDownTime - TrainingPod_KillLasers( pod, true ) -} - -void function TrainingPod_GlowLightsShutDown( entity player, entity pod, float shutdownTime ) -{ - player.EndSignal( "OnDestroy" ) - - float shutdownDelay = shutdownTime * 0.65 - float finishEarly = shutdownTime * 0.1 - float glowLightShutDownDuration = shutdownTime - shutdownDelay - finishEarly - - wait shutdownDelay - - Assert( glowLightShutDownDuration > 0.0 ) - - float timePerLight = glowLightShutDownDuration / file.trainingPodGlowLightFXHandles.len().tofloat() - - foreach ( entity fxHandle in file.trainingPodGlowLightFXHandles ) - { - if ( !IsValid_ThisFrame( fxHandle ) ) - continue - - thread KillFXWithEndcap( fxHandle ) - wait timePerLight - } - - file.trainingPodGlowLightFXHandles = [] -} - -void function TrainingPod_ViewConeLock_Shared( entity player ) -{ - player.PlayerCone_FromAnim() - player.PlayerCone_SetMinYaw( -25 ) - player.PlayerCone_SetMaxYaw( 25 ) - player.PlayerCone_SetMinPitch( -30 ) -} - -void function TrainingPod_ViewConeLock_PodOpen( entity player ) -{ - TrainingPod_ViewConeLock_Shared( player ) - player.PlayerCone_SetMaxPitch( 35 ) -} - -void function TrainingPod_ViewConeLock_PodClosed( entity player ) -{ - TrainingPod_ViewConeLock_Shared( player ) - player.PlayerCone_SetMaxPitch( 32 ) -} - -void function TrainingPod_ViewConeLock_SemiStrict( entity player ) -{ - player.PlayerCone_FromAnim() - player.PlayerCone_SetMinYaw( -10 ) - player.PlayerCone_SetMaxYaw( 10 ) - player.PlayerCone_SetMinPitch( -10 ) - player.PlayerCone_SetMaxPitch( 10 ) -} - -void function TrainingPod_ViewConeLock_Strict( entity player ) -{ - player.PlayerCone_FromAnim() - player.PlayerCone_SetMinYaw( 0 ) - player.PlayerCone_SetMaxYaw( 0 ) - player.PlayerCone_SetMinPitch( 0 ) - player.PlayerCone_SetMaxPitch( 0 ) -} - - -// ================================================== -// ============ CLIENT COMMAND CALLBACKS ============ -// ================================================== - -bool function ClientCommand_Training_SetInputType( entity player, array<string> args ) -{ - int inputType = args[0].tointeger() - - Assert( inputType == INPUT_TYPE_CONTROLLER || inputType == INPUT_TYPE_KBM ) - //printt( "Training- client input type updated:", inputType ) - file.playerInputType = inputType - return true -} - -bool function ClientCommand_Training_PlayerPressedUse( entity player, array<string> args ) -{ - FlagSet( "PlayerPressedUse" ) - return true -} - -bool function ClientCommand_Training_PlayerReloaded( entity player, array<string> args ) -{ - FlagSet( "PlayerReloaded" ) - return true -} - -bool function ClientCommand_LookTarget_Top( entity player, array<string> args ) -{ - player.ResetIdleTimer() - printt( "ClientCommand_LookTarget_Top" ) - FlagSet( "PlayerLookedAtTopTarget" ) - return true -} - -bool function ClientCommand_LookTarget_Bottom( entity player, array<string> args ) -{ - player.ResetIdleTimer() - printt( "ClientCommand_LookTarget_Bottom" ) - FlagSet( "PlayerLookedAtBottomTarget" ) - return true -} - - - -// =============================== -// ============ DOORS ============ -// =============================== -void function DoorOpenFast( string doorEntName ) -{ - entity door = GetEntByScriptName( doorEntName ) - door.Hide() - door.NotSolid() - - entity navBlocker = door.GetLinkEnt() - navBlocker.NotSolid() - ToggleNPCPathsForEntity( navBlocker, true ) -} - -void function DoorCloseFast( string doorEntName ) -{ - entity door = GetEntByScriptName( doorEntName ) - door.Show() - door.Solid() - - entity navBlocker = door.GetLinkEnt() - navBlocker.Solid() - ToggleNPCPathsForEntity( navBlocker, false ) -} - - -void function OpenZenGardenExitDoor() -{ - DoorOpenFast( "zengarden_door" ) -} - -void function CloseZenGardenExitDoor() -{ - DoorCloseFast( "zengarden_door" ) -} - -void function OpenGauntletDoor() -{ - DoorOpenFast( "gauntlet_door" ) -} - - - -// =================================== -// ========= LOUDSPEAKER VO ========== -// =================================== -void function LoudspeakerVO_Setup() -{ - vector loudspeakerPos = <10524, -9660, -5896> // HACK - file.loudspeaker = CreateScriptMover( loudspeakerPos, <0,0,0> ) - - // ======= PA ANNOUNCEMENTS: POD INTRO ======= - // "Inbound to Planet Typhon. Subspace rendezvous in approximately 20 minutes." - RegisterLoudspeakerVO( "intro_0", "diag_sp_addtional_TR411_01_mcor_shipPA", 8.0 ) - - // "Major Anderson, please report to the briefing room." - RegisterLoudspeakerVO( "intro_1", "diag_sp_addtional_TR411_02_mcor_grunt1", 3.0 ) - - // "Reminder to dock personnel: Titan ordnance is a Type 3 Hazardous Material." - RegisterLoudspeakerVO( "intro_2", "diag_sp_addtional_TR411_03_mcor_shipPA", 6.0 ) - - // "Captain Cole to communications." - RegisterLoudspeakerVO( "intro_3", "diag_sp_addtional_TR411_04_mcor_grunt1", 3.0 ) - - // "Running Lifeboat diagnostic test two point one. All Mark Eight lifeboats are in the green." - RegisterLoudspeakerVO( "intro_4", "diag_sp_addtional_TR411_05_mcor_shipPA", 6.0 ) - - // "3rd Militia Grenadiers - prep dropship MacAllan 17." - RegisterLoudspeakerVO( "intro_5", "diag_sp_addtional_TR411_06_mcor_grunt1", 4.0 ) - - - // ======= PA ANNOUNCEMENTS: MEET OG ======= - // "Prepare for Typhon atmospheric entry in less than three minutes." - RegisterLoudspeakerVO( "outro_01", "diag_sp_addtional_TR411_07_mcor_shipPA", 7.0 ) - - // "Powering down all non-essential systems." - RegisterLoudspeakerVO( "outro_01_1", "diag_sp_outro_TR171_01_01_mcor_shipPA", 4.0 ) - - // "All personnel to battle stations." - RegisterLoudspeakerVO( "outro_01_2", "diag_sp_outro_TR171_02_01_mcor_shipPA", 3.0 ) - - // "This is not a drill." - RegisterLoudspeakerVO( "outro_01_3", "diag_sp_outro_TR171_03_01_mcor_shipPA", 3.0 ) - - // "Titan bays two through five, drop clearance confirmed." - RegisterLoudspeakerVO( "outro_03", "diag_sp_addtional_TR411_09_mcor_shipPA", 5.0 ) - - // "Infantry teams Stork three, Elk four, Shark six, Badger one, prepare for emergency atmospheric drop sequence" - RegisterLoudspeakerVO( "outro_04", "diag_sp_addtional_TR411_10_mcor_grunt1", 7.0 ) - - // "All available medical personnel, report to Med Central for tasking." - RegisterLoudspeakerVO( "outro_05", "diag_sp_addtional_TR411_11_mcor_grunt2", 5.0 ) - - // "Titan mech team - Rabbit six, prep the Vanguards." - RegisterLoudspeakerVO( "outro_06", "diag_sp_addtional_TR411_12_mcor_grunt3", 4.0 ) - - // "We need all Riflemen to docking bay four. Dropships standing by." - RegisterLoudspeakerVO( "outro_07", "diag_sp_addtional_TR411_13_mcor_grunt1", 5.0 ) - - // "Incoming hostile ship - Designation: IMS Malta. Battle stations." - RegisterLoudspeakerVO( "outro_08", "diag_sp_addtional_TR411_14_mcor_shipPA", 6.0 ) - - // "Special Recon Squad deploy from Drop Bay thirty-seven - now." - RegisterLoudspeakerVO( "outro_10", "diag_sp_addtional_TR411_16_mcor_grunt2", 5.0 ) - - // "Infantry teams 2nd Militia Fusiliers, Raptor three, target the IMS Malta." - RegisterLoudspeakerVO( "outro_11", "diag_sp_addtional_TR411_17_mcor_grunt3", 6.0 ) - - // "Caution - Fuel leak in Cargo Bay eighty - five. Decompressing for fire suppression." - RegisterLoudspeakerVO( "outro_12", "diag_sp_addtional_TR411_18_mcor_shipPA", 6.0 ) -} - -void function RegisterLoudspeakerVO( string scriptAlias, string soundAlias, float duration = 6.0 ) -{ - Assert( !( scriptAlias in file.loudspeakerVO ), "duplicate scriptAlias " + scriptAlias ) - - LoudspeakerVO_Info voInfo - voInfo.scriptAlias = scriptAlias - voInfo.soundAlias = soundAlias - voInfo.duration = duration - - file.loudspeakerVO[ scriptAlias ] <- voInfo -} - -void function PlayLoudspeakerVO( string scriptAlias, float delay = 0.0 ) -{ - Assert( scriptAlias in file.loudspeakerVO ) - LoudspeakerVO_Info voInfo = file.loudspeakerVO[ scriptAlias ] - - string soundAlias = voInfo.soundAlias - - if ( delay > 0 ) - wait delay - - entity emitter = file.loudspeaker - emitter.Signal( "LoudspeakerVO_Stop" ) - emitter.EndSignal( "LoudspeakerVO_Stop" ) - - OnThreadEnd( - function() : ( emitter, soundAlias ) - { - if ( IsValid( emitter ) ) - FadeOutSoundOnEntity( emitter, soundAlias, 2.0 ) - } - ) - - //printt( "playing loudspeaker VO", scriptAlias, "/", soundAlias ) - EmitSoundOnEntity( emitter, soundAlias ) - wait voInfo.duration -} - -void function LoopLoudspeakerVO( array<string> scriptAliases, string endFlag = "", float minPause = -1, float maxPause = -1 ) -{ - if ( endFlag != "" ) - { - if ( Flag( endFlag ) ) - return - - FlagEnd( endFlag ) - } - - while ( 1 ) - { - foreach ( scriptAlias in scriptAliases ) - { - waitthread PlayLoudspeakerVO( scriptAlias ) - - if ( minPause > 0 && maxPause >= minPause ) - wait RandomFloatRange( minPause, maxPause ) - } - } -} - - - -// ============================== -// ============ MISC ============ -// ============================== - -entity function Training_SpawnAnOG( entity startSpot ) -{ - entity og = CreateSoldier( TEAM_MILITIA, startSpot.GetOrigin(), startSpot.GetAngles() ) - og.kv.spawnflags = SF_NPC_ALLOW_SPAWN_SOLID - DispatchSpawn( og ) - - TakeAllWeapons( og ) - - og.SetModel( OG_PILOT_MODEL ) - - og.SetTitle( "#TRAINING_OG_PILOT_NAME" ) - ShowName( og ) - - Training_OGPilot_SetHelmetOn( og, true ) - - og.DisableHibernation() - og.SetNoTarget( true ) - og.UseSequenceBounds( true ) - MakeInvincible( og ) - og.kv.scriptedAnimForceInterrupt = true - - og.DisableNPCFlag( NPC_ALLOW_FLEE | NPC_ALLOW_HAND_SIGNALS ) - og.SetHologram() - - return og -} - -void function Training_OGPilot_SetHelmetOn( entity og, bool setOn ) -{ - int headIdx = og.FindBodyGroup( "head" ) - - int submodelIdx = OG_PILOT_MODEL_HEAD_IDX_BARE - if ( setOn ) - submodelIdx = OG_PILOT_MODEL_HEAD_IDX_HELMET - - og.SetBodygroup( headIdx, submodelIdx ) - - /* - int decalIdx = og.FindBodyGroup( "decal" ) - if ( decalIdx == -1 ) - return - - submodelIdx = OG_PILOT_MODEL_DECAL_IDX_BARE - if ( setOn ) - submodelIdx = OG_PILOT_MODEL_DECAL_IDX - - og.SetBodygroup( decalIdx, submodelIdx ) - */ -} - -entity function Training_SpawnOGPilot( entity startSpot ) -{ - if ( IsValid( file.ogPilot ) ) - file.ogPilot.Destroy() - - entity og = Training_SpawnAnOG( startSpot ) - file.ogPilot = og - - return og - } - -entity function Training_SpawnOGTwin( entity startSpot ) -{ - if ( IsValid( file.ogTwin ) ) - file.ogTwin.Destroy() - - entity ogTwin = Training_SpawnAnOG( startSpot ) - file.ogTwin = ogTwin - - return ogTwin -} - -entity function GetOGPilot() -{ - Assert( IsValid( file.ogPilot ) ) - return file.ogPilot -} - -entity function GetOGTwin() -{ - if ( !IsValid( file.ogTwin ) ) - return null - - return file.ogTwin -} - - -void function Training_OG_NagPlayerUntilFlag_Sitting( entity player, array<string> nagAliases, float nagInterval, entity idleRef, string endFlag, string talkAnim = "", string idleAnim = "" ) -{ - entity og = GetOGPilot() - Training_NPC_NagPlayerUntilFlag_Sitting( og, player, nagAliases, nagInterval, idleRef, endFlag, talkAnim, idleAnim ) -} - -void function Training_OG_NagPlayerUntilFlag( entity player, array<string> nagAliases, float nagInterval, entity idleRef, string endFlag, string talkAnim = "", string idleAnim = "" ) -{ - entity og = GetOGPilot() - Training_NPC_NagPlayerUntilFlag( og, player, nagAliases, nagInterval, idleRef, endFlag, talkAnim, idleAnim ) -} - -void function Training_NPC_NagPlayerUntilFlag_Sitting( entity npc, entity player, array<string> nagAliases, float nagInterval, entity idleRef, string endFlag, string talkAnim = "", string idleAnim = "" ) -{ - if ( talkAnim == "" ) - talkAnim = ANIM_OG_SITTING_TALK - - if ( idleAnim == "" ) - idleAnim = ANIM_OG_SITTING_IDLE - - Training_OG_NagPlayerUntilFlag( player, nagAliases, nagInterval, idleRef, endFlag, talkAnim, idleAnim ) -} - -void function Training_NPC_NagPlayerUntilFlag( entity npc, entity player, array<string> nagAliases, float nagInterval, entity idleRef, string endFlag, string talkAnim = "", string idleAnim = "" ) -{ - player.EndSignal( "OnDestroy" ) - - if ( talkAnim == "" ) - talkAnim = ANIM_OG_STANDING_TALK - - if ( idleAnim == "" ) - idleAnim = ANIM_OG_STANDING_IDLE - - int nagIdx = 0 - float nextNagTime = Time() + nagInterval - - while ( !Flag( endFlag ) ) - { - if ( Time() > nextNagTime ) - { - waitthread Training_OG_Talks( nagAliases[nagIdx], idleRef, talkAnim, idleAnim, true ) - nextNagTime = Time() + nagInterval - - nagIdx++ - if ( nagIdx >= nagAliases.len() ) - nagIdx = 0 - } - - wait 0.1 - } -} - -void function Training_OG_Talks_Sitting( string voScriptAlias, entity idleRef, string talkAnim = "", string idleAnim = "", bool useBlend = false ) -{ - entity og = GetOGPilot() - Training_NPC_Talks_Sitting( og, voScriptAlias, idleRef, talkAnim, idleAnim, useBlend ) -} - -void function Training_OG_Talks_Leaning( string voScriptAlias, entity idleRef, string talkAnim = "", string idleAnim = "", bool useBlend = false ) -{ - entity og = GetOGPilot() - Training_NPC_Talks_Leaning( og, voScriptAlias, idleRef, talkAnim, idleAnim, useBlend ) -} - -void function Training_OG_Talks( string voScriptAlias, entity idleRef, string talkAnim = "", string idleAnim = "", bool useBlend = false ) -{ - entity og = GetOGPilot() - Training_NPC_Talks( og, voScriptAlias, idleRef, talkAnim, idleAnim, useBlend ) -} - -void function Training_OG_Idles_Sitting( entity idleRef, string anim = "", bool useBlend = false ) -{ - entity og = GetOGPilot() - Training_NPC_Idles_Sitting( og, idleRef, anim, useBlend ) -} - -void function Training_OG_Idles_SittingAndTalking( entity idleRef, string anim = "", bool useBlend = false ) -{ - entity og = GetOGPilot() - Training_NPC_Idles_SittingAndTalking( og, idleRef, anim, useBlend ) -} - -void function Training_OG_Idles_Talking( entity idleRef, string anim = "", bool useBlend = false ) -{ - entity og = GetOGPilot() - Training_NPC_Idles_Talking( og, idleRef, anim, useBlend ) -} - -void function Training_OG_Idles( entity idleRef, string anim = "", bool useBlend = false ) -{ - entity og = GetOGPilot() - thread Training_NPC_Idles( og, idleRef, anim, useBlend ) -} - -void function Training_OG_ScriptedAnim( entity idleRef, string anim, bool useBlend = false ) -{ - entity og = GetOGPilot() - Training_NPC_ScriptedAnim( og, idleRef, anim, useBlend ) -} - - -void function Training_NPC_Talks_Sitting( entity npc, string voScriptAlias, entity idleRef, string talkAnim = "", string idleAnim = "", bool useBlend = false ) -{ - if ( talkAnim == "" ) - talkAnim = ANIM_OG_SITTING_TALK - - if ( idleAnim == "" ) - idleAnim = ANIM_OG_SITTING_IDLE - - Training_NPC_Talks( npc, voScriptAlias, idleRef, talkAnim, idleAnim, useBlend ) -} - -void function Training_NPC_Talks_Leaning( entity npc, string voScriptAlias, entity idleRef, string talkAnim = "", string idleAnim = "", bool useBlend = false ) -{ - if ( talkAnim == "" ) - talkAnim = ANIM_OG_LEANING_TALK - - if ( idleAnim == "" ) - idleAnim = ANIM_OG_LEANING_IDLE - - Training_NPC_Talks( npc, voScriptAlias, idleRef, talkAnim, idleAnim, useBlend ) -} - -void function Training_NPC_Talks( entity npc, string voScriptAlias, entity idleRef, string talkAnim = "", string idleAnim = "", bool useBlend = false ) -{ - npc.EndSignal( "OnDestroy" ) - npc.EndSignal( "NPC_NewCommand" ) - - if ( talkAnim == "" ) - talkAnim = ANIM_OG_STANDING_TALK - - if ( idleAnim == "" ) - idleAnim = ANIM_OG_STANDING_IDLE - - npc.Anim_Stop() - if ( useBlend ) - thread PlayAnim( npc, talkAnim, idleRef ) - else - thread PlayAnim( npc, talkAnim, idleRef, null, 0.0 ) - - OnThreadEnd( - function() : ( npc, idleRef, idleAnim, useBlend ) - { - if ( IsValid( npc ) ) - Training_NPC_Idles( npc, idleRef, idleAnim, useBlend ) - } - ) - - waitthread PlayDialogue( voScriptAlias, npc ) -} - -void function Training_NPC_Idles_Sitting( entity npc, entity idleRef, string anim = "", bool useBlend = false ) -{ - if ( anim == "" ) - anim = ANIM_OG_SITTING_IDLE - - Training_NPC_Idles( npc, idleRef, anim, useBlend ) -} - -void function Training_NPC_Idles_SittingAndTalking( entity npc, entity idleRef, string anim = "", bool useBlend = false ) -{ - if ( anim == "" ) - anim = ANIM_OG_SITTING_TALK - - Training_NPC_Idles( npc, idleRef, anim, useBlend ) -} - -void function Training_NPC_Idles_Talking( entity npc, entity idleRef, string anim = "", bool useBlend = false ) -{ - if ( anim == "" ) - anim = ANIM_OG_STANDING_TALK - - thread Training_NPC_Idles( npc, idleRef, anim, useBlend ) -} - -void function Training_NPC_Idles( entity npc, entity idleRef, string anim = "", bool useBlend = false ) -{ - npc.Signal( "NPC_NewCommand" ) - - if ( anim == "" ) - anim = ANIM_OG_STANDING_IDLE - - npc.Anim_Stop() - - if ( useBlend ) - thread PlayAnim( npc, anim, idleRef ) - else - thread PlayAnim( npc, anim, idleRef, null, 0.0 ) -} - -void function Training_NPC_ScriptedAnim( entity npc, entity idleRef, string anim, bool useBlend = false ) -{ - npc.Signal( "NPC_NewCommand" ) - - npc.Anim_Stop() - - if ( useBlend ) - PlayAnim( npc, anim, idleRef ) - else - PlayAnim( npc, anim, idleRef, null, 0.0 ) -} - -void function Training_OG_Moves_ToSitting( entity moveToRef, string destAnim = "", float moveTimeOverride = -1 ) -{ - if ( destAnim == "" ) - destAnim = ANIM_OG_SITTING_IDLE - - Training_OG_Moves( moveToRef, destAnim, moveTimeOverride, true ) -} - -void function Training_OG_Moves( entity moveToRef, string destAnim = "", float moveTimeOverride = -1, bool destAnim_isSitting = false ) -{ - entity og = GetOGPilot() - og.Signal( "NPC_NewCommand" ) - - int ogAttachIdx = og.LookupAttachment( "CHESTFOCUS" ) - vector startOrigin = og.GetAttachmentOrigin( ogAttachIdx ) - - const vector standingOffset = <0, 0, 42> - const vector sittingOffset = <0, 0, 20> - vector destHeightOffset = destAnim_isSitting ? sittingOffset : standingOffset - vector endOrigin = moveToRef.GetOrigin() + destHeightOffset - - og.Freeze() - - file.ogPilot = null - - if ( IsValid( og ) ) - { - og.NotSolid() - DissolveGhost( og ) - } - - entity newOG = Training_SpawnOGPilot( moveToRef ) - newOG.Hide() - - entity mover = CreateScriptMover( startOrigin, <0,0,0> ) - int moverAttachIdx = mover.LookupAttachment( "REF" ) - EmitSoundOnEntity( mover, "og_dissolve_trail" ) - file.ogPathMover = mover - - newOG.EndSignal( "OnDestroy" ) - mover.EndSignal( "OnDestroy" ) - - OnThreadEnd( - function() : ( mover, newOG, moveToRef, destAnim_isSitting, destAnim, ogAttachIdx ) - { - if ( IsValid( mover ) ) - { - StopSoundOnEntity( mover, "og_dissolve_trail" ) - mover.Destroy() - file.ogPathMover = null - } - - if ( IsValid( newOG ) ) - { - StartParticleEffectOnEntity( newOG, GetParticleSystemIndex( GHOST_FLASH_EFFECT ), FX_PATTACH_POINT, ogAttachIdx ) - newOG.Show() - - if ( destAnim_isSitting ) - Training_OG_Idles_Sitting( moveToRef, destAnim ) - else - Training_OG_Idles( moveToRef, destAnim ) - } - } - ) - - StartParticleEffectOnEntity( mover, GetParticleSystemIndex( GHOST_TRAIL_EFFECT ), FX_PATTACH_POINT_FOLLOW, moverAttachIdx ) - StartParticleEffectOnEntity( mover, GetParticleSystemIndex( GHOST_FLASH_EFFECT ), FX_PATTACH_POINT, moverAttachIdx ) - wait 0.5 - - float moveSpeed = 1350.0 - float moveDist = Distance( startOrigin, endOrigin ) - float moveTime = moveDist / moveSpeed - if ( moveTimeOverride > 0 ) - moveTime = moveTimeOverride - - float accel = moveTime * 0.1 - float decel = moveTime * 0.1 - mover.NonPhysicsMoveTo( endOrigin, moveTime, accel, decel ) - wait moveTime - 0.1 - - EmitSoundAtPosition( TEAM_UNASSIGNED, endOrigin, "PathHologram_Materialized_training" ) - StartParticleEffectOnEntity( mover, GetParticleSystemIndex( GHOST_FLASH_EFFECT ), FX_PATTACH_POINT, moverAttachIdx ) - wait 0.1 -} - -entity function TeleportOG( string entName ) -{ - Assert( IsValid( file.ogPilot ) ) - - file.ogPilot.Signal( "NPC_NewCommand" ) - file.ogPilot.Anim_Stop() - - entity teleportSpot = GetEntByScriptName( entName ) - - vector org = teleportSpot.GetOrigin() - vector ang = teleportSpot.GetAngles() - file.ogPilot.SetOrigin( org ) - file.ogPilot.SetAngles( ang ) - - return teleportSpot -} - -void function NPC_DisableArrivals( entity npc ) -{ - printt( "disabling arrivals" ) - npc.EnableNPCMoveFlag( NPCMF_DISABLE_ARRIVALS ) -} - -void function NPC_EnableArrivals( entity npc ) -{ - printt( "enabling arrivals" ) - npc.DisableNPCMoveFlag( NPCMF_DISABLE_ARRIVALS ) -} - - -void function PlayerAndOGTeleport_Fancy( entity player, vector destPos, string ogTeleportSpotName, vector destAng = < -1, -1, -1 > ) -{ - EndSignal( player, "OnDeath" ) - thread FancyTeleport_EffectsAndSound( player, destPos ) - - player.WaitSignal( "FancyTeleportStart" ) - - entity ogTeleportSpot = TeleportOG( ogTeleportSpotName ) - Training_OG_Idles_Sitting( ogTeleportSpot ) - - MakeInvincible( player ) - WaitEndFrame() // player will take damage from random hazard triggers otherwise - - player.SetOrigin( destPos ) - if ( destAng != < -1, -1, -1 > ) - player.SetAngles( destAng ) - - ClearInvincible( player ) -} - -void function FancyTeleport_EffectsAndSound( entity player, vector teleportPos ) -{ - EndSignal( player, "OnDeath" ) - - float statusEffect_severity = 2.5 - float statusEffect_totalDuration = 0.8 - float statusEffect_easeOutTime = 0.1 - StatusEffect_AddTimed( player, eStatusEffect.timeshift_visual_effect, statusEffect_severity, statusEffect_totalDuration, statusEffect_easeOutTime ) - - wait 0.1 - - Remote_CallFunction_Replay( player, "ScriptCallback_PodTransition_PlayerScreenFX" ) - - EmitSoundOnEntity( player, "Timeshift_Scr_DeviceShift2Present" ) - - wait 0.25 // let screen FX fade screen - - player.Signal( "FancyTeleportStart" ) - - //wait holdTime - 0.1 - - wait 0.5 // let white screen fade - - EmitSoundOnEntity( player, "training_scr_zen_player_fall" ) - - wait 0.2 // let screen clear before pulsing - - entity pulseFXHandle = PlayFX( FX_FANCY_TELEPORT_ENV_PULSE, teleportPos, <0,0,0> ) - EffectSetControlPointVector( pulseFXHandle, 1, <2.5,50,0> ) - thread KillFX_Delayed( pulseFXHandle, 0.5 ) -} - -entity function WaitForPlayerActiveWeapon( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - entity weapon = null - while ( !weapon ) - { - WaitFrame() - weapon = player.GetActiveWeapon() - } - - return weapon -} - - -void function GhostRecorder_RepeatUntilFlag( entity player, string endFlag, entity animRef, asset recordedAnim, float extraRepeatDelay = 0.0, bool silentDissolve = false ) -{ - EndSignal( player, "OnDestroy" ) - EndSignal( level, "StopRepeatingGhostRecorder" ) - - if ( Flag( endFlag ) ) - return - FlagEnd( endFlag ) - - string dissolveSFX = "object_dissolve_training" - if ( silentDissolve ) - dissolveSFX = "" - - table<int,entity> t = {} - t[0] <- null - - OnThreadEnd( - function() : ( t, dissolveSFX ) - { - if ( !t.len() ) - return - - entity ghost = t[0] - - if ( IsValid( ghost ) ) - { - StopSoundOnEntity( ghost, "PathHologram_Sustain_Loop_3P" ) - DissolveGhost( ghost, dissolveSFX ) - } - } - ) - - var rec = LoadRecordedAnimation( recordedAnim ) - float duration = GetRecordedAnimationDuration( rec ) - - const float ghostFadeTime = 1.2 - - while ( 1 ) - { - entity ghost = CreateGhost( animRef.GetOrigin() ) - t[0] = ghost - - EmitSoundOnEntity( ghost, "PathHologram_Sustain_Loop_3P" ) - - ghost.PlayRecordedAnimation( rec, <0,0,0>, <0,0,0>, DEFAULT_SCRIPTED_ANIMATION_BLEND_TIME, animRef ) - wait duration - ghostFadeTime - - DissolveGhost( ghost, dissolveSFX ) - - wait ghostFadeTime - wait extraRepeatDelay - } -} - -void function Training_TeleportEffect( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - player.MovementDisable() - - OnThreadEnd( - function() : ( player ) - { - if ( IsValid( player ) ) - player.MovementEnable() - } - ) - - float fadeTime = 0.3 - float holdTime = 0.5 - - ScreenFade( player, 255, 255, 255, 254, fadeTime, holdTime, FFADE_IN | FFADE_PURGE ) - EmitSoundOnEntity( player, "NPE_VisualImpair" ) - wait fadeTime - wait holdTime - FadeOutSoundOnEntity( player, "NPE_VisualImpair", fadeTime ) -} - -void function TakeAmmoFromPlayerASAP( entity player ) -{ - player.EndSignal( "OnDestroy" ) - - entity weapon = WaitForPlayerActiveWeapon( player ) - - array<entity> weapons = player.GetMainWeapons() - - foreach ( weapon in weapons ) - { - weapon.SetWeaponPrimaryAmmoCount( 0 ) - weapon.SetWeaponPrimaryClipCount( 0 ) - } - - // take offhand weapons player may have collected - array<entity> offhands = player.GetOffhandWeapons() - foreach ( index, weapon in clone offhands ) - player.TakeOffhandWeapon( index ) -} - -void function Training_WeaponPickups_Init( entity player ) -{ - Assert( Flag( "EntitiesDidLoad" ) ) - - LeveledScriptedWeapons leveledScriptedWeapons = GetAllLeveledScriptWeapons() - - foreach ( ent in leveledScriptedWeapons.infoTargets ) - thread Training_RecreateWeaponPickup_Think( ent, player ) -} - -void function Training_SetWeaponPickupsEmptyAmmo() -{ - file.weaponPickupsHaveAmmo = false - - LeveledScriptedWeapons leveledScriptedWeapons = GetAllLeveledScriptWeapons() - foreach ( ent in leveledScriptedWeapons.infoTargets ) - { - // fix for player picking up a weapon right before calling this- attachedEnt is empty because it hasn't been recreated yet - // - actual fix is to thread, wait for attachedEnts to get the recreated weapon again, and timeout, but going with less risk for now - if ( !ent.e.attachedEnts.len() ) - continue - - entity weaponEnt = ent.e.attachedEnts[0] - if ( !IsValid( weaponEnt ) ) - continue - - weaponEnt.SetWeaponPrimaryAmmoCount( 0 ) - weaponEnt.SetWeaponPrimaryClipCount( 0 ) - } -} - -void function Training_SetWeaponPickupsFullAmmo() -{ - file.weaponPickupsHaveAmmo = true - - LeveledScriptedWeapons leveledScriptedWeapons = GetAllLeveledScriptWeapons() - foreach ( ent in leveledScriptedWeapons.infoTargets ) - { - // fix for player picking up a weapon right before calling this- attachedEnt is empty because it hasn't been recreated yet - // - actual fix is to thread, wait for attachedEnts to get the recreated weapon again, and timeout, but going with less risk for now - if ( !ent.e.attachedEnts.len() ) - continue - - entity weaponEnt = ent.e.attachedEnts[0] - if( !IsValid( weaponEnt ) ) - continue - - string weaponClass = weaponEnt.GetWeaponClassName() - int defaultTotal = GetWeaponInfoFileKeyField_GlobalInt( weaponClass, "ammo_default_total" ) - int defaultMag = GetWeaponInfoFileKeyField_GlobalInt( weaponClass, "ammo_clip_size" ) - - weaponEnt.SetWeaponPrimaryAmmoCount( defaultTotal ) - } -} - -void function Training_RecreateWeaponPickup_Think( entity ent, entity player ) -{ - EndSignal( player, "OnDestroy" ) - EndSignal( ent, "OnDestroy" ) - - const float MATCHING_PICKUP_DIST = 0.5 - const float NEARBY_SIMILAR_DIST = 200.0 - - string pickupEntWeaponClass = ent.GetValueForKey( "script_weapon" ) - - while ( ent.e.attachedEnts.len() && IsValid( ent.e.attachedEnts[0] ) ) - { - entity weaponEnt = ent.e.attachedEnts[0] - - while ( IsValid( weaponEnt ) && !weaponEnt.GetOwner() ) - wait 0.1 - - // this is the most reliable way to get a good push vector for if we need to kick another weapon out (pickup ent angles are often not optimal) - vector playerPos_onPickup = player.GetOrigin() - vector vecToPlayer_whenPickedUp = Normalize( playerPos_onPickup - ent.GetOrigin() ) - - ent.e.attachedEnts.remove( 0 ) - - wait 2.2 // don't respawn it right away - - bool oldWeapon_similarPickupNearby = false - bool pickupEnt_similarPickupNearby = false - - // previous player weapon may be here after swapping - array<entity> allPickups = GetWeaponArray( true ) - entity oldWeapon - foreach ( pickup in allPickups ) - { - float distToThisPickup = Distance( pickup.GetOrigin(), ent.GetOrigin() ) - if ( distToThisPickup <= MATCHING_PICKUP_DIST ) - { - oldWeapon = pickup - break - } - } - - if ( IsValid( oldWeapon ) ) - { - foreach ( pickup in allPickups ) - { - if ( oldWeapon == pickup ) - continue - - float distToThisPickup = Distance( pickup.GetOrigin(), ent.GetOrigin() ) - if ( distToThisPickup <= NEARBY_SIMILAR_DIST ) - { - string pickupWeaponClass = pickup.GetWeaponClassName() - - if ( pickupWeaponClass == oldWeapon.GetWeaponClassName() && !oldWeapon_similarPickupNearby ) - { - //printt( "found similar pickup nearby to one the player dropped:", pickupWeaponClass ) - oldWeapon_similarPickupNearby = true - } - - if ( pickupWeaponClass == pickupEntWeaponClass && !pickupEnt_similarPickupNearby ) - { - //printt( "found similar pickup nearby to one that would be recreated:", pickupWeaponClass ) - pickupEnt_similarPickupNearby = true - } - } - } - } - - bool recreatePickup = true - bool destroyOldWeapon = false - if ( IsValid( oldWeapon ) ) - { - if ( oldWeapon.GetWeaponClassName() == pickupEntWeaponClass ) - { - printt( "old weapon that is here is the same kind of weapon as we would spawn, so don't recreate:", pickupEntWeaponClass ) - recreatePickup = false // old weapon that is here is the same kind of weapon as we would spawn, so don't recreate - } - - if ( oldWeapon_similarPickupNearby ) - { - printt( "Old weapon can be destroyed, because a similar pickup is nearby:", oldWeapon.GetWeaponClassName() ) - destroyOldWeapon = true - } - - if ( !oldWeapon_similarPickupNearby && pickupEnt_similarPickupNearby ) - { - printt( "old weapon is unique to this area and pickup ent has a similar pickup nearby, so don't recreate pickup ent. Old weapon:", oldWeapon.GetWeaponClassName(), "/ pickup ent class:", pickupEntWeaponClass ) - recreatePickup = false - } - } - - if ( recreatePickup ) - { - if ( IsValid( oldWeapon ) ) - { - if ( destroyOldWeapon ) - { - printt( "destroying old weapon because similar pickup is nearby:", oldWeapon.GetWeaponClassName() ) - oldWeapon.Destroy() - } - else - { - MoveOldWeapon( ent, oldWeapon, vecToPlayer_whenPickedUp ) // kick the old weapon out of this spot - } - } - - // cover respawn with a flash effect - EmitSoundAtPosition( TEAM_UNASSIGNED, ent.GetOrigin(), "training_scr_rack_weapon_appear" ) - StartParticleEffectInWorld( GetParticleSystemIndex( GHOST_FLASH_EFFECT ), ent.GetOrigin(), ent.GetAngles() ) - CreateScriptWeapon( ent ) - - // defensive checks - if ( !ent.e.attachedEnts.len() || !IsValid( ent.e.attachedEnts[0] ) ) - { - printt( "WARNING! Recreated script pickup FAILED to recreate:", pickupEntWeaponClass, "on ent", ent ) - continue - } - - entity recreatedPickup = ent.e.attachedEnts[0] - printt( "training: recreated weapon pickup:", pickupEntWeaponClass, "by spawning:", recreatedPickup ) - - if ( !file.weaponPickupsHaveAmmo ) - { - recreatedPickup.SetWeaponPrimaryAmmoCount( 0 ) - recreatedPickup.SetWeaponPrimaryClipCount( 0 ) - } - } - else - { - if ( IsValid( oldWeapon ) ) - ent.e.attachedEnts.append( oldWeapon ) - } - } - - printt( "WARNING- Stopping think on pickupEntWeapon:", pickupEntWeaponClass ) -} - -void function MoveOldWeapon( entity pickupEnt, entity oldWeapon, vector pushVec = <0,0,0> ) -{ - // recreate weapon as unconstrained so we can physics push it - entity recreatedOldWeapon = Training_RecreatePlayerWeaponPickup( oldWeapon ) - string recreatedClassName = recreatedOldWeapon.GetWeaponClassName() - - float velocityScalar = 300.0 - - var hasSubClass = GetWeaponInfoFileKeyField_Global( recreatedClassName, "weaponSubClass" ) - if ( hasSubClass ) - { - string weaponSubClass = GetWeaponInfoFileKeyField_GlobalString( recreatedClassName, "weaponSubClass" ) - - switch ( weaponSubClass ) - { - case "offhand": - case "pistol": - velocityScalar = 200 - break - - case "smg": - velocityScalar = 300 - break - - case "rifle": - velocityScalar = 400 - break - - case "lmg": - case "at": - velocityScalar = 500 - break - } - } - - if ( pushVec == <0,0,0> ) - pushVec = AnglesToForward( pickupEnt.GetAngles() ) - - //vector pushAng = VectorToAngles( pushVec ) - //vector addVec = AnglesToUp( pushAng ) * (velocityScalar * 0.2) - //pushVec += addVec - pushVec += <0,0,1> - - printt( "moving old weapon:", oldWeapon.GetWeaponClassName(), "with velocity scalar:", velocityScalar ) - recreatedOldWeapon.SetVelocity( pushVec * velocityScalar ) -} - -entity function Training_RecreatePlayerWeaponPickup( entity oldWeapon ) -{ - if ( file.scriptCreatedWeaponPickups.len() >= MAX_RECREATED_OLD_WEAPONS ) - { - entity cleanupWeapon = file.scriptCreatedWeaponPickups[0] - - if ( IsValid( cleanupWeapon ) ) - cleanupWeapon.Destroy() - - file.scriptCreatedWeaponPickups.remove( 0 ) - } - - string oldWeaponClass = oldWeapon.GetWeaponClassName() - - entity weapon = CreateWeaponEntityByNameWithPhysics( oldWeaponClass, oldWeapon.GetOrigin(), oldWeapon.GetAngles() ) - weapon.SetVelocity( <0,0,0> ) - - SetTargetName( weapon, "_old_player_weapon_" + oldWeaponClass ) - weapon.kv.fadedist = -1 - - array<string> existingMods = oldWeapon.GetMods() - weapon.SetMods( existingMods ) - - bool doMarkAsLoadoutPickup = false - if ( doMarkAsLoadoutPickup ) - weapon.MarkAsLoadoutPickup() - - HighlightWeapon( weapon ) - - oldWeapon.Destroy() - - file.scriptCreatedWeaponPickups.append( weapon ) - - return weapon -} - - -void function Training_WeaponRacks_SetSolidity( bool doSolid ) -{ - array<entity> racks = GetEntArrayByScriptName( "ineedguns_racks" ) - - foreach ( rack in racks ) - { - if ( doSolid ) - rack.Solid() - else - rack.NotSolid() - } -} - - -bool function GetAutosprintEnabled() -{ - int autosprintSetting = GetConVarInt( AUTOSPRINT_CONVAR_NAME ) - bool autoSprintEnabled = autosprintSetting > 0 && autosprintSetting < 3 // 0 = none, 3 = titans only - return autoSprintEnabled -} - - -void function EmitSoundOnEntity_Delayed( entity ent, string alias, float delay ) -{ - ent.EndSignal( "OnDestroy" ) - - if ( delay > 0 ) - wait delay - - EmitSoundOnEntity( ent, alias ) -} - -void function PlayFXOnEntity_Delayed( entity player, asset fxAsset, entity ent, float delay ) -{ - player.EndSignal( "OnDestroy" ) - ent.EndSignal( "OnDeath" ) - - wait delay - - PlayFXOnEntity( fxAsset, ent ) -} - -void function KillFX_Delayed( entity fxHandle, float delay ) -{ - fxHandle.EndSignal( "OnDestroy" ) - - if ( delay > 0.0 ) - wait delay - - KillFX( fxHandle ) -} - -void function KillFX( entity fxHandle ) -{ - if ( !IsValid_ThisFrame( fxHandle ) ) - return - - fxHandle.SetStopType( "DestroyImmediately" ) - fxHandle.ClearParent() - fxHandle.Destroy() -} - -void function KillFXWithEndcap( entity fxHandle, float killDelay = 1.0 ) -{ - if ( !IsValid_ThisFrame( fxHandle ) ) - return - - EffectStop( fxHandle ) - wait killDelay - - if ( !IsValid_ThisFrame( fxHandle ) ) - return - - fxHandle.ClearParent() - fxHandle.Destroy() -} - - -void function FlagSetDelayed( string setFlag, float delay ) -{ - thread FlagSetDelayed_Think( setFlag, delay ) -} - -void function FlagSetDelayed_Think( string setFlag, float delay ) -{ - EndSignal( level, "OnDestroy" ) - - if ( delay > 0 ) - wait delay - - FlagSet( setFlag ) -} - - -void function Training_PlayerQuickdeathSFX( entity player ) -{ - EndSignal( player, "OnDestroy" ) - - while ( 1 ) - { - WaitSignal( player, "QuickDeath" ) - EmitSoundOnEntity( player, "training_scr_zen_player_fall" ) - } -} - - -void function Training_EnvArtColorCorrection_SetEnabled( bool isEnabled ) -{ - Assert( IsValid( file.envArt_colorCorrectionEnt ), "Called too early?" ) - - string setEnabledStr = "Disable" - if ( isEnabled) - setEnabledStr = "Enable" - - EntFireByHandle( file.envArt_colorCorrectionEnt, setEnabledStr, "", 0, null, null ) -} - - -void function SetDoF_Hangar( entity player ) -{ - Remote_CallFunction_Replay( player, "ScriptCallback_DoF_SetNearDepth", 0, 18 ) - Remote_CallFunction_Replay( player, "ScriptCallback_DoF_SetFarDepth", 450, 1250 ) -} - -void function SetDoF_Default( entity player ) -{ - Remote_CallFunction_Replay( player, "ScriptCallback_DoF_SetNearDepthToDefault" ) - Remote_CallFunction_Replay( player, "ScriptCallback_DoF_SetFarDepthToDefault" ) -} - -void function RackDoF_NearDepth( entity player, float nearDepthStart, float nearDepthEnd, float rackTime ) -{ - Remote_CallFunction_Replay( player, "ScriptCallback_DoF_SetNearDepth", nearDepthStart, nearDepthEnd, rackTime ) -} - -void function RackDOF_NearDepth_ToDefault( entity player, float duration ) -{ - Remote_CallFunction_Replay( player, "ScriptCallback_DoF_SetNearDepthToDefault", duration ) -} - -void function RackDoF_FarDepth( entity player, float farDepthStart, float farDepthEnd, float rackTime ) -{ - Remote_CallFunction_Replay( player, "ScriptCallback_DoF_SetFarDepth", farDepthStart, farDepthEnd, rackTime ) -} - -void function SimpleScreenShake( entity player, float duration, float amplitude, float blurMaxIntensity = 0.75 ) -{ - Remote_CallFunction_Replay( player, "ScriptCallback_SimpleScreenShake", duration, amplitude, blurMaxIntensity ) -} - -void function SetWeaponHUDEnabled( entity player, bool setEnabled ) -{ - file.displayWeaponHUD = setEnabled - Remote_CallFunction_Replay( player, "ScriptCallback_SetWeaponHUDEnabled", setEnabled ) -} - - - -// --------------------- -// ----- SKIT GUYS ----- -// --------------------- -SkitGuyInfo function AddSkitGuy_Manually( string name, entity guy ) -{ - if ( SkitGuyExists( name ) ) - DeleteSkitGuy( GetSkitGuyInfo_ByName( name ) ) - - SkitGuyInfo info - info.id = file.skitguys.len() - info.guy = guy - info.name = name - - file.skitguys.append( info ) - - return info -} - -SkitGuyInfo function SpawnSkitGuy( string name, string anim, vector origin, vector angles, int team = TEAM_IMC, string aiSettings = "", string weapon = "mp_weapon_semipistol", bool isRunner = false ) -{ - if ( SkitGuyExists( name ) ) - DeleteSkitGuy( GetSkitGuyInfo_ByName( name ) ) - - string guyType = "grunt" - if ( name.find( "marvin" ) != null ) - guyType = "marvin" - - // spawn the guy - entity guy - if ( guyType == "marvin" ) - { - Assert( !isRunner, "Marvins don't run!" ) - - guy = CreateEntity( "npc_marvin" ) - - DispatchSpawn( guy ) - - SetTeam( guy, TEAM_SPECTATOR ) - guy.SetNPCMoveSpeedScale( 0.6 ) - - //TakeAllJobs( guy ) - } - else - { - guy = CreateSoldier( team, <0,0,0>, <0,0,0> ) // spawn the guy at worldspawn to avoid "npc spawned in solid" red text` - SetSpawnOption_Weapon( guy, weapon ) - if ( aiSettings != "" ) - SetSpawnOption_AISettings( guy, aiSettings ) - - if ( isRunner ) - guy.kv.alwaysAlert = 1 - - DispatchSpawn( guy ) - } - - guy.SetTitle( "" ) - - entity ref = CreateOwnedScriptMover( guy ) - ref.SetOrigin( origin ) - ref.SetAngles( angles ) - - guy.SetOrigin( ref.GetOrigin() ) - guy.SetAngles( ref.GetAngles() ) - - MakeInvincible( guy ) - guy.SetEfficientMode( true ) - guy.EnableNPCFlag( NPC_IGNORE_ALL | NPC_DISABLE_SENSING ) - guy.DisableNPCFlag( NPC_ALLOW_PATROL | NPC_ALLOW_INVESTIGATE | NPC_ALLOW_FLEE | NPC_ALLOW_HAND_SIGNALS ) - - SkitGuyInfo info - info.id = file.skitguys.len() - info.guy = guy - info.skitRef = ref - info.skitAnim = anim - info.name = name - - file.skitguys.append( info ) - - return info -} - -void function SpawnSkitGuy_AndRun( string name, array<Point> path, float moveSpeedScale, int team, string aiSettings = "", string weaponName = "" ) -{ - SkitGuyInfo runnerInfo - runnerInfo = SpawnSkitGuy( name, "", path[0].origin, path[0].angles, team, aiSettings, weaponName, true ) - - entity runner = runnerInfo.guy - EndSignal( runner, "OnDestroy" ) - - OnThreadEnd( - function() : ( runnerInfo ) - { - DeleteSkitGuy( runnerInfo ) - } - ) - - waitthread ScriptedPath_Run( runnerInfo, path, moveSpeedScale ) -} - -void function SpawnSkitGuy_AndRunForever( string name, array<Point> path, float moveSpeedScale, int team, string aiSettings = "", string weaponName = "" ) -{ - SkitGuyInfo runnerInfo - while ( 1 ) - { - runnerInfo = SpawnSkitGuy( name, "", path[0].origin, path[0].angles, team, aiSettings, weaponName ) - waitthread ScriptedPath_Run( runnerInfo, path, moveSpeedScale ) - } -} - -void function SkitGuy_PlayAnim( SkitGuyInfo info, float skipAheadTime = 0 ) -{ - Assert( info.skitAnim != "" ) - Assert( IsValid( info.skitRef ) ) - - entity guy = info.guy - - thread PlayAnim( guy, info.skitAnim, info.skitRef, null, 0.0, skipAheadTime ) -} - -bool function SkitGuyExists( string name ) -{ - foreach ( info in file.skitguys ) - { - if ( info.name == name ) - return true - } - - return false -} - -SkitGuyInfo function GetSkitGuyInfo_ByName( string guyName ) -{ - SkitGuyInfo thisInfo - foreach ( info in file.skitguys ) - { - if ( info.name == guyName ) - { - thisInfo = info - return thisInfo - } - } - - Assert( false, "couldn't find skit guy info by name: " + guyName ) - unreachable -} - -void function DeleteAllSkitGuys() -{ - array<string> deleteNames = [] - - foreach ( skitInfo in file.skitguys ) - deleteNames.append( skitInfo.name ) - - foreach ( name in deleteNames ) - { - if ( !SkitGuyExists( name ) ) - continue - - SkitGuyInfo deleteInfo = GetSkitGuyInfo_ByName( name ) - DeleteSkitGuy( deleteInfo ) - } -} - -void function DeleteSkitGuy( SkitGuyInfo info ) -{ - KillSkitGuy( info ) - - int removeIdx = -1 - foreach ( idx, guyInfo in file.skitguys ) - { - if ( guyInfo.id == info.id ) - { - removeIdx = idx - break - } - } - - if ( removeIdx == -1 ) - { - printt( "WARNING: SkitGuy was already deleted!" ) - return - } - - - file.skitguys.remove( removeIdx ) -} - -void function KillSkitGuy( SkitGuyInfo info ) -{ - entity guy = info.guy - entity skitRef = info.skitRef - - if ( IsValid( skitRef ) ) - skitRef.Destroy() - - info.skitRef = null - - if ( IsAlive( guy ) ) - { - guy.Anim_Stop() - ClearInvincible( guy ) - } - - if ( IsValid( guy ) ) - guy.Destroy() - - info.guy = null -} - -#if DEV -string function NudgeSkitGuy( string name, float offsetX, float offsetY = 0.0, float offsetZ = 0.0 ) -{ - if ( !SkitGuyExists( name ) ) - { - return "WARNING: SKIT GUY NAME NOT RECOGNIZED: " + name - } - - SkitGuyInfo info = GetSkitGuyInfo_ByName( name ) - entity guy = info.guy - entity skitRef = info.skitRef - string name = info.name - - vector offset = <offsetX, offsetY, offsetZ> - - if ( IsValid( skitRef ) ) - skitRef.SetOrigin( skitRef.GetOrigin() + offset ) - else - guy.SetOrigin( guy.GetOrigin() + offset ) - - if ( info.skitAnim != "" ) - SkitGuy_PlayAnim( info ) - - printt( "NUDGED:") - return PrintSkitGuy( info ) -} - -string function PrintSkitGuy( SkitGuyInfo info ) -{ - entity guy = info.guy - entity skitRef = info.skitRef - string name = info.name - - string returnStr = name + " origin/angles: " + CreateOriginAnglesString( guy.GetOrigin(), guy.GetAngles() ) - if ( IsValid( skitRef ) ) - returnStr = name + " ref origin/angles: " + CreateOriginAnglesString( skitRef.GetOrigin(), skitRef.GetAngles() ) - - return returnStr -} -#endif //DEV - - - -// ------------------------------ -// ----- SCRIPTED NPC PATHS ----- -// ------------------------------ -void function ScriptedPath_AddPoint( array<Point> pathpoints, vector origin, vector angles ) -{ - Point pathpoint - pathpoint.origin = origin - pathpoint.angles = angles - - pathpoints.append( pathpoint ) -} - -void function ScriptedPath_Walk( SkitGuyInfo info, array<Point> path, float moveSpeedScale = 0.8, string idleAnim = "" ) -{ - NPC_ScriptedPath( SCRIPTED_PATH_WALK, info, path, moveSpeedScale, idleAnim ) -} - -void function ScriptedPath_Run( SkitGuyInfo info, array<Point> path, float moveSpeedScale = 1.0, string idleAnim = "" ) -{ - NPC_ScriptedPath( SCRIPTED_PATH_RUN, info, path, moveSpeedScale, idleAnim ) -} - -void function NPC_ScriptedPath( int pathFollowType, SkitGuyInfo info, array<Point> path, float moveSpeedScale = 1.0, string idleAnim = "" ) -{ - entity guy = info.guy - - guy.EndSignal( "OnDestroy" ) - - guy.Anim_Stop() - - guy.EnableNPCMoveFlag( NPCMF_DISABLE_MOVE_TRANSITIONS ) - guy.EnableNPCMoveFlag( NPCMF_DISABLE_ARRIVALS ) - guy.SetNPCMoveSpeedScale( moveSpeedScale ) - - if ( pathFollowType == SCRIPTED_PATH_RUN ) - guy.SetAlert() // change his alert state so he will run - - if ( pathFollowType == SCRIPTED_PATH_WALK ) - guy.SetMoveAnim( "patrol_walk_bored" ) - - string waitSignal = "OnEnterGoalRadius" //"OnFinishedAssault" - float pathfindingFailTimeout = 20.0 - - guy.SetOrigin( path[0].origin ) - guy.SetAngles( path[0].angles ) - - for ( int i = 1; i < path.len(); i++ ) - { - Point pathpoint = path[i] - float goalradius = 64.0 // MINIMUM - //guy.DisableArrivalOnce( true ) // always want arrivals disabled because they are blended from run anim, not walking - - guy.AssaultPoint( pathpoint.origin ) - guy.AssaultSetGoalRadius( goalradius ) - - WaitSignalTimeout( guy, pathfindingFailTimeout, waitSignal ) - - if ( Distance( guy.GetOrigin(), pathpoint.origin ) >= goalradius ) - { - printt( guy, " scripted pathfinding stopped, quitting." ) - break - } - } - - if ( idleAnim != "" ) - { - guy.DisableBehavior( "Assault" ) - - while ( !guy.IsInterruptable() ) - wait 0.1 - - entity ref = CreateOwnedScriptMover( guy ) - thread PlayAnim( guy, idleAnim, ref, null, 0.4 ) - - WaitForever() - } - else - { - DeleteSkitGuy( info ) - } -} - - - -// ----------------------------- -// ----- TITAN GROUP SKITS ----- -// ----------------------------- -void function HangarTitanGroup_Init( HangarTitanGroup group ) -{ - group.rack_ogPos = group.rack.GetOrigin() - group.rack_ogAng = group.rack.GetAngles() - - if ( IsValid( group.titan ) ) - { - if ( group.titanSkin == -1 ) - group.titanSkin = 1 - } - - if ( group.marvinAnim != "" ) - { - group.marvin = CreatePropDynamic( MARVIN_MODEL ) - group.marvin.DisableHibernation() - } - - if ( group.pilotAnim != "" ) - { - group.pilot = CreatePropDynamic( group.pilotModel ) - group.pilot.DisableHibernation() - } - - HangarTitanGroup_SetMaxSequenceDuration( group ) - - group.isInited = true -} - -void function HangarTitanGroup_SetMaxSequenceDuration( HangarTitanGroup group ) -{ - table<string,entity> sceneActors = {} - sceneActors[ group.titanAnim ] <- group.titan - sceneActors[ group.rackAnim ] <- group.rack - sceneActors[ group.marvinAnim ] <- group.marvin - - if ( IsValid( group.titan ) ) - { - // set titan to use non posed model - group.titan.SetModel( BUDDY_MODEL ) - group.titan.SetSkin( group.titanSkin ) - } - - float maxDuration = 0 - foreach ( anim, actor in sceneActors ) - { - if ( !IsValid( actor ) ) - continue - - float animDuration = actor.GetSequenceDuration( anim ) - if ( animDuration > maxDuration ) - maxDuration = animDuration - } - - group.sequenceDuration = maxDuration - - if ( IsValid( group.titan ) ) - { - // set titan back to posed anim - group.titan.SetModel( BUDDY_MODEL_POSED_NO_ANIMS ) - //group.titan.SetSkin( group.titanSkin ) - } -} - -void function HangarTitanGroup_Animate( HangarTitanGroup group, string endFlag = "", float duration = -1, bool doCleanup = true ) -{ - if ( endFlag != "" ) - FlagEnd( endFlag ) - - Assert( group.isInited, "Need to call HangarTitanGroup_Init on this group before using" ) - - entity ref = group.ref - entity titan = group.titan - entity rack = group.rack - entity marvin = group.marvin - entity pilot = group.pilot - string titanAnim = group.titanAnim - string rackAnim = group.rackAnim - string marvinAnim = group.marvinAnim - string pilotAnim = group.pilotAnim - float animInitialTime = group.animInitialTime - - EndSignal( rack, "OnDestroy" ) - - if ( IsValid( marvin ) ) - EndSignal( marvin, "OnDestroy") - - if ( IsValid( titan ) ) - { - EndSignal( titan, "OnDestroy" ) - - // set titan to use non posed model - titan.SetModel( BUDDY_MODEL ) - titan.SetSkin( group.titanSkin ) - } - - OnThreadEnd( - function() : ( doCleanup, group ) - { - if ( doCleanup ) - HangarTitanGroup_Cleanup( group ) - } - ) - - if ( duration == -1 || group.sequenceDuration < duration ) - duration = group.sequenceDuration - - thread PlayAnim( rack, rackAnim, ref, null, 0.0, animInitialTime ) - - if ( IsValid( titan) ) - thread PlayAnim( titan, titanAnim, ref, null, 0.0, animInitialTime ) - - if ( IsValid( marvin ) ) - thread PlayAnim( marvin, marvinAnim, ref, null, 0.0, animInitialTime ) - - if ( IsValid( pilot ) ) - thread PlayAnim( pilot, pilotAnim, ref, null, 0.0, animInitialTime ) - - wait duration -} - -void function HangarTitanGroup_Cleanup( HangarTitanGroup group ) -{ - HangarTitanGroup_Reset( group ) - - if ( IsValid( group.marvin ) ) - group.marvin.Destroy() - - if ( IsValid( group.pilot ) ) - group.pilot.Destroy() -} - -void function HangarTitanGroup_Reset( HangarTitanGroup group ) -{ - entity titan = group.titan - entity rack = group.rack - - if ( IsValid( titan ) ) - { - titan.Anim_Stop() - titan.SetModel( BUDDY_MODEL_POSED_NO_ANIMS ) - //titan.SetSkin( group.titanSkin ) - } - - if ( IsValid( rack ) ) - { - rack.Anim_Stop() - rack.SetOrigin( group.rack_ogPos ) - rack.SetAngles( group.rack_ogAng ) - } -} - - - -#if DEV -void function skyboxchange( string tName ) -{ - entity cam = GetEnt( tName ) - GetPlayerArray()[0].SetSkyCamera( cam ) -} - - -// ====================================================== -// ============ GHOST RECORDER DEV FUNCTIONS ============ -// ====================================================== -void function wallruntest() -{ - entity preWallrunRef = GetEntByScriptName( "basic_movement_wallrun_start_ref" ) - var rec = LoadRecordedAnimation( $"anim_recording/training_record_zengarden_wallrun.rpak" ) - file.ogPilot.Anim_Stop() - file.ogPilot.PlayRecordedAnimation( rec, <0,0,0>, <0,0,0>, DEFAULT_SCRIPTED_ANIMATION_BLEND_TIME, preWallrunRef ) -} - -void function Record_ZenGarden_Wallrun() -{ - thread RecordAnimation_Think( "training_record_zengarden_wallrun", "basic_movement_wallrun_start_ref" ) -} - -void function Record_ZenGarden_Slide() -{ - thread RecordAnimation_Think( "training_record_zengarden_slide", "zengarden_slide_ref" ) -} - -void function Record_ZenGarden_DoubleJump() -{ - thread RecordAnimation_Think( "training_record_zengarden_doublejump", "zengarden_doublejump_ref" ) -} - -void function RecordAnimation_Think( string filename, string refName ) -{ - entity player = file.player - player.Signal( "RecordAnimation_Start" ) - player.EndSignal( "RecordAnimation_Start" ) - - TeleportPlayerAndBT( refName ) - - player.EndSignal( "OnDestroy" ) - - entity ref = GetEntByScriptName( refName ) - - printt( "READY TO RECORD: " + filename ) - - //start recording - player.WaitSignal( "ButtonPressedAttack" ) - printt( "RECORDING STARTED" ) - - player.StartRecordingAnimation( ref.GetOrigin(), ref.GetAngles() ) - - //stop - player.WaitSignal( "ButtonPressedAttack" ) - - var recording = player.StopRecordingAnimation() - -#if PC_PROG - SaveRecordedAnimation( recording, filename ) -#endif - printt( "STOP RECORD player org/ang:", player.GetOrigin(), player.GetAngles() ) -} -#endif //DEV |