aboutsummaryrefslogtreecommitdiff
path: root/Northstar.Coop/scripts/vscripts/sp/hubs/sp_timeshift_spoke02.nut
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-06-22 14:30:49 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-06-22 14:30:49 +0100
commit207facbc402f5639cbcd31f079214351ef605cf2 (patch)
tree4710b2a88dd64f3dfea1609d31a5de9141640951 /Northstar.Coop/scripts/vscripts/sp/hubs/sp_timeshift_spoke02.nut
parentc2d438568df6d98cf731807e30eaa7da31e5ea52 (diff)
downloadNorthstarMods-207facbc402f5639cbcd31f079214351ef605cf2.tar.gz
NorthstarMods-207facbc402f5639cbcd31f079214351ef605cf2.zip
initial commit after moving to new repo
Diffstat (limited to 'Northstar.Coop/scripts/vscripts/sp/hubs/sp_timeshift_spoke02.nut')
-rw-r--r--Northstar.Coop/scripts/vscripts/sp/hubs/sp_timeshift_spoke02.nut3891
1 files changed, 3891 insertions, 0 deletions
diff --git a/Northstar.Coop/scripts/vscripts/sp/hubs/sp_timeshift_spoke02.nut b/Northstar.Coop/scripts/vscripts/sp/hubs/sp_timeshift_spoke02.nut
new file mode 100644
index 000000000..bdb291d7b
--- /dev/null
+++ b/Northstar.Coop/scripts/vscripts/sp/hubs/sp_timeshift_spoke02.nut
@@ -0,0 +1,3891 @@
+untyped
+
+global function CodeCallback_MapInit
+global function TransitionSpoke1
+
+const DUMMY_MODEL = $"models/Robots/stalker/robot_stalker.mdl"
+const TIMEZONE_DAY = 0
+const TIMEZONE_NIGHT = 1
+const TIMEZONE_ALL = 2
+
+const ANDERSON_MODEL = $"models/humans/heroes/mlt_hero_anderson.mdl"
+const IMC_CORPSE_MODEL_CIV = $"models/levels_terrain/sp_timeshift/civilian_eng_v2_corpse_static_20.mdl"
+
+//const FX_HUMAN_DOOR_OPEN = $"steam_leak_SM_CH_end"
+const FX_ANDERSON_DEVICE_FX = $"P_timeshift_gauntlet_hld"
+const FX_ARK_LAUNCH_GLOW = $"P_ts_core_hld_sm"
+const FX_ARK_LAUNCH_IN_PLACE = $"P_ts_core_hld_sm_lock"
+
+struct
+{
+ int elevatorDudesDead
+ array <entity> elevatorAnimNodes
+ array <entity> elevatorDoors
+
+} file
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+//
+//
+// TIMESHIFT SPOKE 2 - MAP INIT
+//
+//
+/////////////////////////////////////////////////////////////////////////////////////////
+void function CodeCallback_MapInit()
+{
+ ShSpTimeshiftSpoke2CommonInit()
+ RegisterSignal( "AnimTimeshift" )
+ RegisterSignal( "PlayerInsideCage" )
+ RegisterSignal( "ReleaseLabRat")
+
+ PrecacheModel( DUMMY_MODEL )
+ PrecacheModel( ANDERSON_MODEL )
+ PrecacheModel( IMC_CORPSE_MODEL_CIV )
+
+ //PrecacheParticleSystem( FX_HUMAN_DOOR_OPEN )
+ PrecacheParticleSystem( FX_ARK_LAUNCH_GLOW )
+ PrecacheParticleSystem( FX_ARK_LAUNCH_IN_PLACE )
+ PrecacheParticleSystem( FX_ANDERSON_DEVICE_FX )
+
+ //PrecacheModel( LABRAT_MODEL )
+ AddCallback_EntitiesDidLoad( EntitiesDidLoad )
+ AddPlayerDidLoad( TimeShiftHub_PlayerDidLoad )
+ AddSpawnCallback( "npc_soldier", OnSpawnedLevelNPC )
+ AddSpawnCallback( "npc_prowler", OnSpawnedLevelNPC )
+ AddSpawnCallback( "npc_spectre", OnSpawnedLevelNPC )
+ AddSpawnCallback( "prop_dynamic", OnSpawnedPropDynamic )
+
+ AddDeathCallback( "npc_prowler", OnDeathProwlerAcheivement )
+
+
+ SPTimeshiftUtilityInit()
+
+ //------------------
+ // Flags
+ //-----------------
+ FlagInit( "SwappedToFrozenWorld" )
+ FlagInit( "DoneWithFanDropSequence")
+ FlagInit( "ProwlerAcheivementUnlocked" )
+ FlagInit( "BrokeOutOfFanDropMusicLoop")
+ FlagInit( "ProwlerAmbushTriggered" )
+ FlagInit( "AndersomHologram2AboutToStart" )
+ FlagInit( "AcheivementUnlockedLabProwler" )
+ FlagInit( "ForceFlyerTakeoff" )
+ FlagInit( "RingVistaSequenceComplete" )
+ FlagInit( "AllProwlersSpawnedInHumanControlRoom" )
+ FlagInit( "IntelRoom1Finished" )
+ FlagInit( "LabRatAcheivementUnlocked" )
+ FlagInit( "AllElevatorProwlersSpawned" )
+ FlagInit( "player_back_in_amenities_lobby" )
+ FlagInit( "StartAndersonHologram1" )
+ FlagInit( "StartAndersonHologram2" )
+ FlagInit( "StartAndersonHologram3" )
+ FlagInit( "StartSphereRoomGunship" )
+ FlagInit( "LabBravoEnemiesDead" )
+ FlagInit( "human_bridge_soldiers_dead" )
+ FlagInit( "CampusReturnConversationFinished" )
+ FlagInit( "PlayerPickingUpDevice" )
+ FlagInit( "HidePlayerWeaponsDuringShifts")
+ FlagInit( "AllElevatorDudesDead" )
+ FlagInit( "ElevatorDudesDead1" )
+ FlagInit( "ElevatorDudesDead2" )
+ FlagInit( "ElevatorDudesDead3" )
+ FlagInit( "ElevatorDudesDead4" )
+ FlagInit( "CinematicTimeshiftSequenceFinished")
+ FlagInit( "retract_bridge_human_01" )
+ FlagInit( "retract_bridge_control_panel_pressed" )
+ FlagInit( "door_open_amenities_lobby_return_pristine" )
+ FlagInit( "finishedHumanVistaSequence" )
+ FlagInit( "spawnHumanBridgeEnemies" )
+ FlagInit( "player_looking_at_reactor_window" )
+ FlagInit( "open_door_lobby_main_overgrown" )
+ FlagInit( "PlayerLookingTowardsElevators" )
+ FlagInit( "ConcoursePanelHacked01" )
+ FlagInit( "ConcoursePanelHacked02" )
+ FlagInit( "PlayerPickedUpTimeshiftDevice" )
+ FlagInit( "FirstSpectreDeployedLobbyReduxPristine" )
+ FlagInit( "FirstSpectreDeployedLobbyReduxOvergrown" )
+ FlagInit( "SeveralElevatorDudesDead" )
+ FlagInit( "ShowMobilityGhostTurretFirepit" )
+ FlagInit( "ShowMobilityGhostElevatorShaft" )
+ FlagInit( "ShowMobilityGhostTurretFlank" )
+ FlagInit( "ShowMobilityGhostHumanLillypad01" )
+ FlagInit( "ShowMobilityGhostHumanLillypad02" )
+ FlagInit( "ShowMobilityGhostHumanWallrunChain" )
+ FlagInit( "ShowMobilityGhostPowertech" )
+
+ //------------------
+ // Start points
+ //------------------
+ //startPoint, mainFunc, setupFunc skipFunc
+ AddStartPoint( "Timeshift Device", AA_TimeshiftDeviceThread, TimeshiftDeviceStartPointSetup, TimeshiftDeviceSkipped )
+ AddStartPoint( "WILDLIFE RESEARCH", AA_WildlifeResearchThread, WildlifeResearchStartPointSetup, WildlifeResearchSkipped )
+ AddStartPoint( "First Timeshift Fight", AA_FirstTimeshiftFightThread, FirstTimeshiftFightStartPointSetup, FirstTimeshiftFightSkipped )
+ AddStartPoint( "Elevator Fight", AA_ElevatorFightThread, ElevatorFightStartPointSetup, ElevatorFightSkipped )
+ AddStartPoint( "HUMAN RESEARCH", AA_ElevatorTopThread, ElevatorTopStartPointSetup, ElevatorTopSkipped )
+ AddStartPoint( "Sphere Room", AA_SphereRoomThread, SphereRoomStartPointSetup, SphereRoomSkipped ) //checkpointIntelRoom2
+ AddStartPoint( "Human Room", AA_HumanResearchThread, HumanResearchStartPointSetup, HumanResearchSkipped )
+ AddStartPoint( "CAMPUS RETURN", AA_CampusReturnThread, CampusReturnStartPointSetup, CampusReturnSkipped )
+ AddStartPoint( "Fan Drop", AA_FanDropThread, FanDropStartPointSetup, FanDropSkipped )
+ AddStartPoint( "Fan Drop End", AA_FanDropEndThread, FanDropEndStartPointSetup, FanDropEndSkipped )
+
+ AddMobilityGhost( $"anim_recording/timeshift_turret_firepit_overgrown.rpak", "ShowMobilityGhostTurretFirepit" )
+ AddMobilityGhost( $"anim_recording/timeshift_elevator_shaft_overgrown.rpak", "ShowMobilityGhostElevatorShaft" )
+ AddMobilityGhost( $"anim_recording/timeshift_elevator_shaft_pristine.rpak", "ShowMobilityGhostElevatorShaft" )
+ AddMobilityGhost( $"anim_recording/timeshift_turret_flank_overgrown.rpak", "ShowMobilityGhostTurretFlank" )
+ AddMobilityGhost( $"anim_recording/timeshift_lillypad01_overgrown.rpak", "ShowMobilityGhostHumanLillypad01" )
+ AddMobilityGhost( $"anim_recording/timeshift_lillypad01_pristine.rpak", "ShowMobilityGhostHumanLillypad01" )
+ AddMobilityGhost( $"anim_recording/timeshift_lillypad02_overgrown.rpak", "ShowMobilityGhostHumanLillypad02" )
+ AddMobilityGhost( $"anim_recording/timeshift_lillypad02_pristine.rpak", "ShowMobilityGhostHumanLillypad02" )
+ AddMobilityGhost( $"anim_recording/timeshift_wallchain_overgrown.rpak", "ShowMobilityGhostHumanWallrunChain" )
+ AddMobilityGhost( $"anim_recording/timeshift_wallchain_pristine.rpak", "ShowMobilityGhostHumanWallrunChain" )
+ AddMobilityGhost( $"anim_recording/timeshift_powertech_overgrown.rpak", "ShowMobilityGhostPowertech" )
+ AddMobilityGhost( $"anim_recording/timeshift_powertech_pristine.rpak", "ShowMobilityGhostPowertech" )
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function EntitiesDidLoad()
+{
+ FlagSet( "retract_bridge_human_01" )
+
+ HideStuff( "human_bridge_overgrown" )
+ HideStuff( "elevator_doors_upper_overgrown" )
+ HideStuff( "blocker_fandrop_pristine" )
+ HideStuff( "blocker_fandrop_overgrown" )
+
+
+ thread SkyboxStart()
+ thread RingsThink()
+
+ array <entity> elevatorAnimNodesLocal = GetEntArrayByScriptName( "node_elevator_anim" )
+ Assert( elevatorAnimNodesLocal.len() == 4 )
+ file.elevatorAnimNodes = elevatorAnimNodesLocal
+
+ array <entity> elevatorDoorsLocal = GetEntArrayByScriptName( "elevator_door_exec_housing_access" )
+ Assert( elevatorDoorsLocal.len() == 4 )
+ file.elevatorDoors = elevatorDoorsLocal
+
+
+ //navmesh sep to keep prowlers away from half-open elevators
+ entity navmesh_blocker_elevator_overgrown = GetEntByScriptName( "navmesh_blocker_elevator_overgrown" )
+ navmesh_blocker_elevator_overgrown.NotSolid() //ok if it's notsolid, will still disconnect the navmesh
+
+
+ //CleanupEnts( "triggers_instadeath_humanroom" )
+ //CleanupEnts( "triggers_quickdeath_humanroom" )
+ //CleanupEnts( "trigger_quickdeath_checkpoint_humanroom" )
+
+ thread AndersonSetup()
+
+ // coop code: fuck with entities so we can prevent some weird flags
+ //array< entity > doors =
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function TimeShiftHub_PlayerDidLoad( entity player )
+{
+ /*
+ This will run before any start points run.
+ Useful for doing common player-specific setup,
+ saving you from having to put a common player
+ setup function in each of your start points
+ */
+
+ //---------------------
+ // Timeshift thread
+ //----------------------
+ thread TimeshiftPlayerThink( player )
+
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+████████╗██╗███╗ ███╗███████╗███████╗██╗ ██╗██╗███████╗████████╗ ██████╗ ███████╗██╗ ██╗██╗ ██████╗███████╗
+╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ ██╔══██╗██╔════╝██║ ██║██║██╔════╝██╔════╝
+ ██║ ██║██╔████╔██║█████╗ ███████╗███████║██║█████╗ ██║ ██║ ██║█████╗ ██║ ██║██║██║ █████╗
+ ██║ ██║██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║██║██╔══╝ ██║ ██║ ██║██╔══╝ ╚██╗ ██╔╝██║██║ ██╔══╝
+ ██║ ██║██║ ╚═╝ ██║███████╗███████║██║ ██║██║██║ ██║ ██████╔╝███████╗ ╚████╔╝ ██║╚██████╗███████╗
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═══╝ ╚═╝ ╚═════╝╚══════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+████████╗██╗███╗ ███╗███████╗███████╗██╗ ██╗██╗███████╗████████╗ ██████╗ ███████╗██╗ ██╗██╗ ██████╗███████╗
+╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ ██╔══██╗██╔════╝██║ ██║██║██╔════╝██╔════╝
+ ██║ ██║██╔████╔██║█████╗ ███████╗███████║██║█████╗ ██║ ██║ ██║█████╗ ██║ ██║██║██║ █████╗
+ ██║ ██║██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║██║██╔══╝ ██║ ██║ ██║██╔══╝ ╚██╗ ██╔╝██║██║ ██╔══╝
+ ██║ ██║██║ ╚═╝ ██║███████╗███████║██║ ██║██║██║ ██║ ██████╔╝███████╗ ╚████╔╝ ██║╚██████╗███████╗
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═══╝ ╚═╝ ╚═════╝╚══════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+████████╗██╗███╗ ███╗███████╗███████╗██╗ ██╗██╗███████╗████████╗ ██████╗ ███████╗██╗ ██╗██╗ ██████╗███████╗
+╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ ██╔══██╗██╔════╝██║ ██║██║██╔════╝██╔════╝
+ ██║ ██║██╔████╔██║█████╗ ███████╗███████║██║█████╗ ██║ ██║ ██║█████╗ ██║ ██║██║██║ █████╗
+ ██║ ██║██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║██║██╔══╝ ██║ ██║ ██║██╔══╝ ╚██╗ ██╔╝██║██║ ██╔══╝
+ ██║ ██║██║ ╚═╝ ██║███████╗███████║██║ ██║██║██║ ██║ ██████╔╝███████╗ ╚████╔╝ ██║╚██████╗███████╗
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═══╝ ╚═╝ ╚═════╝╚══════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+████████╗██╗███╗ ███╗███████╗███████╗██╗ ██╗██╗███████╗████████╗ ██████╗ ███████╗██╗ ██╗██╗ ██████╗███████╗
+╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ ██╔══██╗██╔════╝██║ ██║██║██╔════╝██╔════╝
+ ██║ ██║██╔████╔██║█████╗ ███████╗███████║██║█████╗ ██║ ██║ ██║█████╗ ██║ ██║██║██║ █████╗
+ ██║ ██║██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║██║██╔══╝ ██║ ██║ ██║██╔══╝ ╚██╗ ██╔╝██║██║ ██╔══╝
+ ██║ ██║██║ ╚═╝ ██║███████╗███████║██║ ██║██║██║ ██║ ██████╔╝███████╗ ╚████╔╝ ██║╚██████╗███████╗
+ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═══╝ ╚═╝ ╚═════╝╚══════╝
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+void function TimeshiftDeviceStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointTimeshiftDevice" ) )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function TimeshiftDeviceSkipped( entity player )
+{
+ FlagSet( "open_creature_door_start_pristine" )
+ FlagSet( "PlayerPickedUpTimeshiftDevice" )
+ GiveTimeshiftAbility( player )
+ FlagClear( "open_skybridge_door_end_pristine" )
+ FlagClear( "open_skybridge_door_end_overgrown" )
+ FlagSet( "CinematicTimeshiftSequenceFinished")
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_TimeshiftDeviceThread( entity player )
+{
+ InitBoyleAudioLogs()
+
+ //FlagSet( "open_skybridge_door_end_overgrown" )
+ //FlagSet( "open_creature_door_start_pristine" )
+ //-----------------------------------------
+ // Get timeshift device
+ //-----------------------------------------
+ wait 1
+
+ thread MusicGetTimeshiftDevice( player )
+ thread DialogueCreatureLabAnderson( player )
+
+ thread PickupTimeShiftDevice( player )
+
+
+
+ FlagWait( "PlayerPickedUpTimeshiftDevice" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicGetTimeshiftDevice( entity player )
+{
+ StopMusic()
+ PlayMusic( "music_timeshift_15_gettemporaldevice" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueCreatureLabAnderson( entity player )
+{
+ entity anderson = GetEntByScriptName( "anderson_other_half" )
+ local attach_id = anderson.LookupAttachment( "L_HAND" )
+ vector objectivePos = anderson.GetAttachmentOrigin( attach_id )
+
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_TAKE_TIME_DEVICE", objectivePos )
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+ wait 10
+
+ if ( Flag( "PlayerPickingUpDevice" ) )
+ return
+
+
+ Objective_Remind()
+ //timeshift device nags
+ string nagAlias
+ int nextNagNumber = 1
+
+
+ while( !Flag( "PlayerPickingUpDevice") )
+ {
+ wait( RandomFloatRange( 35, 45 ) )
+
+ if ( Flag( "PlayerPickingUpDevice" ) )
+ break
+
+
+ if ( nextNagNumber == 1 )
+ {
+ //BT Well done, Pilot. You located the wrist mounted device. SRS intel suggests if equipped you can withstand and manipulate the temporal shifts.
+ nagAlias = "diag_sp_wildlifeStudy_TS191_01_01_mcor_bt"
+ }
+
+ if ( nextNagNumber == 2 )
+ {
+ //BT Pilot, recommend you equip the device.
+ nagAlias = "diag_sp_wildlifeStudy_TS191_09_01_mcor_bt"
+ }
+ else if ( nextNagNumber == 3 )
+ {
+ //BT The wrist mounted device may be useful. Recommend you equip the device.
+ nagAlias = "diag_sp_wildlifeStudy_TS191_10_01_mcor_bt"
+ }
+ else if ( nextNagNumber == 4 )
+ {
+ //BT Advisory: Pilot, I recommend you equip the wrist mounted device.
+ nagAlias = "diag_sp_wildlifeStudy_TS191_11_01_mcor_bt"
+ }
+
+ waitthread PlayBTDialogue( nagAlias )
+
+ if ( Flag( "PlayerPickingUpDevice" ) )
+ break
+ Objective_Remind()
+ //Objective_Clear()
+ //TimeshiftSetObjective( player, "#TIMESHIFT_OBJECTIVE_TAKE_TIME_DEVICE", objectivePos )
+ nextNagNumber++
+ if ( nextNagNumber > 4 )
+ nextNagNumber = 1
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AndersonSetup()
+{
+ entity node = GetEntByScriptName( "org_get_device_sequence" )
+ entity anderson = GetEntByScriptName( "anderson_other_half" )
+ anderson.SetModel( ANDERSON_MODEL )
+ thread PlayAnimTeleport( anderson, "pt_timeshift_device_equip_corpse_sequence_idle", node )
+
+ entity AndersonDeviceFX = PlayLoopFXOnEntity( FX_ANDERSON_DEVICE_FX, anderson, "L_BACKHAND" )
+
+
+ int bodyGroupIndex = anderson.FindBodyGroup( "watch" )
+ anderson.SetBodygroup( bodyGroupIndex, 1 )
+
+ bodyGroupIndex = anderson.FindBodyGroup( "watch_ts" )
+ anderson.SetBodygroup( bodyGroupIndex, 1 )
+
+ FlagWait( "PlayerPickingUpDevice")
+
+ wait 1
+
+ if ( IsValid( AndersonDeviceFX ) )
+ {
+ StopFX( AndersonDeviceFX )
+ EntFireByHandle( AndersonDeviceFX, "Stop", "", 0, null, null )
+ AndersonDeviceFX.Destroy()
+ }
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function PickupTimeShiftDevice( entity player )
+{
+ entity node = GetEntByScriptName( "org_get_device_sequence" )
+ entity anderson = GetEntByScriptName( "anderson_other_half" )
+
+ wait 0.5
+
+ local attach_id = anderson.LookupAttachment( "L_HAND" )
+ vector origin = anderson.GetAttachmentOrigin( attach_id )
+ vector angles = anderson.GetAttachmentAngles( attach_id )
+
+
+ //entity useDummy = CreatePropDynamic( TempModel, origin, angles, 6 ) // 0 = no collision, 2 = bounding box, 6 = use vPhysics, 8 = hitboxes only
+ entity useDummy = CreatePropDynamic( DUMMY_MODEL, origin, Vector( 0, 0, 0 ), 2 ) // 0 = no collision, 2 = bounding box, 6 = use vPhysics, 8 = hitboxes only
+ useDummy.SetOrigin( origin )
+
+ useDummy.SetUsable()
+ useDummy.Hide()
+ useDummy.SetUsableByGroup( "pilot" )
+ useDummy.SetUsePrompts( "#TIMESHIFT_HINT_TAKE_DEVICE" , "#TIMESHIFT_HINT_TAKE_DEVICE_PC" )
+
+ local playerActivator
+ while( true )
+ {
+ playerActivator = useDummy.WaitSignal( "OnPlayerUse" ).player
+ if ( IsValid( playerActivator ) && playerActivator.IsPlayer() && !playerActivator.IsTitan() )
+ {
+ // set player to whoever actually picked up the device, not host
+ expect entity( playerActivator )
+ player = playerActivator
+ break
+ }
+ }
+
+ //Cooper: Sorry Anderson
+ FlagSet( "PlayerPickingUpDevice" )
+
+ Objective_Clear()
+ delaythread ( 1 ) PlayDialogue( "diag_sp_extra_GB101_65_01_mcor_player", player )
+
+
+ useDummy.UnsetUsable()
+ useDummy.Destroy()
+
+ player.DisableWeaponWithSlowHolster()
+ player.SetInvulnerable()
+ //player.FreezeControlsOnServer()
+ player.ContextAction_SetBusy()
+
+ FlagSet( "DoingCinematicTimeshift" )
+
+ //----------------------------------
+ // Player takes device off Anderson
+ //------------------------------------
+ entity mover = CreateOwnedScriptMover( node ) //need a mover for first person sequence
+
+ FirstPersonSequenceStruct sequenceTakeDevice
+ //sequenceTakeDevice.blendTime = 1
+ sequenceTakeDevice.attachment = "ref"
+ sequenceTakeDevice.firstPersonAnim = "ptpov_timeshift_device_equip_sequence"
+ sequenceTakeDevice.thirdPersonAnim = "pt_timeshift_device_equip_sequence"
+ sequenceTakeDevice.viewConeFunction = ViewConeTight
+
+ thread PlayAndersonCorpseAnims( anderson, node )
+ waitthread FirstPersonSequence( sequenceTakeDevice, player, mover )
+
+ FlagSet( "PlayerPickedUpTimeshiftDevice" )
+ //---------------------------
+ // Player equips device
+ //----------------------------
+ player.ClearParent()
+ mover.Destroy()
+ entity mover2 = CreateOwnedScriptMover( node ) //need a mover for first person sequence
+
+ FirstPersonSequenceStruct sequenceEquipDevice
+ sequenceEquipDevice.blendTime = 0
+ sequenceEquipDevice.attachment = "ref"
+ sequenceEquipDevice.firstPersonAnim = "ptpov_timeshift_device_equip_sequence_02"
+ sequenceEquipDevice.thirdPersonAnim = "pt_timeshift_device_equip_sequence_02"
+ sequenceEquipDevice.viewConeFunction = ViewConeTight
+
+ //WaitFrame()
+
+ GiveTimeshiftAbility( player )
+ thread TimeshiftSequenceShifts( player, mover2 )
+
+ entity proxy = player.GetFirstPersonProxy()
+ int bodyGroupIndex = proxy.FindBodyGroup( "glove_default" )
+ proxy.SetBodygroup( bodyGroupIndex, 1 ) // 0 = show, 1 = hide
+
+ int bodyGroupIndex2 = proxy.FindBodyGroup( "glove_animated" )
+ proxy.SetBodygroup( bodyGroupIndex2, 1 ) // 0 = show, 1 = hide
+
+ waitthread FirstPersonSequence( sequenceEquipDevice, player, mover2 )
+
+ SetTimeshiftArmDeviceSkin( 1 )
+
+ //player.UnfreezeControlsOnServer()
+ player.ClearInvulnerable()
+ player.Anim_Stop()
+ player.ClearParent()
+ ClearPlayerAnimViewEntity( player )
+ if ( player.ContextAction_IsBusy() )
+ player.ContextAction_ClearBusy()
+ player.EnableWeaponWithSlowDeploy()
+
+ FlagClear( "DoingCinematicTimeshift" )
+
+ FlagSet( "CinematicTimeshiftSequenceFinished")
+
+
+ proxy = player.GetFirstPersonProxy()
+ if ( proxy == null )
+ return
+
+ bodyGroupIndex = proxy.FindBodyGroup( "glove_default" )
+ proxy.SetBodygroup( bodyGroupIndex, 0 ) // 0 = show, 1 = hide
+
+ //bodyGroupIndex2= proxy.FindBodyGroup( "glove_animated" )
+ //proxy.SetBodygroup( bodyGroupIndex2, 1 ) // 0 = show, 1 = hide
+
+}
+
+void function PlayAndersonCorpseAnims( entity anderson, entity node )
+{
+ waitthread PlayAnim( anderson, "pt_timeshift_device_equip_corpse_sequence", node )
+
+ //watch
+ //int bodyGroupIndex = anderson.FindBodyGroup( "watch" )
+ //anderson.SetBodygroup( bodyGroupIndex, 1 )
+
+ int bodyGroupIndex = anderson.FindBodyGroup( "watch_ts" )
+ anderson.SetBodygroup( bodyGroupIndex, 0 )
+
+ thread PlayAnim( anderson, "pt_timeshift_device_equip_corpse_sequence_02", node )
+
+}
+void function TimeshiftSequenceShifts( entity player, entity node )
+{
+ player.EndSignal( "OnDeath" )
+ entity proxy = player.GetFirstPersonProxy()
+ vector nodeOrigin = node.GetOrigin()
+ vector playerOrigin = player.GetOrigin()
+
+
+ WaitSignal( proxy, "AnimTimeshift" )
+ SwapTimelines( player, TIMEZONE_DAY )
+ node.SetAbsOrigin( Vector( nodeOrigin.x, nodeOrigin.y, nodeOrigin.z + TIME_ZOFFSET ) )
+ //player.SetAbsOrigin( Vector( playerOrigin.x, playerOrigin.y, playerOrigin.z + TIME_ZOFFSET ) )
+
+ wait 0.1
+ //EmitSoundOnEntity( player, "Pilot_PhaseShift_End_3P" )
+
+ WaitSignal( proxy, "AnimTimeshift" )
+ SwapTimelines( player, TIMEZONE_NIGHT )
+ node.SetAbsOrigin( nodeOrigin )
+ //player.SetAbsOrigin( playerOrigin )
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗██╗ ██████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║██║ ██╔══██╗██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+██║ █╗ ██║██║██║ ██║ ██║██║ ██║█████╗ █████╗ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██║███╗██║██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══╝ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+╚███╔███╔╝██║███████╗██████╔╝███████╗██║██║ ███████╗ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+ ╚══╝╚══╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝╚═╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗██╗ ██████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║██║ ██╔══██╗██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+██║ █╗ ██║██║██║ ██║ ██║██║ ██║█████╗ █████╗ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██║███╗██║██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══╝ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+╚███╔███╔╝██║███████╗██████╔╝███████╗██║██║ ███████╗ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+ ╚══╝╚══╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝╚═╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗██╗ ██████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║██║ ██╔══██╗██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+██║ █╗ ██║██║██║ ██║ ██║██║ ██║█████╗ █████╗ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██║███╗██║██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══╝ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+╚███╔███╔╝██║███████╗██████╔╝███████╗██║██║ ███████╗ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+ ╚══╝╚══╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝╚═╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗██╗ ██████╗ ██╗ ██╗███████╗███████╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║██║ ██╔══██╗██║ ██║██╔════╝██╔════╝ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+██║ █╗ ██║██║██║ ██║ ██║██║ ██║█████╗ █████╗ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██║███╗██║██║██║ ██║ ██║██║ ██║██╔══╝ ██╔══╝ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+╚███╔███╔╝██║███████╗██████╔╝███████╗██║██║ ███████╗ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+ ╚══╝╚══╝ ╚═╝╚══════╝╚═════╝ ╚══════╝╚═╝╚═╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+void function WildlifeResearchStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointWildlifeResearch" ) )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function WildlifeResearchSkipped( entity player )
+{
+ CleanupEnts( "flyer_lab" )
+ CleanupEnts( "civilian_evac_firehall" )
+ //thread MusicWildlifeResearch( player )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_WildlifeResearchThread( entity player )
+{
+ FlagWait( "CinematicTimeshiftSequenceFinished")
+
+ vector objectivePos = GetEntByScriptName( "obj_creature_labs_after_fire_hall" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_LAB_EXPLORE", objectivePos )
+
+ Remote_CallFunction_NonReplay( player, "ServerCallback_PlayGloveGlow", TIMEZONE_NIGHT )
+
+ CheckPoint_Forced()
+
+ thread MusicWildlifeResearch( player )
+ //CheckPoint()
+
+ wait 1
+
+ thread DisplayOnscreenHint( player, "timeshift_hint_default", 3.0 )
+
+ //failsafeFlagToStart lookAtEnt = null
+ thread QuickSkit( player, GetEntByScriptName( "node_evac_firehall01" ), "headed_into_fire_hall" )
+ thread QuickSkit( player, GetEntByScriptName( "node_evac_firehall02" ), "headed_into_fire_hall" )
+ thread QuickSkit( player, GetEntByScriptName( "node_creature_soldiers_surprised" ), "open_door_creature_labs_part2" )
+
+ //-------------------------------------------------
+ // Use timeshift to get past electricity
+ //------------------------------------------------
+ thread DialogueTimeShiftEquipped( player )
+ thread DialogueCivilianEvacCreatureLabs( player )
+ thread DialogueCreaturLabsIMC( player )
+
+ thread TimeshiftHint( player, TIMEZONE_NIGHT, "player_entered_creature_lab", "timeshift_hint_default", GetEntByScriptName( "trig_player_near_first_ts_hazard" ) )
+
+
+ FlagWait( "player_entered_creature_lab" )
+ CleanupEnts( "civilian_walker_courtyard" )
+ CleanupEnts( "civilian_actor_firehall01" )
+ CleanupEnts( "civilian_actor_firehall02" )
+
+
+ // remove this so we don't softlock other players lol
+ //FlagClear( "open_creature_door_start_pristine" )
+
+ objectivePos = GetEntByScriptName( "objective_spoke1_breadcrumb000" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ CheckPoint_Forced()
+
+ thread TimeshiftHint( player, TIMEZONE_DAY, "player_past_creature_first_laser", "timeshift_hint_default", GetEntByScriptName( "trig_player_near_creature_hazard" ) )
+
+ thread ObjectiveRemindUntilFlag( "player_past_creature_first_laser" )
+
+ FlagWait( "player_past_creature_first_laser" )
+
+ objectivePos = GetEntByScriptName( "objective_spoke1_breadcrumb00" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ thread TimeshiftHint( player, TIMEZONE_NIGHT, "player_past_creature_second_obstacle", "timeshift_hint_default", GetEntByScriptName( "trig_player_near_creature_hazard2" ) )
+
+ CheckPoint_Forced()
+
+ //lookAtEnt
+ thread QuickSkit( player, GetEntByScriptName( "node_evac_creaturelabs_2dudes" ), "player_past_creature_second_obstacle" )
+ thread QuickSkit( player, GetEntByScriptName( "node_evac_creaturelabs_bench2" ), "player_past_creature_second_obstacle" )
+
+ thread ObjectiveRemindUntilFlag( "player_past_creature_second_obstacle" )
+
+ FlagWait( "player_past_creature_second_obstacle" )
+
+
+ thread TimeshiftHint( player, TIMEZONE_DAY, "player_entered_creature_fans", "timeshift_hint_default", GetEntByScriptName( "trig_player_near_creature_fan_hazard" ) )
+
+ objectivePos = GetEntByScriptName( "objective_spoke1_breadcrumb00aa" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+
+ //---------------------------------------
+ // Get past laser door in pristine via fans
+ //---------------------------------------
+
+ thread ObjectiveRemindUntilFlag( "player_exited_creature_labs" )
+
+ FlagWait( "player_entered_creature_fans" )
+
+ CleanupEnts( "civilian_evac_firehall" )
+ thread TimeshiftHint( player, TIMEZONE_NIGHT, "player_exited_creature_labs", "timeshift_hint_default", GetEntByScriptName( "trig_player_near_creature_fan_blockage" ) )
+
+ FlagWait( "player_exited_creature_labs" )
+
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicWildlifeResearch( entity player )
+{
+ if ( Flag( "entered_amenities_elevator_room" ) )
+ return
+
+ FlagEnd( "entered_amenities_elevator_room" )
+
+
+ //waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ StopMusic()
+ SetGlobalNetBool( "music14LoopPausable", false )
+ PlayMusicThatCantBeStopped( "music_timeshift_14_pastloop" )
+
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+ //Until the elevator fight, whenever the player switches in the PRESENT - Play music_timeshift_16_explorepresent
+ thread PlayMusicInTimezoneUntilFlag( "music_timeshift_16_explorepresent", TIMEZONE_NIGHT, "entered_amenities_elevator_room" )
+
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function OnDeathProwlerAcheivement( entity npc, var damageInfo )
+{
+ if ( Flag( "ProwlerAcheivementUnlocked" ) )
+ return
+
+ if ( Flag( "crossed_elevator_fire_chasm" ) )
+ return
+
+ entity attacker = DamageInfo_GetAttacker( damageInfo )
+
+ if ( !IsValid ( attacker ) )
+ return
+
+ if ( !attacker.IsPlayer() )
+ return
+
+ entity player = attacker
+
+ string classname = npc.GetClassName()
+
+ if ( !npc.HasKey( "script_noteworthy") )
+ return
+
+ string scriptNoteworthy = expect string( npc.kv.script_noteworthy )
+
+ if ( scriptNoteworthy != "prowler_acheivement" )
+ return
+
+ FlagSet( "ProwlerAcheivementUnlocked" )
+ UnlockAchievement( player, achievements.TIMESHIFT_PROWLER )
+
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueTimeShiftEquipped( entity player )
+{
+ FlagWait( "player_entered_creature_lab" )
+
+ wait 1
+
+ //BT Pilot Cooper, I have transferred some of my AI functions to the device, in order to permit communication across temporal shifts.
+ thread PlayBTDialogue( "diag_sp_wildlifeStudy_TS191_12_01_mcor_bt" )
+
+ FlagWait( "player_nearing_creature_fans" )
+
+ array <entity> grunts
+ entity gruntSpeaker
+ int gruntLines = 6
+ int gruntLinesPlayed = 0
+ string gruntAlias
+
+ while( true )
+ {
+ if ( gruntLinesPlayed >= gruntLines )
+ break
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ gruntSpeaker = GetClosestGrunt( player, TIMEZONE_DAY )
+ if ( !IsValid( gruntSpeaker ) )
+ continue
+ if ( Distance( player.GetOrigin(), gruntSpeaker.GetOrigin() ) > 512 )
+ continue
+
+ switch( gruntLinesPlayed )
+ {
+ case 0:
+ //IMC Grunt 2 (Radio) What the hell? He was just over there!
+ gruntAlias = "diag_sp_wildlifeStudy_TS191_17_01_imc_grunt2"
+ break
+ case 1:
+ //security3 (radio comms, agitated): Who has visual?
+ gruntAlias = "diag_sp_securityComs_TS104_01_01_imc_security3"
+ break
+ case 2:
+ //security1 (radio comms, agitated): Can't track him, he's bouncing all over the place.
+ gruntAlias = "diag_sp_securityComs_TS104_02_01_imc_security1"
+ break
+ case 3:
+ //security1 (radio comms, agitated): Someone give me a location on this guy!
+ gruntAlias = "diag_sp_securityComs_TS106_01_01_imc_security1"
+ break
+ case 4:
+ //security3 (radio comms, agitated): Where the hell did he go?
+ gruntAlias = "diag_sp_securityComs_TS106_03_01_imc_security3"
+ break
+ case 5:
+ //security2 (radio comms, agitated): Watch your back! Watch your back!
+ gruntAlias = "diag_sp_securityComs_TS106_02_01_imc_security2"
+ break
+ }
+
+ waitthread PlayTimeShiftDialogue( player, gruntSpeaker, gruntAlias )
+ gruntLinesPlayed++
+
+ //Don't do next line till you hit elevator fight
+ FlagWait( "crossed_elevator_fire_chasm" )
+
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueCivilianEvacCreatureLabs( entity player )
+{
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ //IMC Security 3 - PA ...ask that all non-combat personnel and research teams proceed directly to the nearest
+ //Emergency Shelter access point due to a minor security breach. Please remain calm and contact the nearest automated security personnel for assistance.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_13_01_imc_security3" )
+
+ wait 1
+
+ soundEnt.Destroy()
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueCreaturLabsIMC( entity player )
+{
+ FlagWait( "player_past_creature_first_laser" )
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ SetGlobalForcedDialogueOnly( true )
+
+ //IMC Grunt 1 (Radio) ….last spotted him headed towards Wildlife research. Get the rest of the eggheads evacuated and set up a choke point.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_14_01_imc_grunt1" )
+
+ SetGlobalForcedDialogueOnly( false )
+
+ FlagWait( "player_past_creature_second_obstacle" )
+ //IMC Base (Radio) Additional laser meshes coming online. Let's box him in.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_15_01_imc_command" )
+
+ FlagWait( "player_entered_creature_fans" )
+
+ SetGlobalForcedDialogueOnly( true )
+
+ //IMC Grunt 3 (Radio) Control, we have initiated contact with the intruder but his movement is...erratic.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_18_01_imc_grunt3" )
+
+ SetGlobalForcedDialogueOnly( false )
+
+ soundEnt.Destroy()
+}
+
+
+void function CourtyardSoldiersThink( entity npc )
+{
+ if ( Flag( "player_entered_creature_lab") )
+ return
+ FlagEnd( "player_entered_creature_lab" )
+ npc.EnableNPCFlag( NPC_IGNORE_ALL )
+ npc.SetNoTarget( true )
+
+ OnThreadEnd(
+ function() : ( npc )
+ {
+ if ( IsValid( npc ) )
+ npc.Destroy()
+ }
+ )
+
+ WaitSignal( npc, "OnFinishedAssault" )
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗██████╗ ███████╗████████╗ ████████╗██╗███╗ ███╗███████╗███████╗██╗ ██╗██╗███████╗████████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗
+██╔════╝██║██╔══██╗██╔════╝╚══██╔══╝ ╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝
+█████╗ ██║██████╔╝███████╗ ██║ ██║ ██║██╔████╔██║█████╗ ███████╗███████║██║█████╗ ██║ █████╗ ██║██║ ███╗███████║ ██║
+██╔══╝ ██║██╔══██╗╚════██║ ██║ ██║ ██║██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║██║██╔══╝ ██║ ██╔══╝ ██║██║ ██║██╔══██║ ██║
+██║ ██║██║ ██║███████║ ██║ ██║ ██║██║ ╚═╝ ██║███████╗███████║██║ ██║██║██║ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║
+╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗██████╗ ███████╗████████╗ ████████╗██╗███╗ ███╗███████╗███████╗██╗ ██╗██╗███████╗████████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗
+██╔════╝██║██╔══██╗██╔════╝╚══██╔══╝ ╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝
+█████╗ ██║██████╔╝███████╗ ██║ ██║ ██║██╔████╔██║█████╗ ███████╗███████║██║█████╗ ██║ █████╗ ██║██║ ███╗███████║ ██║
+██╔══╝ ██║██╔══██╗╚════██║ ██║ ██║ ██║██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║██║██╔══╝ ██║ ██╔══╝ ██║██║ ██║██╔══██║ ██║
+██║ ██║██║ ██║███████║ ██║ ██║ ██║██║ ╚═╝ ██║███████╗███████║██║ ██║██║██║ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║
+╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗██████╗ ███████╗████████╗ ████████╗██╗███╗ ███╗███████╗███████╗██╗ ██╗██╗███████╗████████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗
+██╔════╝██║██╔══██╗██╔════╝╚══██╔══╝ ╚══██╔══╝██║████╗ ████║██╔════╝██╔════╝██║ ██║██║██╔════╝╚══██╔══╝ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝
+█████╗ ██║██████╔╝███████╗ ██║ ██║ ██║██╔████╔██║█████╗ ███████╗███████║██║█████╗ ██║ █████╗ ██║██║ ███╗███████║ ██║
+██╔══╝ ██║██╔══██╗╚════██║ ██║ ██║ ██║██║╚██╔╝██║██╔══╝ ╚════██║██╔══██║██║██╔══╝ ██║ ██╔══╝ ██║██║ ██║██╔══██║ ██║
+██║ ██║██║ ██║███████║ ██║ ██║ ██║██║ ╚═╝ ██║███████╗███████║██║ ██║██║██║ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║
+╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function FirstTimeshiftFightStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointFirstTimeshiftFight" ) )
+ vector objectivePos = GetEntByScriptName( "objective_amenities_elevator_fight" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_LAB_EXPLORE", objectivePos )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function FirstTimeshiftFightSkipped( entity player )
+{
+ FlagClear( "ShowMobilityGhostTurretFirepit" )
+ CleanupEnts( "flyer_lab" )
+ CleanupEnts( "lab_prowlers" )
+ thread LoudspeakerThread( player )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_FirstTimeshiftFightThread( entity player )
+{
+ FlagWait( "player_exited_creature_labs" )
+
+ vector objectivePos = GetEntByScriptName( "objective_spoke1_breadcrumb01" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+
+ thread LoudspeakerThread( player )
+ FlagSet( "ShowMobilityGhostTurretFirepit" )
+
+ CheckPoint()
+
+ thread DialogueToElevatorFight( player )
+ thread SecurityRoom( player )
+ //-------------------------------
+ // Hallway turret setup
+ //-------------------------------
+
+ array <entity> turrets = GetEntArrayByScriptName( "turrets_hallway_to_elevators" )
+ foreach( turret in turrets )
+ {
+ //bool hasShield = true
+ //thread HACK_DisableTurret( turret, hasShield )
+ turret.SetDumbFireMode( true )
+ }
+
+ FlagWait( "open_door_elevator_fight_hallway_both" )
+
+ CheckPoint()
+
+ objectivePos = GetEntByScriptName( "objective_amenities_elevator_fight" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ //-------------------------------
+ // Hallway turret flank
+ //-------------------------------
+
+ foreach( turret in turrets )
+ {
+ //bool hasShield = true
+ //thread HACK_EnableTurret( turret )
+ }
+
+ FlagWait( "player_entered_turret_to_elevator_hallway" )
+
+ FlagWait( "crossed_elevator_fire_chasm" )
+
+ //FlagClear( "open_door_elevator_fight_hallway_both" )
+ FlagClear( "ShowMobilityGhostTurretFirepit" )
+ CleanupEnts( "flyer_lab" )
+ CleanupEnts( "lab_prowlers" )
+
+ FlagWait( "entered_amenities_elevator_room" )
+
+}
+
+
+void function CreatureSurprisedSoldiersThink( entity npc )
+{
+ npc.EndSignal( "OnDeath" )
+
+ FlagWait( "player_past_creature_second_obstacle" )
+
+ npc.Anim_Stop()
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function SecurityRoom( entity player )
+{
+ player.EndSignal( "OnDeath" )
+
+ entity deadCivilian = CreatePropDynamic( IMC_CORPSE_MODEL_CIV, Vector( 3686, -3820, -764 ), Vector( 0, 29.0586, 0 ), 0 ) // 0 = no collision, 2 = bounding box, 6 = use vPhysics, 8 = hitboxes only
+
+ deadCivilian.Hide()
+ int shiftCount = 0
+ int shiftRequirement = 88
+ entity triggerOvergrown = GetEntByScriptName( "trigger_security_underground_overgrown" )
+ entity triggerPristine = GetEntByScriptName( "trigger_security_underground_pristine" )
+
+ while( true )
+ {
+ wait 0.1
+ if ( shiftCount >= shiftRequirement )
+ break
+ FlagWait( "in_fire_pit" )
+
+ if ( level.timeZone == TIMEZONE_DAY )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+ else
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+
+ if ( ( triggerOvergrown.IsTouching( player ) ) || ( triggerPristine.IsTouching( player ) ) )
+ shiftCount++
+ else
+ continue
+ }
+
+ FlagSet( "open_door_security_underground" )
+
+ deadCivilian.Show()
+
+
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ███████╗██╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗
+██╔════╝██║ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝
+█████╗ ██║ █████╗ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ █████╗ ██║██║ ███╗███████║ ██║
+██╔══╝ ██║ ██╔══╝ ╚██╗ ██╔╝██╔══██║ ██║ ██║ ██║██╔══██╗ ██╔══╝ ██║██║ ██║██╔══██║ ██║
+███████╗███████╗███████╗ ╚████╔╝ ██║ ██║ ██║ ╚██████╔╝██║ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║
+╚══════╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ███████╗██╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗
+██╔════╝██║ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝
+█████╗ ██║ █████╗ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ █████╗ ██║██║ ███╗███████║ ██║
+██╔══╝ ██║ ██╔══╝ ╚██╗ ██╔╝██╔══██║ ██║ ██║ ██║██╔══██╗ ██╔══╝ ██║██║ ██║██╔══██║ ██║
+███████╗███████╗███████╗ ╚████╔╝ ██║ ██║ ██║ ╚██████╔╝██║ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║
+╚══════╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ███████╗██╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗
+██╔════╝██║ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝
+█████╗ ██║ █████╗ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ █████╗ ██║██║ ███╗███████║ ██║
+██╔══╝ ██║ ██╔══╝ ╚██╗ ██╔╝██╔══██║ ██║ ██║ ██║██╔══██╗ ██╔══╝ ██║██║ ██║██╔══██║ ██║
+███████╗███████╗███████╗ ╚████╔╝ ██║ ██║ ██║ ╚██████╔╝██║ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║
+╚══════╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ███████╗██╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ███████╗██╗ ██████╗ ██╗ ██╗████████╗
+██╔════╝██║ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ██╔════╝██║██╔════╝ ██║ ██║╚══██╔══╝
+█████╗ ██║ █████╗ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ █████╗ ██║██║ ███╗███████║ ██║
+██╔══╝ ██║ ██╔══╝ ╚██╗ ██╔╝██╔══██║ ██║ ██║ ██║██╔══██╗ ██╔══╝ ██║██║ ██║██╔══██║ ██║
+███████╗███████╗███████╗ ╚████╔╝ ██║ ██║ ██║ ╚██████╔╝██║ ██║ ██║ ██║╚██████╔╝██║ ██║ ██║
+╚══════╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+void function ElevatorFightStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointElevatorFight" ) )
+ vector objectivePos = GetEntByScriptName( "objective_amenities_elevator_fight" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_LAB_EXPLORE", objectivePos )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function ElevatorFightSkipped( entity player )
+{
+ FlagClear( "ShowMobilityGhostElevatorShaft" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_ElevatorFightThread( entity player )
+{
+
+ FlagWait( "entered_amenities_elevator_room" )
+
+ thread DialogueElevatorRoom( player )
+
+ FlagSet( "ShowMobilityGhostElevatorShaft" )
+
+ thread MusicElevatorFight( player )
+
+ //FlagClear( "open_door_elevator_fight_hallway_both" )
+
+ CheckPoint()
+
+ vector objectivePos = GetEntByScriptName( "objective_amenities_elevator" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+
+ thread SetFlagWhenPlayerLookingAtEnt( player, "PlayerLookingTowardsElevators", GetEntByScriptName( "elevator_look_target"), GetEntByScriptName( "trigger_look_elevators" ) )
+
+ array< entity > propSpawners = GetEntArrayByScriptNameInInstance( "spectre_door_spawner", "spectre_spawner_amenities_elevator_overgrown_upper_02" )
+ float delayMin = 0.5
+ float delayMax = 0.6
+ int maxToSpawn = 1
+ string flagToAbort = ""
+ thread SpawnShowcaseGroupWhenInRange( player, propSpawners, maxToSpawn, flagToAbort, "", delayMin, delayMax )
+
+ FlagWait( "time_shifted_to_elevator_room_past" )
+
+ //-------------------------------
+ // Elevator fight
+ //-------------------------------
+ thread OpenElevatorDoorsOvergrownThink()
+ thread TurretEnemiesComeIntoElevatorRoom()
+ FlagWait( "PlayerLookingTowardsElevators" )
+
+ thread AllElevatorDudesDead()
+ FlagSet( "DisplayTheDamageHint" )
+ thread ElevatorObjectiveReminder( player )
+ //-------------------------------
+ // Token prowlers elevator room
+ //-------------------------------
+ int difficulty = GetSpDifficulty()
+ if ( difficulty < DIFFICULTY_MASTER )
+ maxToSpawn = 5 //max for this room is 10
+ else
+ maxToSpawn = 8 //max for this room is 10
+
+ propSpawners = GetEntArrayByScriptName( "prowler_spawnvents_elevator_room" )
+ delayMin = 3.5
+ delayMax = 6
+ maxToSpawn = 5 //max for this room is 10
+ flagToAbort = "AllElevatorDudesDead"
+ string flagToSetWhenAllAreSpawned = "AllElevatorProwlersSpawned"
+ bool requiresLookAt = true
+ thread SpawnShowcaseGroupWhenInRange( player, propSpawners, maxToSpawn, flagToAbort, flagToSetWhenAllAreSpawned, delayMin, delayMax, "", requiresLookAt )
+
+ //------------------------------------------
+ // Player figures out elevator time puzzle
+ //-------------------------------------------
+ FlagWait( "entered_amenities_elevator" )
+
+ objectivePos = GetEntByScriptName( "objective_elevator_top" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ FlagClear( "DisplayTheDamageHint" )
+
+ FlagWait( "at_elevatorshaft_top" )
+
+ FlagClear( "ShowMobilityGhostElevatorShaft" )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueElevatorRoom( entity player )
+{
+
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+ FlagWait( "entered_amenities_elevator" )
+
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ if( Flag( "exited_elevator_run") )
+ return
+ FlagEnd( "exited_elevator_run" )
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+
+ if ( Flag( "AllElevatorDudesDead" ) )
+ {
+
+ //IMC Base (Radio) Security, Beta 4, do you copy? Beta 4! What is your position?
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_16_01_imc_command" )
+ }
+ else
+ {
+ //IMC Base (Radio) Has the intruder been neutralized?
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_22_01_imc_command" )
+
+ //IMC Grunt 6 (Radio) Standby, we can't get a lock on his position
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_23_01_imc_grunt6" )
+ }
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function HallwayTurretDudesThink( entity npc )
+{
+ npc.EndSignal( "OnDeath" )
+
+ //Kill these guys if player has finished elevator fight
+ FlagWait( "AllElevatorDudesDead" )
+
+ array <entity> players = GetPlayerArray()
+ if ( players.len() <= 0 )
+ return
+ entity player = players[ 0 ]
+ thread DeleteNpcWhenOutOfSight( npc, player )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function ElevatorObjectiveReminder( entity player )
+{
+ if( Flag( "at_elevatorshaft_top") )
+ return
+ FlagEnd( "at_elevatorshaft_top" )
+
+ FlagWait( "AllElevatorDudesDead" )
+
+ wait 5
+
+ while( true )
+ {
+ if ( level.timeZone == TIMEZONE_DAY )
+ Objective_Remind()
+ else if ( ( level.timeZone == TIMEZONE_NIGHT ) && ( !Flag( "enemies_inside_elevator_room_trigger_overgrown") ) )
+ Objective_Remind()
+
+ wait ( RandomFloatRange( 30, 40 ) )
+ }
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function GruntElevatorThink( entity npc )
+{
+ if ( !IsValid( npc ) )
+ return
+ npc.EndSignal( "OnDeath" )
+
+ npc.EnableNPCFlag( NPC_NO_MOVING_PLATFORM_DEATH )
+
+ OnThreadEnd(
+ function() : ( )
+ {
+ file.elevatorDudesDead++
+ if ( file.elevatorDudesDead >= 4 )
+ FlagSet( "SeveralElevatorDudesDead" )
+ }
+ )
+
+ if ( npc.HasKey( "script_noteworthy") )
+ {
+ string anim = expect string( npc.kv.script_noteworthy )
+ string animIdle = anim + "_idle"
+ entity node = GetClosest( file.elevatorAnimNodes, npc.GetOrigin() )
+ Assert( IsValid( node ) )
+ thread PlayAnimTeleport( npc, animIdle, node )
+
+ entity elevatorDoor = GetClosest( file.elevatorDoors, npc.GetOrigin() )
+ Assert( IsValid( elevatorDoor ) )
+
+ string flagToWaitFor = expect string( elevatorDoor.kv.script_flag )
+
+ if ( !Flag( flagToWaitFor ) )
+ {
+ FlagWait( flagToWaitFor )
+ //wait 0.5
+ }
+
+ thread PlayAnimTeleport( npc, anim, node )
+
+ }
+
+ WaitForever()
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function TurretEnemiesComeIntoElevatorRoom()
+{
+ /*
+ entity goal_lobby_middle = GetEntByScriptName( "goal_lobby_middle" )
+ array <entity> grunts = GetNPCArrayBySquad( "kfiejfff" )
+ foreach( grunt in grunts )
+ {
+ if ( !IsAlive( grunt ) )
+ continue
+ grunt.AssaultPoint( goal_lobby_middle.GetOrigin() )
+ }
+ */
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function OpenElevatorDoorsOvergrownThink()
+{
+ FlagWait( "AllElevatorDudesDead" )
+ HideStuff( "doors_and_blockers_elevator_overgrown" )
+ entity navmesh_blocker_elevator_overgrown = GetEntByScriptName( "navmesh_blocker_elevator_overgrown" )
+ navmesh_blocker_elevator_overgrown.Hide()
+ navmesh_blocker_elevator_overgrown.NotSolid()
+ ToggleNPCPathsForEntity( navmesh_blocker_elevator_overgrown, true )
+
+
+//ToggleNPCPathsForEntity( GetEntByScriptName( "navmesh_blocker_elevator_overgrown" ), true )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicElevatorFight( entity player )
+{
+ FlagWait( "entered_amenities_elevator_room" )
+
+ wait 0.1
+
+ StopMusic()
+ PlayMusic( "music_timeshift_17_enterelevatorarea" )
+
+ FlagWait( "elevator_open_d" )
+
+ StopMusic()
+ PlayMusic( "music_timeshift_18_startelevatorfight" )
+ SetGlobalNetBool( "music14LoopPausable", true )
+
+ if( Flag( "entered_amenities_elevator") )
+ return
+
+ FlagEnd( "entered_amenities_elevator" )
+
+
+ //When you climb out of the roof of the elevator - Play music_timeshift_21b_climboutofelevator
+ //also need to stop the old music_timeshift_14_pastloop - Just play music_timeshift_21c_pastloop_stop
+ OnThreadEnd(
+ function() : ( player )
+ {
+ StopMusic()
+ PlayMusicThatCantBeStopped( "music_timeshift_21c_pastloop_stop" )
+ if ( IsValid( player ) )
+ StopSoundOnEntity( player, "music_timeshift_21_combatpresentdone" )
+ PlayMusic( "music_timeshift_21b_climboutofelevator" )
+ if ( IsValid( player ) )
+ {
+ StopSoundOnEntity( player, "music_timeshift_14_pastloop" )
+ printl( "manually stopping music: music_timeshift_14_pastloop")
+ }
+ SetGlobalNetBool( "music14LoopPausable", false )
+ }
+ )
+
+
+
+
+
+ //-----------------------------------------------------------------------------------------------
+ // Don't start playing different time period-specific tracks till the player starts time traveling
+ //-----------------------------------------------------------------------------------------------
+ if ( level.timeZone == TIMEZONE_NIGHT )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ else
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+
+
+ while( true )
+ {
+
+
+ if ( level.timeZone == TIMEZONE_NIGHT )
+ {
+ //----------------------
+ // Enemies still alive TIMEZONE_NIGHT
+ //----------------------
+ if ( ( Flag( "enemies_inside_elevator_room_trigger_overgrown") ) || ( !Flag( "AllElevatorProwlersSpawned" ) ) )
+ {
+ //During the combat, if the player switches to PRESENT - Play music_timeshift_20_combatpresent
+ //StopMusic()
+ StopMusicTrack( "music_timeshift_18_startelevatorfight" )
+ PlayMusicThatCantBeStopped( "music_timeshift_20_combatpresent" )
+
+ //While in TIMEZONE_DAY, check to see when all are dead, so we can stop combat music
+ while( level.timeZone == TIMEZONE_NIGHT )
+ {
+ wait 0.1
+ if ( ( !Flag( "enemies_inside_elevator_room_trigger_overgrown" ) )
+ && ( Flag( "AllElevatorProwlersSpawned" ) )
+ )
+ break
+ }
+ }
+
+ //------------------------------------------------
+ // If all enemies spawned and dead in TIMEZONE_NIGHT, play the "done" track
+ //------------------------------------------------
+ if ( ( !Flag( "enemies_inside_elevator_room_trigger_overgrown") ) && ( Flag( "AllElevatorProwlersSpawned" ) ) && ( level.timeZone == TIMEZONE_NIGHT ) )
+ {
+ //Each time the player switches to the PRESENT where there are no more enemies - Play music_timeshift_21_combatpresentdone
+ //StopMusic()
+ if ( IsValid( player ) )
+ StopSoundOnEntity( player, "music_timeshift_21_combatpresentdone" )
+ PlayMusicThatCantBeStopped( "music_timeshift_21_combatpresentdone" )
+ }
+
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ }
+ else //TIMEZONE_DAY
+ {
+ //----------------------
+ // Enemies still alive TIMEZONE_DAY
+ //----------------------
+ if ( ( !Flag( "AllElevatorDudesDead" ) ) && ( level.timeZone == TIMEZONE_DAY ) )
+ {
+ //During the combat, if the player switches to PAST - Play music_timeshift_19_combatpast
+ PlayMusic( "music_timeshift_19_combatpast" )
+
+ //While in TIMEZONE_DAY, check to see when all are dead, so we can stop combat music
+ while( level.timeZone == TIMEZONE_DAY )
+ {
+ wait 0.1
+ if ( Flag( "AllElevatorDudesDead" ) )
+ break
+ }
+
+ }
+
+ //------------------------------------------------
+ //If all enemies dead in TIMEZONE_DAY, play the "done" track
+ //------------------------------------------------
+ if ( ( Flag( "AllElevatorDudesDead" ) ) && ( level.timeZone == TIMEZONE_DAY ) )
+ {
+ //Each time the player switches to the PAST where there are no more enemies - Play music_timeshift_21a_combatpastdone
+ //StopMusic()
+ PlayMusic( "music_timeshift_21a_combatpastdone" )
+ }
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+ }
+ }
+
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function DialogueToElevatorFight( entity player )
+{
+ player.EndSignal( "OnDeath" )
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ FlagWait( "open_door_elevator_fight_hallway_both" )
+
+ SetGlobalForcedDialogueOnly( true )
+
+ //IMC Grunt 8 (Radio) In position. Activating turrets at south-east corridor.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_26_01_imc_grunt8" )
+
+ //IMC Base (Radio) We have an intruder, heavily armed and dangerous. All units in the area proceed to the south-east elevator banks on level 4 to intercept.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_19_01_imc_command" )
+
+
+ if ( !Flag( "entered_amenities_elevator_room" ) )
+ {
+ //IMC Grunt 4 (Radio) Copy that, control!
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_20_01_imc_grunt4" )
+
+ }
+
+ if ( !Flag( "entered_amenities_elevator_room" ) )
+ {
+ //IMC Grunt 5 (Radio) On our way, control!
+ thread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_21_01_imc_grunt5" )
+
+ }
+
+ FlagWait( "SeveralElevatorDudesDead" )
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ if ( Flag( "entered_amenities_elevator" ) || Flag( "AllElevatorDudesDead" ) )
+ {
+ SetGlobalForcedDialogueOnly( false )
+ return
+ }
+
+ //IMC Base (Radio) Sitrep on the unknown target.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_24_01_imc_command" )
+
+
+ if ( Flag( "entered_amenities_elevator" ) || Flag( "AllElevatorDudesDead" ) )
+ {
+ SetGlobalForcedDialogueOnly( false )
+ return
+ }
+
+ entity soldier = GetClosestGrunt( player, TIMEZONE_DAY, "grunts_elevator" )
+
+ if ( IsValid( soldier ) )
+ {
+ //IMC Grunt 7 (Radio) We're getting our asses kicked out here, that's the bloody SitRep!
+ waitthread PlayTimeShiftDialogue( player, soldier, "diag_sp_wildlifeStudy_TS191_25_01_imc_grunt7" )
+ }
+
+ SetGlobalForcedDialogueOnly( false )
+
+ soundEnt.Destroy()
+
+}
+
+void function AllElevatorDudesDead()
+{
+ FlagWaitAll( "ElevatorDudesDead1", "ElevatorDudesDead2", "ElevatorDudesDead3", "ElevatorDudesDead4" )
+ FlagSet( "AllElevatorDudesDead" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ███████╗██╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ████████╗ ██████╗ ██████╗
+██╔════╝██║ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ╚══██╔══╝██╔═══██╗██╔══██╗
+█████╗ ██║ █████╗ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ ██║ ██║ ██║██████╔╝
+██╔══╝ ██║ ██╔══╝ ╚██╗ ██╔╝██╔══██║ ██║ ██║ ██║██╔══██╗ ██║ ██║ ██║██╔═══╝
+███████╗███████╗███████╗ ╚████╔╝ ██║ ██║ ██║ ╚██████╔╝██║ ██║ ██║ ╚██████╔╝██║
+╚══════╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ███████╗██╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ████████╗ ██████╗ ██████╗
+██╔════╝██║ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ╚══██╔══╝██╔═══██╗██╔══██╗
+█████╗ ██║ █████╗ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ ██║ ██║ ██║██████╔╝
+██╔══╝ ██║ ██╔══╝ ╚██╗ ██╔╝██╔══██║ ██║ ██║ ██║██╔══██╗ ██║ ██║ ██║██╔═══╝
+███████╗███████╗███████╗ ╚████╔╝ ██║ ██║ ██║ ╚██████╔╝██║ ██║ ██║ ╚██████╔╝██║
+╚══════╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ███████╗██╗ ██╗ █████╗ ████████╗ ██████╗ ██████╗ ████████╗ ██████╗ ██████╗
+██╔════╝██║ ██╔════╝██║ ██║██╔══██╗╚══██╔══╝██╔═══██╗██╔══██╗ ╚══██╔══╝██╔═══██╗██╔══██╗
+█████╗ ██║ █████╗ ██║ ██║███████║ ██║ ██║ ██║██████╔╝ ██║ ██║ ██║██████╔╝
+██╔══╝ ██║ ██╔══╝ ╚██╗ ██╔╝██╔══██║ ██║ ██║ ██║██╔══██╗ ██║ ██║ ██║██╔═══╝
+███████╗███████╗███████╗ ╚████╔╝ ██║ ██║ ██║ ╚██████╔╝██║ ██║ ██║ ╚██████╔╝██║
+╚══════╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function ElevatorTopStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointElevatorTop" ) )
+ vector objectivePos = GetEntByScriptName( "objective_intel_data_panel01" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_LAB_EXPLORE", objectivePos )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function ElevatorTopSkipped( entity player )
+{
+ FlagSet( "LabBravoEnemiesDead" )
+ FlagSet( "entered_hallways_to_human_research" )
+ FlagSet( "open_door_elevator_top_lab" )
+ FlagSet( "StartAndersonHologram1" )
+ FlagClear( "open_door_lab_civilian_escape_01" )
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_ElevatorTopThread( entity player )
+{
+ FlagWait( "at_elevatorshaft_top" )
+ FlagClear( "open_door_elevator_top_lab" )
+ //failsafeFlagToStart
+ thread QuickSkit( player, GetEntByScriptName( "node_holo1_evac" ), "exited_elevator_run" )
+
+ thread LabSoldierA( player )
+
+ FlagWait( "exited_elevator_run" )
+
+ SetGlobalForcedDialogueOnly( true )
+
+ thread MusicElevatorTop( player )
+ thread DialogueLabAlphaEvac( player )
+ thread DialogueLabAlpha( player )
+ thread ProwlerGagLabAlpha( player )
+ thread AndersonHologramSequence( player, "node_hologram_lab1", "StartAndersonHologram1" )
+ thread AchievementAndersonsFirstLog( player )
+
+ vector objectivePos = GetEntByScriptName( "objective_intel_data_panel01" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ CheckPoint()
+
+ FlagWait( "open_door_elevator_top_lab" )
+
+ CheckPoint()
+
+ CleanupEnts( "grunts_elevator" )
+
+ thread CleanupAI( player )
+
+ ShowStuff( "elevator_doors_upper_overgrown" )
+
+ wait 2
+
+ SetGlobalForcedDialogueOnly( false )
+
+ FlagClear( "open_door_lab_civilian_escape_01" )
+
+ FlagWait( "AndersonHologram1Finished" )
+
+
+ FlagSet( "IntelRoom1Finished" )
+
+ if ( !Flag( "back_in_hall_after_anderson_first_log" ) )
+ CheckPoint()
+
+ objectivePos = GetEntByScriptName( "objective_sphere_room_breadcrumb01" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ thread ObjectiveRemindUntilFlag( "entered_hallways_to_human_research" )
+
+ FlagWait( "entered_hallways_to_human_research" )
+
+}
+
+void function AchievementAndersonsFirstLog( entity player )
+{
+ FlagWait( "AndersonHologram1Playing" )
+ UnlockAchievement( player, achievements.VIEW_LOG )
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function LabSoldierA( entity player )
+{
+ entity node = GetEntByScriptName( "node_sandtable_soldier_react" )
+ Assert( IsValid( node ) )
+ entity spawner = GetEntByScriptName( "labA_soldier" )
+ Assert( IsValid( spawner ) )
+ entity npc = spawner.SpawnEntity()
+ DispatchSpawn( npc )
+ Assert( IsValid( npc ) )
+
+ npc.EndSignal( "OnDeath" )
+
+ if( Flag( "open_door_elevator_top_lab") )
+ return
+ FlagEnd( "open_door_elevator_top_lab" )
+
+ OnThreadEnd(
+ function() : ( npc )
+ {
+ if ( IsValid( npc ) )
+ npc.Destroy()
+ }
+ )
+
+ npc.EnableNPCFlag( NPC_IGNORE_ALL )
+ npc.SetNoTarget( true )
+ thread PlayAnimTeleport( npc, "pt_cloak_react_app_far_point_timeshift_idle", node )
+
+ FlagWait( "exited_elevator_run" )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ waitthread PlayAnim( npc, "pt_cloak_react_app_far_point_timeshift", node )
+ npc.AssaultPoint( Vector( 4804.74, -3668.88, 11744 ) )
+
+ WaitSignal( npc, "OnFinishedAssault" )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicElevatorTop( entity player )
+{
+ FlagWait( "exited_elevator_run" )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ StopMusic()
+ PlayMusicThatCantBeStopped( "music_timeshift_22_panicburst" )
+
+ FlagWait( "StartAndersonHologram1" )
+
+ StopMusic()
+ PlayMusic( "music_timeshift_23_andersonlog02" )
+
+ thread MusicHologram1Ambush()
+
+ FlagWait( "AndersonHologram1Finished" )
+
+
+ SetGlobalNetBool( "music14LoopPausable", false )
+ PlayMusicThatCantBeStopped( "music_timeshift_14_pastloop" )
+ //Following the ambush, when the player switches to the PRESENT - Play music_timeshift_16_explorepresent
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+ thread PlayMusicInTimezoneUntilFlag( "music_timeshift_16_explorepresent", TIMEZONE_NIGHT, "StartAndersonHologram2" )
+
+
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void function MusicHologram1Ambush()
+{
+ //Ambush could happen in either past of present
+ FlagWaitAny( "open_door_lab_reinforcements_pristine", "ProwlerAmbushTriggered" )
+
+ //StopMusic()
+ PlayMusicThatCantBeStopped( "music_timeshift_24_ambush" )
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void function ProwlerGagLabAlpha( entity player )
+{
+ entity door = GetEntByScriptName( "door_prowler_lab_a" )
+ entity spawner = GetEntByScriptName( "prowler_lab_a" )
+ vector origin = door.GetOrigin()
+ vector angles = door.GetAngles()
+
+ entity prowler = spawner.SpawnEntity()
+ DispatchSpawn( prowler )
+
+ prowler.EnableNPCFlag( NPC_NO_MOVING_PLATFORM_DEATH )
+ prowler.Hide()
+ prowler.NotSolid()
+ MakeInvincible( prowler )
+
+ thread PlayAnimTeleport( prowler, "pr_timeshift_door_tease_01_idle", origin, angles )
+ thread PlayAnimTeleport( door, "door_door_spawn_core_idle", origin, angles )
+
+ string animDoor
+ string animProwler
+
+ FlagWait( "near_lab_alpha_prowler_skit" )
+
+ if ( !Flag( "IntelRoom1Finished" ) )
+ {
+ prowler.Show()
+ prowler.Solid()
+ thread PlayAnimTeleport( door, "door_timeshift_prowler_tease_01", origin, angles )
+ waitthread PlayAnimTeleport( prowler, "pr_timeshift_door_tease_01", origin, angles )
+ prowler.Hide()
+ prowler.NotSolid()
+ thread PlayAnimTeleport( prowler, "pr_timeshift_door_tease_01_idle", origin, angles )
+ thread PlayAnimTeleport( door, "door_door_spawn_core_idle", origin, angles )
+ FlagWait( "AndersonHologram1Finished" )
+ FlagWait( "near_lab_alpha_prowler_skit" )
+ }
+
+ FlagSet( "ProwlerAmbushTriggered" )
+ prowler.Show()
+ prowler.Solid()
+ ClearInvincible( prowler )
+ thread PlayAnimTeleport( prowler, "pr_timeshift_door_spawn_01", origin, angles )
+ thread PlayAnimTeleport( door, "door_timeshift_prowler_spawn_01", origin, angles )
+ DisableNavmeshSeperatorTargetedByEnt( door )
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueLabAlphaEvac( entity player )
+{
+ if( Flag( "open_door_elevator_top_lab") )
+ return
+ FlagEnd( "open_door_elevator_top_lab" )
+
+
+ //entity panel_intel_room1 = GetEntByScriptName( "panel_intel_room1" )
+ entity loudspeakerEnt1 = CreateLoudspeakerEnt( Vector( 5488,-3718, 11736 ) )
+ entity loudspeakerEnt2 = CreateLoudspeakerEnt( Vector( 5488,-3718, 11736 ) )
+ entity loudspeakerEnt3 = CreateLoudspeakerEnt( Vector( 5488,-3718, 11736 ) )
+
+
+ OnThreadEnd(
+ function() : ( loudspeakerEnt1, loudspeakerEnt2, loudspeakerEnt3 )
+ {
+ loudspeakerEnt1.Destroy()
+ loudspeakerEnt2.Destroy()
+ loudspeakerEnt3.Destroy()
+ }
+ )
+
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ //Scientist 1 What about the intruder?!
+ //thread PlayTimeShiftDialogue( player, loudspeakerEnt1, "diag_sp_humanStudy_TS201_03_01_imc_scientist1" )
+
+ wait 0.5
+
+ //He's here!
+ //thread PlayTimeShiftDialogue( player, loudspeakerEnt, "diag_sp_humanStudy_TS202_01_01_imc_scientist1" )
+
+
+ //Grunt: Intruder spotted! Code 83!
+ thread PlayTimeShiftDialogue( player, loudspeakerEnt2, "diag_sp_humanStudy_TS201_14_01_imc_security1" )
+
+ wait 1.8
+
+ //Scientist 2 We have to leave!
+ thread PlayTimeShiftDialogue( player, loudspeakerEnt3, "diag_sp_humanStudy_TS201_04_01_imc_scientist2" )
+
+ wait 1
+
+
+ //General Marder We're going forward with this. The test must be completed.
+ waitthread PlayTimeShiftDialogue( player, player, "diag_sp_humanStudy_TS201_01_01_imc_genMarder" )
+
+
+}
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueLabAlpha( entity player )
+{
+ FlagWait( "open_door_elevator_top_lab" )
+
+ wait 1
+
+
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+ FlagSet( "StartAndersonHologram1" )
+
+ //BT Pilot, a fragment of Anderson's damaged log may be relevant here. Activating log playback...
+ waitthread PlayBTDialogue( "diag_sp_humanStudy_TS201_11_01_imc_bt" )
+
+
+
+ FlagWaitAny( "AndersonHologram1Finished" )
+
+ wait 0.5
+
+
+ FlagWait( "entered_hallways_to_human_research" )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ if ( !Flag( "player_inside_intel_room2" ) )
+ {
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+ //General Marder If we don't test the Sculptor Core now we may never have another chance. Zulu Team, prep the Sculptor Core for delivery.
+ waitthread PlayTimeShiftDialogue( player, player, "diag_sp_humanStudy_TS201_02_01_imc_genMarder" )
+ }
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void function LabAlphaScientistThink( entity npc )
+{
+ npc.EndSignal( "OnDeath" )
+ thread DestroyNPCOnFlag( npc, "open_door_elevator_top_lab" )
+
+ WaitSignal( npc, "OnFinishedAssault" )
+
+ if ( IsValid( npc ) )
+ npc.Destroy()
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██████╗ ██╗ ██╗███████╗██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███╗ ███╗
+██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗██╔════╝ ██╔══██╗██╔═══██╗██╔═══██╗████╗ ████║
+███████╗██████╔╝███████║█████╗ ██████╔╝█████╗ ██████╔╝██║ ██║██║ ██║██╔████╔██║
+╚════██║██╔═══╝ ██╔══██║██╔══╝ ██╔══██╗██╔══╝ ██╔══██╗██║ ██║██║ ██║██║╚██╔╝██║
+███████║██║ ██║ ██║███████╗██║ ██║███████╗ ██║ ██║╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
+╚══════╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██████╗ ██╗ ██╗███████╗██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███╗ ███╗
+██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗██╔════╝ ██╔══██╗██╔═══██╗██╔═══██╗████╗ ████║
+███████╗██████╔╝███████║█████╗ ██████╔╝█████╗ ██████╔╝██║ ██║██║ ██║██╔████╔██║
+╚════██║██╔═══╝ ██╔══██║██╔══╝ ██╔══██╗██╔══╝ ██╔══██╗██║ ██║██║ ██║██║╚██╔╝██║
+███████║██║ ██║ ██║███████╗██║ ██║███████╗ ██║ ██║╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
+╚══════╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██████╗ ██╗ ██╗███████╗██████╗ ███████╗ ██████╗ ██████╗ ██████╗ ███╗ ███╗
+██╔════╝██╔══██╗██║ ██║██╔════╝██╔══██╗██╔════╝ ██╔══██╗██╔═══██╗██╔═══██╗████╗ ████║
+███████╗██████╔╝███████║█████╗ ██████╔╝█████╗ ██████╔╝██║ ██║██║ ██║██╔████╔██║
+╚════██║██╔═══╝ ██╔══██║██╔══╝ ██╔══██╗██╔══╝ ██╔══██╗██║ ██║██║ ██║██║╚██╔╝██║
+███████║██║ ██║ ██║███████╗██║ ██║███████╗ ██║ ██║╚██████╔╝╚██████╔╝██║ ╚═╝ ██║
+╚══════╝╚═╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function SphereRoomStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointIntelRoom2" ) )
+ vector objectivePos = GetEntByScriptName( "objective_intel_data_panel02" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_LAB_EXPLORE", objectivePos )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function SphereRoomSkipped( entity player )
+{
+ FlagSet( "RingsShouldBeSpinning" )
+ FlagSet( "player_inside_intel_room2" )
+ //thread HumanPodsThink( "biodoors_terminal01_pristine", "biodoors_terminal01_overgrown", player )
+ //thread HumanPodsThinkNoHack( "biodoors_terminal01_pristine", "biodoors_terminal02_overgrown", player )
+ //thread HumanPodsThinkNoHack( "biodoors_terminal02_pristine", "biodoors_terminal02_overgrown", player )
+
+ FlagClear( "ShowMobilityGhostTurretFlank" )
+ thread QuickSkit( player, GetEntByScriptName( "node_reactor_flyers" ) )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_SphereRoomThread( entity player )
+{
+ FlagWait( "entered_hallways_to_human_research" )
+
+ FlagSet( "ShowMobilityGhostTurretFlank" )
+
+ thread MusicSphereRoom( player )
+ thread DialogueLabBravo( player )
+ thread DialogueHumanAnteroom( player )
+ thread DialogueGunshipDeploys( player )
+ thread GunshipPadSequenceWait( player )
+ thread GunshipSequence( "gunship_pad", player, "node_gunship_intel_room_2", "pad", "StartSphereRoomGunship" )
+ thread AndersonHologramSequence( player, "node_hologram_lab2", "StartAndersonHologram2" )
+
+ CheckPoint()
+
+ FlagWait( "dropped_into_fire_hallways" )
+ vector objectivePos = GetEntByScriptName( "objective_intel_data_panel02" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ FlagWait( "player_inside_intel_room2" )
+
+ thread TurretNotargetHack( player )
+ FlagWait( "AndersonHologram2Finished" )
+ CheckPoint()
+ FlagSet( "open_door_diorama2_exit_pristine" )
+ FlagSet( "open_door_diorama2_exit_overgrown" )
+
+ thread CheckpointSphereRoomOvergrown( player )
+ thread CheckpointSphereRoomPristine( player )
+
+ objectivePos = GetEntByScriptName( "objective_human_research_breadcrumb_01a" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ thread ObjectiveRemindUntilFlag( "exited_intel_room2" )
+
+ FlagWait( "exited_intel_room2" )
+
+ objectivePos = GetEntByScriptName( "objective_human_research_breadcrumb_02" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ FlagWait( "entering_human_hallway_room" )
+
+ //thread HumanPodsThink( "biodoors_terminal01_pristine", "biodoors_terminal01_overgrown", player )
+ //thread HumanPodsThinkNoHack( "biodoors_terminal01_pristine", "biodoors_terminal02_overgrown", player )
+ //thread HumanPodsThinkNoHack( "biodoors_terminal02_pristine", "biodoors_terminal02_overgrown", player )
+
+ //-------------------------------
+ // Token stalkers
+ //-------------------------------
+ array< entity > propSpawners = GetEntArrayByScriptName( "stalker_spawnvents_human_hallway_room" )
+ float delayMin = 1.3
+ float delayMax = 3
+ int maxToSpawn = 3
+ string flagToAbort = "entering_human_main_room"
+ string flagToSetWhenAllAreSpawned = ""
+ bool requiresLookAt = false
+ thread SpawnShowcaseGroupWhenInRange( player, propSpawners, maxToSpawn, flagToAbort, flagToSetWhenAllAreSpawned, delayMin, delayMax, "", requiresLookAt )
+
+ FlagWait( "past_human_hall_turrets" )
+ thread QuickSkit( player, GetEntByScriptName( "node_reactor_flyers" ) )
+ CheckPoint()
+
+ FlagClear( "ShowMobilityGhostTurretFlank" )
+
+
+ FlagWait( "entering_human_anteroom" )
+
+ //entity rings_pristine = GetEntByScriptName( "rings_pristine" )
+
+ //Spawn a sound dummy model to attach the sound to since doing it on an info_target
+ //or "AtPosition" is unreliable with Timeshift teleports (can get culled)
+ entity lookEnt = GetEntByScriptName( "lookent_rings" )
+ EmitSoundAtPosition( TEAM_UNASSIGNED, lookEnt.GetOrigin(), "timeshift_scr_rings_spin_slow_lp" )
+
+ FlagSet( "RingsShouldBeSpinning" )
+
+ CheckPoint()
+
+
+ objectivePos = GetEntByScriptName( "objective_human_research_main_door" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ FlagWait( "entering_human_main_room" )
+
+}
+
+
+
+
+
+
+void function GruntsSphereRoomThink( entity npc )
+{
+ //TODO: make these guys constanly get the player as an enemy
+ if ( !IsValid( npc ) )
+ return
+
+ npc.EndSignal( "OnDeath" )
+
+ while( true )
+ {
+ AttackPlayer( npc )
+ wait RandomFloatRange( 2, 5 )
+ }
+
+
+
+}
+void function CheckpointSphereRoomOvergrown( entity player )
+{
+ FlagEnd( "entering_human_anteroom" )
+ FlagWait( "sphere_room_stalkers_dead" )
+ CheckPoint()
+}
+
+void function CheckpointSphereRoomPristine( entity player )
+{
+ FlagEnd( "entering_human_anteroom" )
+ FlagWait( "sphere_room_pristine_enemies_dead" )
+ CheckPoint()
+}
+
+void function DialogueHumanAnteroom( entity player )
+{
+ FlagWait( "entering_human_anteroom" )
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ //General Marder - Radio Spin up the outer rings. Test sequence will commence once Sculptor Core is in place.
+ thread PlayTimeShiftDialogue( player, player, "diag_sp_miniSculptor_TS221_02_01_imc_genMarder" )
+
+
+}
+
+void function TurretNotargetHack( entity player )
+{
+ if( Flag( "entering_human_main_room") )
+ return
+ FlagEnd( "entering_human_main_room" )
+ OnThreadEnd(
+ function() : ( player )
+ {
+ if ( IsValid( player ) )
+ player.SetNoTarget( false )
+ }
+ )
+ while( true )
+ {
+ FlagWait( "player_no_target" )
+ player.SetNoTarget( true )
+ FlagWaitClear( "player_no_target" )
+ player.SetNoTarget( false )
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicSphereRoom( entity player )
+{
+ FlagWait( "StartAndersonHologram2" )
+
+ //FlagWait( "AndersonHologram2Playing" )
+
+ // When the third Anderson log starts - Play music_timeshift_25_andersonlog03
+ // At the same time - Play music_timeshift_21c_pastloop_stop
+ StopMusic()
+ PlayMusic( "music_timeshift_25_andersonlog03" )
+
+ if ( IsValid( player ) )
+ {
+ StopSoundOnEntity( player, "music_timeshift_14_pastloop" )
+ printl( "manually stopping music: music_timeshift_14_pastloop")
+ }
+
+ PlayMusicThatCantBeStopped( "music_timeshift_21c_pastloop_stop" )
+
+ //When the door drops down revealing the dudes
+ FlagWaitAny( "open_door_diorama2_exit_pristine", "open_door_diorama2_exit_overgrown" )
+
+ StopMusic()
+ PlayMusicThatCantBeStopped( "music_timeshift_24_ambush" )
+ SetGlobalNetBool( "music14LoopPausable", false )
+ PlayMusicThatCantBeStopped( "music_timeshift_14_pastloop" )
+
+ // Following the ambush, when the player switches to the PRESENT - Play music_timeshift_16_explorepresent
+ FlagWait( "AndersonHologram2Finished" )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+
+ thread PlayMusicInTimezoneUntilFlag( "music_timeshift_16_explorepresent", TIMEZONE_NIGHT, "entering_human_anteroom" )
+
+
+ FlagWait( "entering_human_anteroom" )
+
+ // When you enter human testing - Play music_timeshift_26_humanresearch
+ // At the same time - Play music_timeshift_21c_pastloop_stop
+
+ wait 0.1
+
+ StopMusic()
+ if ( IsValid( player ) )
+ {
+ StopSoundOnEntity( player, "music_timeshift_14_pastloop" )
+ printl( "manually stopping music: music_timeshift_14_pastloop")
+ }
+
+ PlayMusicThatCantBeStopped( "music_timeshift_21c_pastloop_stop" )
+
+ PlayMusic( "music_timeshift_26_humanresearch" )
+
+
+
+}
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueLabBravo( entity player )
+{
+ FlagWaitAny( "LabBravoEnemiesDead", "player_near_intel_room_2_landing_pad" )
+
+ FlagWait( "player_inside_intel_room2" )
+
+ FlagWait( "player_inside_intel_room2_halfway" )
+
+ FlagClear( "open_doors_sphere_room_entrance_all" )
+
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+ FlagSet( "StartAndersonHologram2" )
+ FlagSetDelayed( "AndersomHologram2AboutToStart", 3)
+
+
+ FlagWait( "AndersonHologram2Finished" )
+
+ wait 0.5
+
+
+
+}
+
+
+void function DialogueGunshipDeploys( entity player )
+{
+
+ /*
+ FlagWaitAny( "LabBravoEnemiesDead", "player_inside_intel_room2_halfway" )
+
+
+ //FlagWait( "LookingAtPad" )
+
+ entity soundEnt = CreateLoudspeakerEnt( GetEntByScriptName( "lookent_pad" ).GetOrigin() )
+
+ FlagWait( "AndersonHologram2Finished" )
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ //waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ if ( !Flag( "AndersomHologram2AboutToStart" ) )
+ {
+ //Scientist 5 (Radio) Sculptor Core prepped for delivery and en route to the test chamber.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_miniSculptor_TS221_01_01_imc_scientist5" )
+ }
+
+ */
+
+ FlagWait( "StartSphereRoomGunship")
+
+ wait 1
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ entity soundEnt = CreateLoudspeakerEnt( GetEntByScriptName( "lookent_pad" ).GetOrigin() )
+
+ //Scientist 5 (Radio) Sculptor Core prepped for delivery and en route to the test chamber.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_miniSculptor_TS221_01_01_imc_scientist5" )
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function GunshipPadSequenceWait( entity player )
+{
+ FlagEnd( "exited_intel_room2" )
+
+ FlagWait( "AndersonHologram2Finished" )
+
+ entity lookEnt = GetEntByScriptName( "lookent_pad" )
+ //doTrace degrees minDist timeOut trigger, failsafeFlag )
+ waitthread WaitTillLookingAt( player, lookEnt, false, 30, 0, 0, null, "player_near_intel_room_2_landing_pad" )
+
+ FlagSet( "StartSphereRoomGunship" )
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗ ██╗███╗ ███╗ █████╗ ███╗ ██╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║ ██║████╗ ████║██╔══██╗████╗ ██║ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+███████║██║ ██║██╔████╔██║███████║██╔██╗ ██║ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██╔══██║██║ ██║██║╚██╔╝██║██╔══██║██║╚██╗██║ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+██║ ██║╚██████╔╝██║ ╚═╝ ██║██║ ██║██║ ╚████║ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗ ██╗███╗ ███╗ █████╗ ███╗ ██╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║ ██║████╗ ████║██╔══██╗████╗ ██║ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+███████║██║ ██║██╔████╔██║███████║██╔██╗ ██║ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██╔══██║██║ ██║██║╚██╔╝██║██╔══██║██║╚██╗██║ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+██║ ██║╚██████╔╝██║ ╚═╝ ██║██║ ██║██║ ╚████║ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗ ██╗███╗ ███╗ █████╗ ███╗ ██╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║ ██║████╗ ████║██╔══██╗████╗ ██║ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+███████║██║ ██║██╔████╔██║███████║██╔██╗ ██║ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██╔══██║██║ ██║██║╚██╔╝██║██╔══██║██║╚██╗██║ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+██║ ██║╚██████╔╝██║ ╚═╝ ██║██║ ██║██║ ╚████║ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+██╗ ██╗██╗ ██╗███╗ ███╗ █████╗ ███╗ ██╗ ██████╗ ███████╗███████╗███████╗ █████╗ ██████╗ ██████╗██╗ ██╗
+██║ ██║██║ ██║████╗ ████║██╔══██╗████╗ ██║ ██╔══██╗██╔════╝██╔════╝██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║
+███████║██║ ██║██╔████╔██║███████║██╔██╗ ██║ ██████╔╝█████╗ ███████╗█████╗ ███████║██████╔╝██║ ███████║
+██╔══██║██║ ██║██║╚██╔╝██║██╔══██║██║╚██╗██║ ██╔══██╗██╔══╝ ╚════██║██╔══╝ ██╔══██║██╔══██╗██║ ██╔══██║
+██║ ██║╚██████╔╝██║ ╚═╝ ██║██║ ██║██║ ╚████║ ██║ ██║███████╗███████║███████╗██║ ██║██║ ██║╚██████╗██║ ██║
+╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+void function HumanResearchStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointHumanResearch" ) )
+ vector objectivePos = GetEntByScriptName( "objective_human_research_vista" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_LAB_EXPLORE", objectivePos )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function HumanResearchSkipped( entity player )
+{
+ FlagClear( "ShowMobilityGhostHumanLillypad01" )
+ FlagClear( "ShowMobilityGhostHumanLillypad02" )
+ thread ElectricalScreenEffects( player, "inside_human_control_room" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_HumanResearchThread( entity player )
+{
+
+ FlagWait( "entering_human_main_room" )
+ FlagSet( "ShowMobilityGhostHumanLillypad01" )
+ FlagSet( "ShowMobilityGhostHumanLillypad02" )
+
+ //thread DebugX( player )
+
+ thread FlyersHumanRoom()
+ thread MusicHumanRoom( player )
+ thread DialogueHumanRoomStart( player )
+ vector objectivePos = GetEntByScriptName( "objective_human_research_tower1" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ //thread HumanPanelHacks( player )
+ CheckPoint()
+
+ delaythread ( 60 ) TimeshiftHint( player, TIMEZONE_DAY, "reached_concourse_tower1", "timeshift_hint_default", GetEntByScriptName( "trig_player_near_first_liilypad_puzzle_pristine" ) )
+
+
+ FlagWait( "reached_concourse_tower1" )
+
+ objectivePos = GetEntByScriptName( "objective_human_research_fight" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ thread ElectricalScreenEffects( player, "inside_human_control_room" )
+
+ FlagClear( "ShowMobilityGhostHumanLillypad01" )
+
+
+ CheckPoint()
+
+ FlagWait( "inside_human_control_room" )
+
+ objectivePos = GetEntByScriptName( "objective_human_research_tower2" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ FlagSet( "DisplayTheDamageHint" )
+ thread HumanRoomCheckpointSoldiers()
+ thread HumanRoomCheckpointProwlers()
+
+ CheckPoint()
+
+ //-------------------------------
+ // Token prowlers
+ //-------------------------------
+ array< entity > propSpawners = GetEntArrayByScriptName( "prowler_spawnvents_human_control_room" )
+ float delayMin = 2.5
+ float delayMax = 5
+ int maxToSpawn = 1
+ string flagToAbort = "reached_concourse_tower2"
+ string flagToSetWhenAllAreSpawned = "AllProwlersSpawnedInHumanControlRoom"
+ bool requiresLookAt = true
+ thread SpawnShowcaseGroupWhenInRange( player, propSpawners, maxToSpawn, flagToAbort, flagToSetWhenAllAreSpawned, delayMin, delayMax, "", requiresLookAt )
+
+ FlagWait( "reached_concourse_tower2" )
+
+ FlagClear( "DisplayTheDamageHint" )
+ FlagClear( "ShowMobilityGhostHumanLillypad02" )
+}
+
+void function FlyersHumanRoom()
+{
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+ FlagSet( "ForceFlyerTakeoff")
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function HumanRoomCheckpointSoldiers()
+{
+ FlagWait( "inside_human_control_room" )
+ if ( Flag( "reached_concourse_tower2") )
+ return
+ FlagEnd( "reached_concourse_tower2" )
+ FlagWait( "human_room_soldiers_dead" )
+ CheckPoint()
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function HumanRoomCheckpointProwlers()
+{
+ FlagWait( "inside_human_control_room" )
+ if ( Flag( "reached_concourse_tower2") )
+ return
+ FlagEnd( "reached_concourse_tower2" )
+
+ FlagWait( "AllProwlersSpawnedInHumanControlRoom" )
+ FlagWaitClear( "prowlers_alive_in_human_control_room")
+
+ CheckPoint()
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicHumanRoom( entity player )
+{
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function GunshipRingSequenceWait( entity player )
+{
+ FlagWait( "crossed_wallrun_chain" )
+
+ wait 0.25
+
+ entity lookEnt = GetEntByScriptName( "lookent_rings" )
+ //doTrace degrees minDist timeOut trigger, failsafeFlag )
+ waitthread WaitTillLookingAt( player, lookEnt, false, 30, 0, 0, null, "player_crossing_human_bridge" )
+
+ FlagSet( "player_looking_at_reactor_window" )
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueHumanRoomStart( entity player )
+{
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+
+ FlagWait( "entering_human_main_room" )
+
+ //wait 1
+ //Player Option A Were they doing experiments on these people?
+ //BT Option A SRS files indicated large-scale cryogenic stasis for testing on humans for unknown reasons. They are likely not volunteers.
+
+ //Player Option B Who are these people?
+ //BT Option B Scanning... The genetic makeup matches those captured from the distant planet Colony led by former Militia leader MacAllan.
+ //waitthread PlayerConversation( "TsHumanExperiments", player )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+void function HumanPanelHacks( entity player )
+{
+ //--------------------------------------------
+ // Override all security terminals (optional)
+ //----------------------------------------------
+ array< entity > controlPanels
+ controlPanels.append( GetEntByScriptName( "security_panel_concourse_01" ) )
+ //controlPanels.append( GetEntByScriptName( "security_panel_concourse_02" ) )
+ foreach( panel in controlPanels )
+ thread SecurityPanelConcourseThink( panel, player )
+
+
+}
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+void function SecurityPanelConcourseThink( entity panel, entity player )
+{
+ panel.WaitSignal( "PanelReprogram_Success" )
+
+ string flagToSetWhenHacked
+
+ string scriptName = panel.GetScriptName()
+ string laserMeshInstanceName
+ if ( scriptName == "security_panel_concourse_01" )
+ {
+ laserMeshInstanceName = "laser_mesh_concourse_terminal_01"
+ flagToSetWhenHacked = "ConcoursePanelHacked01"
+ }
+ else if ( scriptName == "security_panel_concourse_02" )
+ {
+ laserMeshInstanceName = "laser_mesh_concourse_terminal_02"
+ flagToSetWhenHacked = "ConcoursePanelHacked02"
+ }
+ else
+ Assert( 0, "Can't find lasermesh trigger associated with " + scriptName )
+
+ FlagSet( flagToSetWhenHacked )
+
+ if ( !Flag( "LabRatAcheivementUnlocked" ) )
+ {
+ FlagSet( "LabRatAcheivementUnlocked" )
+ Dev_PrintMessage( player, "#TIMESHIFT_ACHEIVEMENT_HEADING", "#TIMESHIFT_ACHEIVEMENT_TEXT_LAB_RATS", 5 )
+ }
+
+ wait 1.5
+
+ CheckPoint()
+
+ LaserMeshDestroyByInstanceName( laserMeshInstanceName )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_LabRatLasers" )
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+void function HumanPodsThink( string instanceNamePristine, string instanceNameOvergrown, entity player )
+{
+ array< entity > doorsPristine = GetEntArrayByScriptNameInInstance( "bio_pod_door", instanceNamePristine )
+ array< entity > doorsOvergrown = GetEntArrayByScriptNameInInstance( "bio_pod_door", instanceNameOvergrown )
+ Assert( doorsPristine.len() == 4 )
+ Assert( doorsOvergrown.len() == 4 )
+
+ string flagToReleasePrisoners = "security_concourse_01_hacked"
+ //Militia Prisoner 1 What? What where am I?
+ string prisonerDialogue = "diag_sp_humanStudy_TS202_03_01_mcor_prisoner1"
+ if ( instanceNamePristine == "biodoors_terminal02_pristine" )
+ {
+ //Militia Prisoner 2 What's going on? This isn't Colony....
+ string prisonerDialogue = "diag_sp_humanStudy_TS202_04_01_mcor_prisoner2"
+ flagToReleasePrisoners = "security_concourse_02_hacked"
+
+ }
+
+ entity dialogueEnt
+
+ foreach( door in doorsPristine )
+ {
+ if ( !IsValid( dialogueEnt ) )
+ dialogueEnt = CreateLoudspeakerEnt( door.GetOrigin() )
+ thread HumanPodThinkPristine( door )
+ }
+ foreach( door in doorsOvergrown )
+ thread HumanPodThinkOvergrown( door )
+
+ FlagWait( flagToReleasePrisoners )
+
+ foreach( door in doorsOvergrown )
+ door.Signal( "ReleaseLabRat")
+ foreach( door in doorsPristine )
+ door.Signal( "ReleaseLabRat")
+
+ wait 5
+
+ thread PlayTimeShiftDialogue( player, dialogueEnt, prisonerDialogue )
+}
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+void function HumanPodsThinkNoHack( string instanceNamePristine, string instanceNameOvergrown, entity player )
+{
+ array< entity > spawners = GetEntArrayByScriptNameInInstance( "bio_pod_body", instanceNamePristine )
+ foreach( spawner in spawners )
+ thread HumanPodThinkPristine( null, spawner )
+}
+&*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+void function HumanPodThinkPristine( entity door = null, entity bodySpawner = null )
+{
+ entity spawner
+ if ( !bodySpawner )
+ spawner = door.GetLinkEnt()
+ else
+ spawner = bodySpawner
+ string animIdle
+ string animWakeUp
+ string animIdleEnd
+ entity labRat = spawner.SpawnEntity()
+ DispatchSpawn( labRat )
+ Assert( IsValid( labRat) )
+ entity node = CreateScriptRef( labRat.GetOrigin(), labRat.GetAngles() )
+ vector originOffset = PositionOffsetFromEnt( node, -15, 0, 0 )
+ node.SetOrigin( originOffset )
+
+ MakeInvincible( labRat )
+ MakeCivilian( labRat )
+ labRat.SetNoTarget( true )
+ SetTeam( labRat, TEAM_MILITIA )
+ labRat.SetModel( LABRAT_MODEL )
+ Assert( labRat.HasKey( "script_noteworthy") )
+ animIdle = labRat.kv.script_noteworthy + "_start_idle"
+ animWakeUp = labRat.kv.script_noteworthy + "_start"
+ animIdleEnd = labRat.kv.script_noteworthy + "_end_idle"
+
+ thread PlayAnimTeleport( labRat, animIdle, node )
+
+ if ( !door )
+ return
+
+ door.WaitSignal( "ReleaseLabRat" )
+
+ waitthread OpenLabRatDoor( door, labRat )
+
+ labRat.EndSignal( "OnDeath" )
+ wait 0.25
+
+ ClearInvincible( labRat )
+ labRat.e.forceRagdollDeath = true
+
+ waitthread PlayAnim( labRat, animWakeUp, node )
+ thread PlayAnim( labRat, animIdleEnd, node )
+}
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+void function HumanPodThinkOvergrown( entity door )
+{
+ entity body = door.GetLinkEnt()
+
+ door.WaitSignal( "ReleaseLabRat" )
+
+ body.Destroy()
+ OpenLabRatDoor( door, body )
+}
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+void function OpenLabRatDoor( entity door, entity body )
+{
+ entity soundDummy = CreateInfoTarget( body.GetOrigin() + Vector( 0, 0, 72 ), Vector( 0, 0, 0 ) )
+ vector soundOrigin = soundDummy.GetOrigin()
+ entity lookEnt = CreateInfoTarget( body.GetOrigin() + Vector( 0, 0, 72 ), Vector( 0, 0, 0 ) )
+ vector originOffset = PositionOffsetFromEnt( lookEnt, 15, 0, 0 )
+ lookEnt.SetOrigin( originOffset )
+
+ vector fxOrigin = body.GetOrigin()
+ vector fxAngles = body.GetAngles()
+
+ bool snapToOpen = false
+ if ( GetEntityTimelinePosition( door ) == TIMEZONE_NIGHT )
+ snapToOpen = true
+
+ vector startPos = door.GetOrigin()
+ vector endPos = startPos + Vector( 0, 0, -105 )
+
+ if ( snapToOpen == true )
+ {
+ door.SetOrigin( endPos )
+ return
+ }
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ array <entity> players = GetPlayerArray()
+ if ( players.len() <= 0 )
+ return
+ entity player = players[ 0 ]
+ player.EndSignal( "OnDeath" )
+
+ //WaitTillLookingAt( entity player, entity ent, bool doTrace, float degrees, float minDist = 0, float timeOut = 0, entity trigger = null, string failsafeFlag = "" )
+ waitthread WaitTillLookingAt( player, lookEnt, true, 45, 0, 3 )
+
+ wait( RandomFloatRange( 0, 0.75 ) )
+ entity mover = CreateScriptMover( door.GetOrigin(), door.GetAngles() )
+ door.SetParent( mover )
+ float moveTime = 5
+
+ mover.NonPhysicsMoveTo( endPos, moveTime, moveTime*0.4, moveTime*0.4 )
+
+
+ EmitSoundAtPosition( TEAM_UNASSIGNED, soundOrigin, "Timeshift_Scr_LabRatPodDoor_Open" )
+ //EmitSoundOnEntity( soundDummy, "door_open_loop" )
+ PlayFX( FX_HUMAN_DOOR_OPEN, fxOrigin, fxAngles )
+
+ wait moveTime
+
+ //StopSoundOnEntity( soundDummy, "door_open_loop" )
+ //EmitSoundAtPosition( TEAM_UNASSIGNED, soundOrigin, "door_stop" )
+
+}
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+ ██████╗ █████╗ ███╗ ███╗██████╗ ██╗ ██╗███████╗ ██████╗ ███████╗████████╗██╗ ██╗██████╗ ███╗ ██╗
+██╔════╝██╔══██╗████╗ ████║██╔══██╗██║ ██║██╔════╝ ██╔══██╗██╔════╝╚══██╔══╝██║ ██║██╔══██╗████╗ ██║
+██║ ███████║██╔████╔██║██████╔╝██║ ██║███████╗ ██████╔╝█████╗ ██║ ██║ ██║██████╔╝██╔██╗ ██║
+██║ ██╔══██║██║╚██╔╝██║██╔═══╝ ██║ ██║╚════██║ ██╔══██╗██╔══╝ ██║ ██║ ██║██╔══██╗██║╚██╗██║
+╚██████╗██║ ██║██║ ╚═╝ ██║██║ ╚██████╔╝███████║ ██║ ██║███████╗ ██║ ╚██████╔╝██║ ██║██║ ╚████║
+ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+ ██████╗ █████╗ ███╗ ███╗██████╗ ██╗ ██╗███████╗ ██████╗ ███████╗████████╗██╗ ██╗██████╗ ███╗ ██╗
+██╔════╝██╔══██╗████╗ ████║██╔══██╗██║ ██║██╔════╝ ██╔══██╗██╔════╝╚══██╔══╝██║ ██║██╔══██╗████╗ ██║
+██║ ███████║██╔████╔██║██████╔╝██║ ██║███████╗ ██████╔╝█████╗ ██║ ██║ ██║██████╔╝██╔██╗ ██║
+██║ ██╔══██║██║╚██╔╝██║██╔═══╝ ██║ ██║╚════██║ ██╔══██╗██╔══╝ ██║ ██║ ██║██╔══██╗██║╚██╗██║
+╚██████╗██║ ██║██║ ╚═╝ ██║██║ ╚██████╔╝███████║ ██║ ██║███████╗ ██║ ╚██████╔╝██║ ██║██║ ╚████║
+ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+ ██████╗ █████╗ ███╗ ███╗██████╗ ██╗ ██╗███████╗ ██████╗ ███████╗████████╗██╗ ██╗██████╗ ███╗ ██╗
+██╔════╝██╔══██╗████╗ ████║██╔══██╗██║ ██║██╔════╝ ██╔══██╗██╔════╝╚══██╔══╝██║ ██║██╔══██╗████╗ ██║
+██║ ███████║██╔████╔██║██████╔╝██║ ██║███████╗ ██████╔╝█████╗ ██║ ██║ ██║██████╔╝██╔██╗ ██║
+██║ ██╔══██║██║╚██╔╝██║██╔═══╝ ██║ ██║╚════██║ ██╔══██╗██╔══╝ ██║ ██║ ██║██╔══██╗██║╚██╗██║
+╚██████╗██║ ██║██║ ╚═╝ ██║██║ ╚██████╔╝███████║ ██║ ██║███████╗ ██║ ╚██████╔╝██║ ██║██║ ╚████║
+ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+ ██████╗ █████╗ ███╗ ███╗██████╗ ██╗ ██╗███████╗ ██████╗ ███████╗████████╗██╗ ██╗██████╗ ███╗ ██╗
+██╔════╝██╔══██╗████╗ ████║██╔══██╗██║ ██║██╔════╝ ██╔══██╗██╔════╝╚══██╔══╝██║ ██║██╔══██╗████╗ ██║
+██║ ███████║██╔████╔██║██████╔╝██║ ██║███████╗ ██████╔╝█████╗ ██║ ██║ ██║██████╔╝██╔██╗ ██║
+██║ ██╔══██║██║╚██╔╝██║██╔═══╝ ██║ ██║╚════██║ ██╔══██╗██╔══╝ ██║ ██║ ██║██╔══██╗██║╚██╗██║
+╚██████╗██║ ██║██║ ╚═╝ ██║██║ ╚██████╔╝███████║ ██║ ██║███████╗ ██║ ╚██████╔╝██║ ██║██║ ╚████║
+ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝
+ */
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+void function CampusReturnStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointCampusReturn" ) )
+ vector objectivePos = GetEntByScriptName( "objective_human_research_vista" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_LAB_EXPLORE", objectivePos )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function CampusReturnSkipped( entity player )
+{
+ FlagSet( "CampusReturnConversationFinished" )
+ FlagClear( "ShowMobilityGhostHumanWallrunChain" )
+ FlagClear( "ShowMobilityGhostPowertech" )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_CampusReturnThread( entity player )
+{
+ FlagWait( "reached_concourse_tower2" )
+
+ vector objectivePos = GetEntByScriptName( "objective_human_research_vista" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ thread ObjectiveRemindUntilFlag( "crossed_wallrun_chain" )
+
+ FlagSet( "ShowMobilityGhostHumanWallrunChain" )
+ FlagSet( "ShowMobilityGhostPowertech" )
+
+ CheckPoint()
+ thread ArtifactLaunchThink( player )
+ thread BridgeThink()
+ thread MusicCampusReturn( player )
+ thread GunshipRingSequenceWait( player )
+ thread GunshipSequence( "gunship_rings", player, "node_gunship_rings", "rings", "player_looking_at_reactor_window" )
+
+ FlagWait( "crossed_wallrun_chain" )
+
+ wait 0.25
+
+ //Checkpoint done with a trigger with safe spot here
+
+ objectivePos = GetEntByScriptName( "objective_return_breadcrumb00" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ thread DialogueHumanRoomEnd( player )
+
+ FlagSet( "finishedHumanVistaSequence" )
+
+
+ thread HumanBridgeEnemies( player )
+ thread HumanBridgeOvergrownThink( player )
+
+
+ FlagWait( "entered_powertech_return" )
+
+ objectivePos = GetEntByScriptName( "objective_return_breadcrumb01" ).GetOrigin()
+ TimeshiftSetObjective( player, "#TIMESHIFT_OBJECTIVE_RETURN", objectivePos )
+
+ CheckPoint()
+
+ FlagWait( "approaching_fan_drop" )
+}
+
+void function BridgeThink()
+{
+ FlagWait( "bridge_control_panel_pressed" )
+ FlagClear( "retract_bridge_human_01" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function HumanBridgeOvergrownThink( entity player )
+{
+ //Show it when enemies extend it in other time zone
+ FlagWaitClear( "retract_bridge_human_01" )
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ ShowStuff( "human_bridge_overgrown" )
+
+
+ //Hide it again if player manually retracts it
+ //FlagWait( "retract_bridge_human_01" )
+
+ //waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ //HideStuff( "human_bridge_overgrown" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicCampusReturn( entity player )
+{
+ FlagWait( "crossing_wallrun_chain" )
+
+ StopMusic()
+ PlayMusic( "music_timeshift_27_towardthemachine" )
+
+ FlagWait( "spawnHumanBridgeEnemies" )
+
+ //Only play drone spawn music if player is actually in the trigger spawning the drones
+
+ if ( !Flag( "player_touching_drone_spawn_area_bridge_pristine") )
+ return
+
+ StopMusic()
+ PlayMusic( "music_timeshift_28_bridge" )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function ArtifactLaunchThink( entity player )
+{
+ entity arkShell = GetEntByScriptName( "core_model_pristine" )
+ entity arkSphere = GetEntByScriptName( "core_glow_model_pristine" )
+ vector startPos = arkShell.GetOrigin()
+ vector startAng = arkShell.GetAngles()
+ vector endPos = GetEntByScriptName( "artifact_ring_startpoint" ).GetOrigin()
+
+ entity fxLaunchGlow = PlayLoopFXOnEntity( FX_ARK_LAUNCH_GLOW, arkShell )
+ entity mover = CreateScriptMover( startPos, startAng )
+ arkSphere.SetParent( arkShell )
+ arkShell.SetParent( mover )
+ float moveTime = 2
+
+ FlagWait( "crossed_wallrun_chain" )
+
+ wait 0.25
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ wait 0.1
+
+ mover.NonPhysicsMoveTo( endPos, moveTime, moveTime*0.4, moveTime*0.4 )
+ EmitSoundOnEntity( player, "timeshift_scr_core_rise_start" )
+
+ wait moveTime
+
+ entity fxLaunchInPlace = PlayFXOnEntity( FX_ARK_LAUNCH_IN_PLACE, arkShell )
+
+ //StopSoundOnEntity( player, "timeshift_scr_core_rise_start" )
+ EmitSoundAtPosition( TEAM_UNASSIGNED, endPos, "timeshift_scr_core_rise_end" )
+ EmitSoundAtPosition( TEAM_UNASSIGNED, endPos, "timeshift_scr_core_pulse" )
+ //CreateShake( vector org, float amplitude = 16, float frequency = 150, float duration = 1.5, float radius = 2048 )
+ thread CreateAirShake( startPos, 32, 200, 1.5, 10000 )
+ thread CreateShakeWhileFlagSet( 0.5, 0.5, 1, "player_near_rings", "DoneWithFanDropSequence" )
+
+ FlagSet( "RingVistaSequenceComplete" )
+
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueHumanRoomEnd( entity player )
+{
+
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+ FlagWait( "crossed_wallrun_chain" )
+
+ wait 0.25
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ //Scientist 5 PA Ark successfully delivered to fold weapon rings. Commencing test run.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_humanStudy_TS203_01_01_imc_sci" )
+
+ //FlagWaitAny( "human_bridge_soldiers_dead", "entered_powertech_return" )
+
+ FlagWaitAny( "RingVistaSequenceComplete", "player_crossing_human_bridge" )
+
+
+ //BT: Pilot, the rings at my location contain a large amount of residual energy. This was the Ark's final destination.
+ waitthread PlayBTDialogue( "diag_sp_targeting_TS231_01_01_mcor_bt" )
+
+ //BT: Anderson's plan indicated a recon mission within close proximity to the center of the active rings.
+ waitthread PlayBTDialogue( "diag_sp_targeting_TS231_07_01_mcor_bt" )
+
+ if ( !Flag( "approaching_fan_drop" ) )
+ {
+ // Player (Option A) You want me to do what?
+ // Player (Option B) Are you sure I'll be safe over there? (diag_sp_pristine_TS242_03_01_mcor_player)
+
+ // BT (Option A) If we can obtain the Ark's energy signature, the Militia fleet will be able to track its current location in the present day.
+ // BT (Option B) No. But a true Militia Pilot takes risks for the welfare of others. As did Major Anderson and Captain Lastimosa before you. (diag_sp_pristine_TS242_04_01_mcor_bt)
+
+ waitthread PlayerConversationStopOnFlag( "TsSeeingCoreFlownToRings", player, "entered_powertech_return" )
+ }
+
+ FlagSet( "CampusReturnConversationFinished" )
+
+ FlagSet( "spawnHumanBridgeEnemies" )
+
+
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function HumanBridgeEnemies( entity player )
+{
+ FlagWait( "finishedHumanVistaSequence" )
+
+ entity lookEnt = GetEntByScriptName( "look_ent_human_bridge" )
+ entity trigger = GetEntByScriptName( "trig_player_at_human_vista_pristine" )
+ //doTrace degrees minDist timeOut trigger, failsafeFlag )
+ waitthread WaitTillLookingAt( player, lookEnt, true, 30, 0, 0, trigger, "player_crossing_human_bridge" )
+
+
+ //entity triggerBridgeVolume = GetEntByScriptName( "trigger_bridge_human_volume" )
+ //entity bridge = GetEntByScriptName( "human_bridge" )
+ //FlagSet( "spawnHumanBridgeEnemies" )
+
+ /*
+ //FlagClearDelayed( "retract_bridge_human_01", 3 )
+
+ FlagWait( "retract_bridge_control_panel_pressed" )
+ FlagSet( "retract_bridge_human_01" )
+ bridge.NotSolid()
+
+ SetGlobalForcedDialogueOnly( true )
+ bool screamPlayed = false
+ array<entity> ai = GetNPCArrayByClass( "npc_soldier" )
+ entity tempNode
+ float delayTime = 0
+ string floorDropAnim = "pt_react_bridgedrop_A"
+ foreach( guy in ai )
+ {
+ if ( !triggerBridgeVolume.IsTouching( guy ) )
+ continue
+
+ if ( IsAlive( guy ) )
+ {
+ //guy.NotSolid()
+ if ( screamPlayed == false )
+ {
+ EmitSoundOnEntity( guy, "Grunt_DroppedByFlyer" )
+ screamPlayed = true
+ }
+ if ( CoinFlip() )
+ floorDropAnim = "pt_react_bridgedrop_B"
+ tempNode = CreateScriptMover( guy.GetOrigin(), guy.GetAngles() )
+ guy.SetParent( tempNode )
+ delayTime = RandomFloatRange( 0, 0.3 )
+ delaythread ( delayTime ) PlayAnim( guy, floorDropAnim, tempNode )
+ //guy.TakeDamage( guy.GetHealth() / 2, null, null, { damageSourceId=damagedef_suicide } )
+ }
+ }
+ if ( screamPlayed == true )
+ {
+ delaythread ( 2 ) Dev_PrintMessage( player, "#TIMESHIFT_ACHEIVEMENT_HEADING", "#TIMESHIFT_ACHEIVEMENT_TEXT_BRIDGE_FALL", 5 )
+ }
+
+ wait 1
+
+ SetGlobalForcedDialogueOnly( false )
+
+ DestroyIfValid( "human_bridge" )
+ */
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗ █████╗ ███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗
+██╔════╝██╔══██╗████╗ ██║ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗
+█████╗ ███████║██╔██╗ ██║ ██║ ██║██████╔╝██║ ██║██████╔╝
+██╔══╝ ██╔══██║██║╚██╗██║ ██║ ██║██╔══██╗██║ ██║██╔═══╝
+██║ ██║ ██║██║ ╚████║ ██████╔╝██║ ██║╚██████╔╝██║
+╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗ █████╗ ███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗
+██╔════╝██╔══██╗████╗ ██║ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗
+█████╗ ███████║██╔██╗ ██║ ██║ ██║██████╔╝██║ ██║██████╔╝
+██╔══╝ ██╔══██║██║╚██╗██║ ██║ ██║██╔══██╗██║ ██║██╔═══╝
+██║ ██║ ██║██║ ╚████║ ██████╔╝██║ ██║╚██████╔╝██║
+╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗ █████╗ ███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗
+██╔════╝██╔══██╗████╗ ██║ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗
+█████╗ ███████║██╔██╗ ██║ ██║ ██║██████╔╝██║ ██║██████╔╝
+██╔══╝ ██╔══██║██║╚██╗██║ ██║ ██║██╔══██╗██║ ██║██╔═══╝
+██║ ██║ ██║██║ ╚████║ ██████╔╝██║ ██║╚██████╔╝██║
+╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗ █████╗ ███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗
+██╔════╝██╔══██╗████╗ ██║ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗
+█████╗ ███████║██╔██╗ ██║ ██║ ██║██████╔╝██║ ██║██████╔╝
+██╔══╝ ██╔══██║██║╚██╗██║ ██║ ██║██╔══██╗██║ ██║██╔═══╝
+██║ ██║ ██║██║ ╚████║ ██████╔╝██║ ██║╚██████╔╝██║
+╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function FanDropStartPointSetup( entity player )
+{
+ //entity temp = CreateInfoTarget( Vector( 3536, -4641, -127), Vector( 35.5, -90, 0 ) )
+ //TeleportPlayerToEnt( player, temp )
+
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointFanDrop" ) )
+ vector objectivePos = GetEntByScriptName( "objective_concourse_panel" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_RETURN", objectivePos )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function FanDropSkipped( entity player )
+{
+ CleanupEnts( "rings_pristine" )
+ FlagSet( "approaching_fan_drop" )
+ FlagSet( "DoneWithFanDropSequence" )
+ thread QuickSkit( player, GetEntByScriptName( "node_labC_deathpose_overgrown" ), "approaching_fan_drop" )
+ thread QuickSkit( player, GetEntByScriptName( "node_labC_deathpose_pristine" ), "approaching_fan_drop" )
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_FanDropThread( entity player )
+{
+ FlagWait( "approaching_fan_drop" )
+
+ thread MusicFanDrop( player )
+ thread FanDropTeleport( player )
+ thread QuickSkit( player, GetEntByScriptName( "node_labC_deathpose_overgrown" ), "approaching_fan_drop" )
+ thread QuickSkit( player, GetEntByScriptName( "node_labC_deathpose_pristine" ), "approaching_fan_drop" )
+ thread FanDropLanding( player )
+
+ vector objectivePos = GetEntByScriptName( "objective_return_breadcrumb01" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+
+
+ FlagWait( "doing_fan_drop_pristine" )
+
+
+ while( true )
+ {
+ FlagWait( "exited_fan_drop" )
+
+ WaitEndFrame() //even if player hit the "exited_fan_drop", he might already be starting a quickDeath
+
+ if ( player.p.doingQuickDeath )
+ {
+ printl( "player doing quickDeath...waiting 2 secs")
+ wait 2
+ printl( "Waiting to exit fan drop..." )
+ continue
+ }
+ else
+ {
+ if ( IsAlive( player ) )
+ thread FanDropQuickdeathFailsafe( player )
+ break
+ }
+
+ }
+
+
+ FlagSet( "DoneWithFanDropSequence" )
+
+}
+
+void function FanDropQuickdeathFailsafe( entity player )
+{
+ player.EndSignal( "OnDeath" )
+ //If player gets into a state where the game thinks he has exited the fan sequence, but is in fact doing a quick death, restart from last checkpoint
+ wait 0.5
+ if ( player.p.doingQuickDeath )
+ player.TakeDamage( 9999, null, null, { damageSourceId=damagedef_suicide } )
+}
+
+void function FanDropLanding( entity player )
+{
+
+ entity node = GetEntByScriptName( "checkpointFanDropEnd" )
+ entity nodePristine = CreateScriptRef( node.GetOrigin() + Vector( 0, 0, TIME_ZOFFSET ), node.GetAngles() )
+
+ FlagWait( "DoneWithFanDropSequence" )
+
+
+
+ printl( "Done with fan drop...playing land anim" )
+
+ player.FreezeControlsOnServer()
+ level.allowTimeTravel = false
+ ShowStuff( "blocker_fandrop_pristine" )
+ ShowStuff( "blocker_fandrop_overgrown" )
+
+ player.DisableWeapon()
+ player.ForceStand()
+
+
+ waitthread AdjustPlayerTimelineHack( player, true )
+
+ WaitFrame()
+ if ( GetEntityTimelinePosition( player ) == TIMEZONE_NIGHT )
+ waitthread PlayerDropLand( player, node, true )
+ else
+ waitthread PlayerDropLand( player, nodePristine, true )
+
+ waitthread AdjustPlayerTimelineHack( player )
+
+ wait 0.5
+ player.UnfreezeControlsOnServer()
+ level.allowTimeTravel = true
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AdjustPlayerTimelineHack( entity player, bool isBeforePlayerLandAnim = false )
+{
+ vector newPos
+ var playerCurrentTimeline = GetEntityTimelinePosition( player )
+
+ if ( playerCurrentTimeline != level.timeZone )
+ {
+ printl( "*********WARNING***************" )
+ printl( "Rare bug: Player timeline and level timeline don't match....adjusting player pos" )
+ printl( "Adjusting before player land animation: " + isBeforePlayerLandAnim )
+ printl( "*******************************" )
+ newPos = GetPosInOtherTimeline( player.GetOrigin() )
+ player.SetOrigin( newPos )
+ }
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function FanDropTeleport( entity player )
+{
+ player.EndSignal( "OnDeath" )
+ FlagEnd( "DoneWithFanDropSequence" )
+ entity orgFanDropOvergrownMain = GetEntByScriptName( "fandrop_start_overgrown_main" )
+ entity orgFanDropOvergrownAlt = GetEntByScriptName( "fandrop_start_overgrown_alt" )
+ vector vectorOffset = orgFanDropOvergrownAlt.GetOrigin() - orgFanDropOvergrownMain.GetOrigin()
+
+
+ while( true )
+ {
+ //wait till player timeshifts past first fire
+ FlagWait( "doing_fan_drop_pristine" )
+
+ //now wait till he switches back to dodge the spinning fan
+ FlagWait( "past_first_spinning_fan_and_back_in_overgrown" )
+ //WaittillPlayerSwitchesTimezone( TIMEZONE_NIGHT )
+
+ //if we haven't died yet, do the teleport while in overgrown
+ if ( CanDoFanTeleport( player, vectorOffset ) )
+ player.SetOrigin( player.GetOrigin() + vectorOffset )
+
+ //otherwise, we died, wait for player to be in reset pos
+ else
+ FlagWait( "standing_at_top_of_fan" )
+
+ }
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+bool function CanDoFanTeleport( entity player, vector vectorOffset )
+{
+ //trying to teleport while in overgrown
+
+ if ( !IsValid( player ) )
+ return false
+
+ player.EndSignal( "OnDeath" )
+
+ if ( Flag( "standing_at_top_of_fan" ) )
+ return false
+ if ( !Flag( "dropping_down_fan" ) )
+ return false
+ if ( player.p.doingQuickDeath )
+ return false
+ if ( GetEntityTimelinePosition( player ) != TIMEZONE_NIGHT )
+ return false
+ if ( GetTimelinePosition( player.GetOrigin() + vectorOffset ) != TIMEZONE_NIGHT )
+ return false
+
+ return true
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicFanDrop( entity player )
+{
+ if ( Flag( "StartAndersonHologram3") )
+ return
+
+ FlagEnd( "StartAndersonHologram3")
+
+ OnThreadEnd(
+ function() : ()
+ {
+ FlagSet( "BrokeOutOfFanDropMusicLoop")
+ }
+ )
+ while( true )
+ {
+ FlagWait( "dropping_down_fan" )
+ StopMusic()
+ PlayMusic( "music_timeshift_29_downtherabbithole" )
+ wait 2
+ FlagWait( "standing_at_top_of_fan" )
+ StopMusic()
+
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗ █████╗ ███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗███╗ ██╗██████╗
+██╔════╝██╔══██╗████╗ ██║ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗ ██╔════╝████╗ ██║██╔══██╗
+█████╗ ███████║██╔██╗ ██║ ██║ ██║██████╔╝██║ ██║██████╔╝ █████╗ ██╔██╗ ██║██║ ██║
+██╔══╝ ██╔══██║██║╚██╗██║ ██║ ██║██╔══██╗██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██║ ██║
+██║ ██║ ██║██║ ╚████║ ██████╔╝██║ ██║╚██████╔╝██║ ███████╗██║ ╚████║██████╔╝
+╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗ █████╗ ███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗███╗ ██╗██████╗
+██╔════╝██╔══██╗████╗ ██║ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗ ██╔════╝████╗ ██║██╔══██╗
+█████╗ ███████║██╔██╗ ██║ ██║ ██║██████╔╝██║ ██║██████╔╝ █████╗ ██╔██╗ ██║██║ ██║
+██╔══╝ ██╔══██║██║╚██╗██║ ██║ ██║██╔══██╗██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██║ ██║
+██║ ██║ ██║██║ ╚████║ ██████╔╝██║ ██║╚██████╔╝██║ ███████╗██║ ╚████║██████╔╝
+╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗ █████╗ ███╗ ██╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗███╗ ██╗██████╗
+██╔════╝██╔══██╗████╗ ██║ ██╔══██╗██╔══██╗██╔═══██╗██╔══██╗ ██╔════╝████╗ ██║██╔══██╗
+█████╗ ███████║██╔██╗ ██║ ██║ ██║██████╔╝██║ ██║██████╔╝ █████╗ ██╔██╗ ██║██║ ██║
+██╔══╝ ██╔══██║██║╚██╗██║ ██║ ██║██╔══██╗██║ ██║██╔═══╝ ██╔══╝ ██║╚██╗██║██║ ██║
+██║ ██║ ██║██║ ╚████║ ██████╔╝██║ ██║╚██████╔╝██║ ███████╗██║ ╚████║██████╔╝
+╚═╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝╚═╝ ╚═══╝╚═════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+void function FanDropEndStartPointSetup( entity player )
+{
+ TeleportPlayerToEnt( player, GetEntByScriptName( "checkpointFanDropEnd" ) )
+ vector objectivePos = GetEntByScriptName( "objective_concourse_panel" ).GetOrigin()
+ TimeshiftSetObjectiveSilent( player, "#TIMESHIFT_OBJECTIVE_RETURN", objectivePos )
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function FanDropEndSkipped( entity player )
+{
+
+ CleanupEnts( "triggers_instadeath_humanroom" )
+ CleanupEnts( "triggers_quickdeath_humanroom" )
+ CleanupEnts( "trigger_quickdeath_checkpoint_humanroom" )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function AA_FanDropEndThread( entity player )
+{
+ FlagWait( "DoneWithFanDropSequence" )
+
+
+ CleanupEnts( "rings_pristine" )
+ CleanupEnts( "triggers_instadeath_humanroom" )
+ CleanupEnts( "triggers_quickdeath_humanroom" )
+ CleanupEnts( "trigger_quickdeath_checkpoint_humanroom" )
+
+ Remote_CallFunction_Replay( player, "ServerCallback_ShowHologramTitles" )
+ thread MusicFanDropEnd( player)
+ thread StalkerDoorSequences( player )
+ thread DialogueLabCharlie( player )
+ thread DialogueTransitionHall( player )
+ delaythread ( 1 ) AndersonHologramSequence( player, "node_hologram_lab3", "StartAndersonHologram3" )
+
+ vector objectivePos = GetEntByScriptName( "objective_concourse_panel_breadcrumb_01" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+
+ wait 2
+
+ CheckPoint()
+
+
+ FlagWait( "exited_intel_room3" )
+
+ objectivePos = GetEntByScriptName( "objective_concourse_panel" ).GetOrigin()
+ TimeshiftUpdateObjective( player, objectivePos )
+
+ //-------------------------------
+ // Token overgrown/pristine wall Spectres
+ //-------------------------------
+ array< entity > propSpawners = GetEntArrayByScriptNameInInstance( "spectre_door_spawner", "spectre_spawner_return_overgrown" )
+ float delayMin = 0
+ float delayMax = 0.4
+ int maxToSpawn = 1
+ string flagToAbort = "transition_hallway_return_finished"
+ string flagToSetWhenSpectreSpawned = ""
+ bool requiresLookAt = true
+ thread SpawnShowcaseGroupWhenInRange( player, propSpawners, maxToSpawn, flagToAbort, "", delayMin, delayMax, flagToSetWhenSpectreSpawned, requiresLookAt )
+
+ propSpawners = GetEntArrayByScriptNameInInstance( "spectre_door_spawner", "spectre_spawner_return_pristine" )
+ delayMin = 0
+ delayMax = 0.4
+ maxToSpawn = 1
+ flagToAbort = "transition_hallway_return_finished"
+ flagToSetWhenSpectreSpawned = ""
+ requiresLookAt = true
+ thread SpawnShowcaseGroupWhenInRange( player, propSpawners, maxToSpawn, flagToAbort, "", delayMin, delayMax, flagToSetWhenSpectreSpawned, requiresLookAt )
+
+
+ FlagWait( "transition_hallway_return_finished" )
+
+
+
+ //ScreenFadeToBlack( player, 1.5, 5 )
+ //wait 1.5
+ //player.SetInvulnerable()
+ //player.FreezeControlsOnServer()
+
+ thread TransitionSpoke1()
+}
+
+
+void function TransitionSpoke1()
+{
+ LevelTransitionStruct trans = SaveBoyleAudioLogs()
+ if ( level.timeZone == TIMEZONE_NIGHT )
+ trans.timeshiftMostRecentTimeline = 1
+ else
+ trans.timeshiftMostRecentTimeline = 0
+
+ PickStartPoint( "sp_hub_timeshift", "PRISTINE CAMPUS", trans )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function MusicFanDropEnd( entity player )
+{
+ FlagWait( "StartAndersonHologram3" )
+ FlagWait( "BrokeOutOfFanDropMusicLoop" )
+
+ //FlagWait( "AndersonHologram3Playing" )
+
+ //StopMusic()
+ PlayMusicThatCantBeStopped( "music_timeshift_30_andersonlog04")
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function StalkerDoorSequences( entity player )
+{
+
+ thread QuickSkit( player, GetEntByScriptName( "node_intel_room3_stalker_door_overgrown" ), "player_near_intel3_exit", GetEntByScriptName( "intel3_exit_overgrown_look_ent" ), GetEntByScriptName( "trig_approaching_lab3_exit_overgrown" ) )
+ thread QuickSkit( player, GetEntByScriptName( "node_intel_room3_stalker_door_pristine" ), "player_near_intel3_exit", GetEntByScriptName( "intel3_exit_pristine_look_ent" ), GetEntByScriptName( "trig_approaching_lab3_exit_pristine" ) )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueLabCharlie( entity player )
+{
+
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+ FlagWait( "DoneWithFanDropSequence" )
+
+ wait 1.5
+
+ FlagSet( "StartAndersonHologram3" )
+
+
+ FlagWaitAny( "AndersonHologram3Finished", "exited_intel_room3" )
+
+ wait 0.75
+
+ //That was Major Anderson's final recording.
+ waitthread PlayBTDialogue( "diag_sp_targeting_TS232_02_01_mcor_bt" )
+
+ while( true )
+ {
+ wait 0.25
+ if ( IsAudioLogPlaying( player ) )
+ continue
+
+ else
+ {
+ //Cooper, based on your recon of this facility, I may have a plan. Meet me outside. diag_sp_targeting_TS232_03_01_mcor_bt
+ waitthread PlayBTDialogue( "diag_sp_targeting_TS232_03_01_mcor_bt" )
+ Objective_Remind()
+ break
+ }
+ }
+
+ thread ObjectiveRemindUntilFlag( "transition_hallway_return_finished" )
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+void function DialogueTransitionHall( entity player )
+{
+
+
+/*
+██████╗ ██╗ █████╗ ██╗ ██████╗ ██████╗ ██╗ ██╗███████╗
+██╔══██╗██║██╔══██╗██║ ██╔═══██╗██╔════╝ ██║ ██║██╔════╝
+██║ ██║██║███████║██║ ██║ ██║██║ ███╗██║ ██║█████╗
+██║ ██║██║██╔══██║██║ ██║ ██║██║ ██║██║ ██║██╔══╝
+██████╔╝██║██║ ██║███████╗╚██████╔╝╚██████╔╝╚██████╔╝███████╗
+╚═════╝ ╚═╝╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝
+*/
+
+
+ FlagWaitAny( "player_near_intel3_exit_overgrown", "player_near_intel3_exit_pristine" )
+
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ wait 1.5
+
+ //Security - PA Attention. Automated security personnel have now been deployed in all non-combatant sectors.
+ //Please display security credentials clearly to avoid accidental termination. Thank you.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_targeting_TS231_12_01_imc_facilityPA" )
+
+ wait 3
+
+ soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ //Security -PA Automated security personnel: Please target all non-IMC military subjects.
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_targeting_TS231_11_01_imc_facilityPA" )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ██╗ █████╗ ██████╗ ███████╗██████╗
+██╔════╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗
+███████╗███████║███████║██████╔╝█████╗ ██║ ██║
+╚════██║██╔══██║██╔══██║██╔══██╗██╔══╝ ██║ ██║
+███████║██║ ██║██║ ██║██║ ██║███████╗██████╔╝
+╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ██╗ █████╗ ██████╗ ███████╗██████╗
+██╔════╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗
+███████╗███████║███████║██████╔╝█████╗ ██║ ██║
+╚════██║██╔══██║██╔══██║██╔══██╗██╔══╝ ██║ ██║
+███████║██║ ██║██║ ██║██║ ██║███████╗██████╔╝
+╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ██╗ █████╗ ██████╗ ███████╗██████╗
+██╔════╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗
+███████╗███████║███████║██████╔╝█████╗ ██║ ██║
+╚════██║██╔══██║██╔══██║██╔══██╗██╔══╝ ██║ ██║
+███████║██║ ██║██║ ██║██║ ██║███████╗██████╔╝
+╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////
+/*
+███████╗██╗ ██╗ █████╗ ██████╗ ███████╗██████╗
+██╔════╝██║ ██║██╔══██╗██╔══██╗██╔════╝██╔══██╗
+███████╗███████║███████║██████╔╝█████╗ ██║ ██║
+╚════██║██╔══██║██╔══██║██╔══██╗██╔══╝ ██║ ██║
+███████║██║ ██║██║ ██║██║ ██║███████╗██████╔╝
+╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═════╝
+
+*/
+/////////////////////////////////////////////////////////////////////////////////////////
+
+void function OnSpawnedPropDynamic( entity propDynamic )
+{
+ string scriptName = propDynamic.GetScriptName()
+
+ if ( scriptName == "flyer_lab" )
+ thread LabCreatureThink( propDynamic )
+
+ if ( scriptName == "labrats_idlers" )
+ thread LabRatIdlerThink( propDynamic )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function LabRatIdlerThink( entity propDynamic )
+{
+ entity node = CreateScriptRef( propDynamic.GetOrigin(), propDynamic.GetAngles() )
+ vector originOffset = PositionOffsetFromEnt( node, -15, 0, 0 )
+ node.SetOrigin( originOffset )
+ thread PlayAnimTeleport( propDynamic, propDynamic.kv.script_noteworthy, node )
+
+}
+/////////////////////////////////////////////////////////////////////////////////////////
+void function OnSpawnedLevelNPC( entity npc )
+{
+ string scriptName = npc.GetScriptName()
+
+ if ( scriptName == "lab_prowlers" )
+ {
+ thread LabCreatureThink( npc )
+
+ }
+
+ if ( scriptName == "soldiers_human_room_fight_01" )
+ AttackPlayer( npc )
+
+
+ //if ( scriptName == "doctor_science_intel_room_01" )
+ //thread LabAlphaDoctorScienceThink( npc )
+
+ if ( scriptName == "civilian_walker_evac_elevator_labs" )
+ thread LabAlphaScientistThink( npc )
+
+ if ( scriptName == "labA_dudes" )
+ thread LabAlphaScientistThink( npc )
+
+ if ( scriptName == "grunts_elevator" )
+ thread GruntElevatorThink( npc )
+
+ if ( scriptName == "prowlers_courtyard" )
+ thread ProwlersAmbientThink( npc )
+
+ if ( scriptName == "courtyard_responders" )
+ thread CourtyardSoldiersThink( npc )
+
+ if ( scriptName == "civilian_walker_courtyard" )
+ thread CourtyardSoldiersThink( npc )
+
+ if ( scriptName == "creature_surprised_dudes" )
+ thread CreatureSurprisedSoldiersThink( npc )
+
+ if ( scriptName == "elevator_turret_dudes" )
+ thread HallwayTurretDudesThink( npc )
+
+ if ( scriptName == "sphere_room_dudes" )
+ thread GruntsSphereRoomThink( npc )
+
+ if ( scriptName == "first_timeshift_soldiers" )
+ AttackPlayer( npc )
+
+
+
+}
+
+
+void function LabCreatureThink( entity creature )
+{
+ creature.EndSignal( "PlayerInsideCage" )
+ creature.EndSignal( "OnDeath" )
+ creature.EndSignal( "OnDestroy" )
+
+ thread AnimalCrueltyAcheivement( creature )
+ wait 1 //need to wait for player to spawn, otherwise it may early out
+
+ if ( creature.IsNPC() )
+ creature.SetNoTarget( true )
+
+ entity trigger
+ entity node
+ array <entity> linkedEnts = creature.GetLinkEntArray()
+ foreach ( entity ent in linkedEnts )
+ {
+ if ( ent.GetClassName() == "script_ref" )
+ {
+ node = ent
+ continue
+ }
+ if ( ent.GetClassName() == "trigger_multiple" )
+ {
+ trigger = ent
+ continue
+ }
+ }
+ //if ( creature.IsNPC() )
+ //Assert( IsValid( trigger ), "creature at " + creature.GetOrigin() + " is not linked to a trigger" )
+
+ Assert( IsValid( node ), "creature at " + creature.GetOrigin() + " is not linked to a node" )
+
+
+ string animIdle = ""
+ string animBreakout = ""
+ string animAggroLoop = ""
+
+ switch ( node.GetScriptName() )
+ {
+ case "variant01":
+ animIdle = "pr_timeshift_caged_sleeping_01"
+ animBreakout = "pr_timeshift_caged_sleeping_01_interrupt"
+ animAggroLoop = "pr_timeshift_caged_small_aggro_01"
+ break
+ case "variant02":
+ animIdle = "pr_timeshift_caged_sleeping_02"
+ animBreakout = "pr_timeshift_caged_sleeping_02_interrupt"
+ animAggroLoop = "pr_timeshift_caged_small_aggro_02"
+ break
+ case "variant03":
+ animIdle = "pr_timeshift_caged_sleeping_03"
+ animBreakout = "pr_timeshift_caged_sleeping_03_interrupt"
+ animAggroLoop = "pr_timeshift_caged_small_aggro_03"
+ break
+ case "variant04":
+ animIdle = "pr_timeshift_caged_laying_01"
+ animBreakout = "pr_timeshift_caged_laying_01_interrupt"
+ animAggroLoop = "pr_timeshift_caged_small_aggro_04"
+ break
+ case "variant05":
+ animIdle = "pr_timeshift_caged_sitting_01"
+ animBreakout = "pr_timeshift_caged_sitting_01_interrupt"
+ animAggroLoop = "pr_timeshift_caged_small_aggro_05"
+ break
+ case "variant06":
+ animIdle = "pr_timeshift_caged_standing_01"
+ animBreakout = "pr_timeshift_caged_standing_01_interrupt"
+ animAggroLoop = "pr_timeshift_caged_small_aggro_03"
+ break
+ case "variant07":
+ animIdle = "pr_timeshift_caged_long_14"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA1":
+ animIdle = "pr_timeshift_caged_long_06"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA2":
+ animIdle = "pr_timeshift_caged_long_07"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA3":
+ animIdle = "pr_timeshift_caged_long_08"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA4":
+ animIdle = "pr_timeshift_caged_long_09"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA5":
+ animIdle = "pr_timeshift_caged_long_10"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA6":
+ animIdle = "pr_timeshift_caged_long_11"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA7":
+ animIdle = "pr_timeshift_caged_long_12"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterA8":
+ animIdle = "pr_timeshift_caged_long_13"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterB1":
+ animIdle = "pr_timeshift_caged_long_01"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterB2":
+ animIdle = "pr_timeshift_caged_long_02"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterB3":
+ animIdle = "pr_timeshift_caged_long_03"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterB4":
+ animIdle = "pr_timeshift_caged_long_04"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantCageTogeterB5":
+ animIdle = "pr_timeshift_caged_long_05"
+ animBreakout = ""
+ animAggroLoop = ""
+ break
+ case "variantLab01":
+ animIdle = "fl_timeshift_caged_tall_laying_01"
+ animBreakout = "fl_timeshift_caged_tall_interrupt_01"
+ animAggroLoop = "fl_timeshift_caged_tall_aggro_01"
+ break
+ case "variantLab02":
+ animIdle = "fl_timeshift_caged_tall_laying_02"
+ animBreakout = "fl_timeshift_caged_tall_interrupt_02"
+ animAggroLoop = "fl_timeshift_caged_tall_aggro_02"
+ break
+ case "variantLab03":
+ animIdle = "fl_timeshift_caged_tall_laying_03"
+ animBreakout = "fl_timeshift_caged_tall_interrupt_03"
+ animAggroLoop = "fl_timeshift_caged_tall_aggro_03"
+ break
+ case "variantLab04":
+ animIdle = "fl_timeshift_caged_tall_laying_04"
+ animBreakout = "fl_timeshift_caged_tall_interrupt_04"
+ animAggroLoop = "fl_timeshift_caged_tall_aggro_04"
+ break
+ case "variantCylinder01":
+ animIdle = "fl_timeshift_caged_cylinder_01"
+ animBreakout = ""
+ animAggroLoop = ""
+ thread PlayDeathAnimWhenShot( creature, "fl_timeshift_caged_cylinder_death_01" )
+ break
+ case "variantCylinder02":
+ animIdle = "fl_timeshift_caged_cylinder_02"
+ animBreakout = ""
+ animAggroLoop = ""
+ thread PlayDeathAnimWhenShot( creature, "fl_timeshift_caged_cylinder_death_01" )
+ break
+ default:
+ Assert( 0, "creatureNode at " + node.GetOrigin() + " has an unhandled script_name" )
+
+ }
+
+ //-------------------------------------------------------------
+ // Go back into AI if this thread ends (player inside cage)
+ //--------------------------------------------------------------
+
+ OnThreadEnd(
+ function() : ( creature )
+ {
+ if ( !IsAlive( creature ) )
+ return
+ creature.Anim_Stop()
+ }
+ )
+
+ //------------------------------------------
+ // Play chill idle
+ //------------------------------------------
+ thread PlayAnimTeleport( creature, animIdle, node )
+
+ array <entity> players = GetPlayerArray()
+ if ( players.len() <= 0 )
+ return
+ entity player = players[ 0 ]
+
+ if ( ( creature.IsNPC() ) && ( trigger != null ) )
+ thread LabProwlerPlayerInsideCage( creature, trigger, player )
+
+ while( !PlayerInRange( player.GetOrigin(), creature.GetOrigin(), 256 ) )
+ wait 0.2
+
+ wait ( RandomFloatRange( 0, 0.8 ) )
+
+ //------------------------------------------
+ // Player close, breakout into aggro idle
+ //------------------------------------------
+ if ( animBreakout != "" )
+ waitthread PlayAnim( creature, animBreakout, node )
+
+ if ( animAggroLoop != "" )
+ thread PlayAnim( creature, animAggroLoop, node )
+
+
+ WaitForever()
+}
+
+
+void function AnimalCrueltyAcheivement( creature )
+{
+ if ( Flag( "AcheivementUnlockedLabProwler") )
+ return
+ if ( !creature.IsNPC() )
+ return
+ if ( creature.GetClassName() != "npc_prowler" )
+ return
+
+ if ( Flag( "AcheivementUnlockedLabProwler") )
+ return
+
+ FlagEnd( "AcheivementUnlockedLabProwler" )
+
+
+ //To do: detect if killed by the player
+ //creature.WaitSignal( "OnDeath" )
+
+
+}
+void function PlayDeathAnimWhenShot( entity propCreature, string anim )
+{
+
+
+
+
+}
+
+void function LabProwlerPlayerInsideCage( entity prowler, entity trigger, entity player )
+{
+ prowler.EndSignal( "OnDeath" )
+ player.EndSignal( "OnDeath" )
+
+ trigger.WaitSignal( "OnTrigger" )
+
+ prowler.Signal( "PlayerInsideCage" )
+
+}
+
+
+void function PlayMusicInTimezoneUntilFlag( string track, var timeZone, string flagToAbort )
+{
+ if ( Flag( flagToAbort ) )
+ return
+
+ FlagEnd( flagToAbort )
+
+ var otherTimeZone
+ if ( timeZone == TIMEZONE_NIGHT )
+ otherTimeZone = TIMEZONE_DAY
+ else
+ otherTimeZone = TIMEZONE_NIGHT
+
+ while( true )
+ {
+
+ waitthread WaittillPlayerSwitchesTimezone( timeZone )
+
+ StopMusic()
+ PlayMusic( track )
+
+ waitthread WaittillPlayerSwitchesTimezone( otherTimeZone )
+ }
+}
+
+
+
+
+void function DebugX( entity player )
+{
+ waitthread WaittillPlayerSwitchesTimezone( TIMEZONE_DAY )
+
+ entity soundEnt = CreateBestLoudspeakerEnt( player, TIMEZONE_DAY )
+
+ waitthread PlayTimeShiftDialogue( player, soundEnt, "diag_sp_wildlifeStudy_TS191_18_01_imc_grunt3" )
+} \ No newline at end of file