aboutsummaryrefslogtreecommitdiff
path: root/Northstar.Coop/scripts/vscripts/sp/sp_training.nut
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-08-31 23:14:58 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-08-31 23:14:58 +0100
commit9a96d0bff56f1969c68bb52a2f33296095bdc67d (patch)
tree4175928e488632705692e3cccafa1a38dd854615 /Northstar.Coop/scripts/vscripts/sp/sp_training.nut
parent27bd240871b7c0f2f49fef137718b2e3c208e3b4 (diff)
downloadNorthstarMods-9a96d0bff56f1969c68bb52a2f33296095bdc67d.tar.gz
NorthstarMods-9a96d0bff56f1969c68bb52a2f33296095bdc67d.zip
move to new mod format
Diffstat (limited to 'Northstar.Coop/scripts/vscripts/sp/sp_training.nut')
-rw-r--r--Northstar.Coop/scripts/vscripts/sp/sp_training.nut7554
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