untyped global function Evac_Init global function Evac_AddLocation global function Evac_SetSpacePosition global function Evac_SetEnabled global function Evac_IsEnabled global function IsEvacDropship global function EvacMain const float EVAC_ARRIVAL_TIME = 40.0 const float EVAC_WAIT_TIME = 18.0 struct { bool enabled = true array evacPoints Point spacePosition entity evacDropship array evacPlayers } file void function Evac_Init() { EvacShared_Init() AddCallback_GameStateEnter( eGameState.Epilogue, Evac_OnEpilogue ) } void function Evac_SetEnabled( bool enabled ) { file.enabled = enabled } bool function Evac_IsEnabled() { return false // shit is busted rn lol //return file.enabled && GetClassicMPMode() && !IsRoundBased() } void function Evac_AddLocation( vector origin, vector angles ) { Point evacPoint evacPoint.origin = origin evacPoint.angles = angles file.evacPoints.append( evacPoint ) } void function Evac_SetSpacePosition( vector origin, vector angles ) { file.spacePosition.origin = origin file.spacePosition.angles = angles } bool function IsEvacDropship( entity ent ) { return file.evacDropship == ent && IsValid( file.evacDropship ) } void function Evac_OnEpilogue() { if ( Evac_IsEnabled() ) thread EvacMain( GetOtherTeam( GameScore_GetWinningTeam() ) ) } void function EvacMain( int winningTeam ) { if ( file.evacPoints.len() == 0 ) { // automatically add evac locations if they aren't registered yet int i = 1 entity current = null while ( true ) { current = GetEnt( "escape_node" + i ) print( current ) if ( current != null ) Evac_AddLocation( current.GetOrigin(), current.GetAngles() ) else break i++ } if ( file.evacPoints.len() == 0 ) unreachable } if ( file.spacePosition.origin == < 0, 0, 0 > ) { // automatically add a space node if not registered yet entity defaultSpaceNode = GetEnt( "spaceNode" ) if ( defaultSpaceNode == null ) unreachable Evac_SetSpacePosition( defaultSpaceNode.GetOrigin(), defaultSpaceNode.GetAngles() ) } Point evacPoint = file.evacPoints[ RandomInt( file.evacPoints.len() ) ] // create an entity for the evac point that clients will get entity evacPointEntity = CreateEntity( MARKER_ENT_CLASSNAME ) evacPointEntity.SetOrigin( evacPoint.origin ) evacPointEntity.kv.spawnflags = SF_INFOTARGET_ALWAYS_TRANSMIT_TO_CLIENT DispatchSpawn( evacPointEntity ) evacPointEntity.DisableHibernation() // set objectives //SetTeamActiveObjective( winningTeam, "EG_DropshipExtract", Time() + EVAC_ARRIVAL_TIME, evacPointEntity ) //SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtract", Time() + EVAC_ARRIVAL_TIME, evacPointEntity ) // wanted to do this with an actual dropship to calculate embarkStartDelay but spawning it before it should exist ingame is weird // could probably do it with a dummy entity but effort wait EVAC_ARRIVAL_TIME - 4.33333//embarkStartDelay // create dropship entity dropship = CreateDropship( winningTeam, evacPoint.origin, evacPoint.angles ) file.evacDropship = dropship DispatchSpawn( dropship ) dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" ) // gotta do this after dispatch for some reason vector startPos = dropship.Anim_GetStartForRefEntity( "cd_dropship_rescue_side_start", evacPointEntity, "origin" ).origin dropship.SetOrigin( startPos ) // set origin so the dropship isn't in the map dropship.EndSignal( "OnDestroy" ) // calculate time until idle float sequenceDuration = dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) float cycleFrac = dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" ) float embarkStartDelay = sequenceDuration * cycleFrac // play anim thread PlayAnim( dropship, "cd_dropship_rescue_side_start", evacPointEntity ) wait embarkStartDelay print( "evac flyin done! ready to load players" ) // set objectives again SetTeamActiveObjective( winningTeam, "EG_DropshipExtract2", Time() + EVAC_WAIT_TIME, evacPointEntity ) SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtract2", Time() + EVAC_WAIT_TIME, evacPointEntity ) thread EvacShipThink( dropship ) // let people enter it wait EVAC_WAIT_TIME // fly away thread PlayAnim( dropship, "cd_dropship_rescue_side_end", evacPointEntity ) // set objectives again SetTeamActiveObjective( winningTeam, "EG_DropshipExtractDropshipFlyingAway" ) SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtractDropshipFlyingAway" ) wait dropship.GetSequenceDuration( "cd_dropship_rescue_side_end" ) - WARPINFXTIME foreach ( entity player in file.evacPlayers ) { Remote_CallFunction_Replay( player, "ServerCallback_PlayScreenFXWarpJump" ) } // todo screen effects and shit //WaittillAnimDone( dropship ) wait WARPINFXTIME // space dropship.SetOrigin( file.spacePosition.origin ) dropship.SetAngles( file.spacePosition.angles ) thread PlayAnim( dropship, "ds_space_flyby_dropshipA" ) // display player [Evacuated] in killfeed foreach ( entity player in GetPlayerArray() ) { foreach ( entity evacPlayer in file.evacPlayers ) Remote_CallFunction_NonReplay( player, "ServerCallback_EvacObit", evacPlayer.GetEncodedEHandle() ) } foreach ( entity player in file.evacPlayers ) { // set skybox to space for all evac players player.SetSkyCamera( GetEnt( "skybox_cam_intro" ) ) Remote_CallFunction_NonReplay( player, "ServerCallback_DisableHudForEvac" ) } wait 5.0 foreach ( entity player in GetPlayerArray() ) ScreenFadeToBlackForever( player, 2.0 ) wait 2.0 // end game lol SetGameState( eGameState.Postmatch ) } void function EvacShipThink( entity dropship ) { dropship.EndSignal( "OnDestroy" ) // this is the easiest way i could figure out to get a bounding box that's parented to the dropship entity mover1 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) mover1.SetParent( dropship ) mover1.SetLocalOrigin( dropship.GetBoundingMaxs() - < 0, 0, 100> ) entity mover2 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) mover2.SetParent( dropship ) mover2.SetLocalOrigin( dropship.GetBoundingMins() - < 0, 0, 100 > ) while ( true ) { foreach ( entity player in GetPlayerArrayOfTeam( dropship.GetTeam() ) ) { if ( file.evacPlayers.contains( player ) || !IsAlive( player ) ) continue vector playerPos = player.GetOrigin() vector mover1Pos = mover1.GetOrigin() vector mover2Pos = mover2.GetOrigin() vector maxPos maxPos.x = mover1Pos.x > mover2Pos.x ? mover1Pos.x : mover2Pos.x maxPos.y = mover1Pos.y > mover2Pos.y ? mover1Pos.y : mover2Pos.y maxPos.z = mover1Pos.z > mover2Pos.z ? mover1Pos.z : mover2Pos.z vector minPos minPos.x = mover1Pos.x < mover2Pos.x ? mover1Pos.x : mover2Pos.x minPos.y = mover1Pos.y < mover2Pos.y ? mover1Pos.y : mover2Pos.y minPos.z = mover1Pos.z < mover2Pos.z ? mover1Pos.z : mover2Pos.z print( "\n" ) print( player ) print( playerPos ) print( minPos ) print( maxPos ) if ( playerPos.x > minPos.x && playerPos.y > minPos.y && playerPos.z > minPos.z && playerPos.x < maxPos.x && playerPos.y < maxPos.y && playerPos.z < maxPos.z ) { print( player + " is evacuating!" ) file.evacPlayers.append( player ) player.SetParent( dropship ) // super duper temp player.SetLocalOrigin( dropship.GetOrigin() - < 0, 10, 80 > ) } } WaitFrame() } } /*void function TestEvac() { if ( file.evacShipSpawns.len() == 0 ) Evac_AddLocation( GetEnt( "escape_node1" ).GetOrigin(), GetEnt( "escape_node1" ).GetAngles() ) Point shipSpawn = file.evacShipSpawns[ RandomInt( file.evacShipSpawns.len() ) ] entity dropship = CreateDropship( GetPlayerArray()[0].GetTeam(), shipSpawn.origin, shipSpawn.angles ) file.evacDropship = dropship DispatchSpawn( dropship ) dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" ) print( dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) ) print( dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" ) ) float embarkStart = dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" ) * dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" ) print( embarkStart ) thread PlayAnim( dropship, "cd_dropship_rescue_side_start" ) wait embarkStart print( "evac start anim done" ) thread TestEvacThink( dropship ) SetTeamActiveObjective( GetPlayerArray()[0].GetTeam(), "EG_DropshipExtract2", Time() + 30, dropship ) thread PlayAnim( dropship, "cd_dropship_rescue_side_idle", GetEnt( "escape_node1" ) ) } void function TestEvacThink( entity dropship ) { dropship.EndSignal( "OnDestroy" ) // these numbers are probably innacurate but there's no real way of getting accurate ones and these are good enough entity mover = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) mover.SetParent( dropship ) mover.SetLocalOrigin( dropship.GetBoundingMaxs() - < 0, 0, 100> ) entity mover2 = CreateScriptMover( dropship.GetOrigin(), dropship.GetAngles() ) mover2.SetParent( dropship ) mover2.SetLocalOrigin( dropship.GetBoundingMins() - < 0, 0, 100> ) while ( true ) { foreach ( entity player in GetPlayerArrayOfTeam( dropship.GetTeam() ) ) { if ( !IsAlive( player ) ) continue vector playerOrigin = player.GetOrigin() vector dropshipMax = mover.GetOrigin() vector dropshipMin = mover2.GetOrigin() // temp, might be permenant but idk if box triggers are a thing in script if ( playerOrigin.x > dropshipMin.x && playerOrigin.y > dropshipMin.y && playerOrigin.z > dropshipMin.z && playerOrigin.x < dropshipMax.x && playerOrigin.y < dropshipMax.y && playerOrigin.z < dropshipMax.z ) player.Die() } WaitFrame() } }*/