aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers
diff options
context:
space:
mode:
authorBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-10-14 21:01:40 +0100
committerBobTheBob <32057864+BobTheBob9@users.noreply.github.com>2021-10-14 21:01:40 +0100
commit9a2778eabc7ba968968e41dda9f03525d6c5383d (patch)
tree6d1c5dc64754d542d68a7f47742a701a4eec9308 /Northstar.CustomServers
parentc0a0c7e502f2bc99185d79a485b965f63de7a203 (diff)
downloadNorthstarMods-9a2778eabc7ba968968e41dda9f03525d6c5383d.tar.gz
NorthstarMods-9a2778eabc7ba968968e41dda9f03525d6c5383d.zip
oh fuck i forgot to commit for a while
Diffstat (limited to 'Northstar.CustomServers')
-rw-r--r--Northstar.CustomServers/mod.json10
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut2
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut17
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut515
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut2
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut15
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut23
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut2
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut4
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut1
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut98
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut93
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut2
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut10
14 files changed, 488 insertions, 306 deletions
diff --git a/Northstar.CustomServers/mod.json b/Northstar.CustomServers/mod.json
index 547a1b8c4..ac826d1a2 100644
--- a/Northstar.CustomServers/mod.json
+++ b/Northstar.CustomServers/mod.json
@@ -10,6 +10,16 @@
{
"Name": "ns_should_return_to_lobby",
"DefaultValue": "1"
+ },
+
+ {
+ "Name": "ns_private_match_last_mode",
+ "DefaultValue": "aitdm"
+ },
+
+ {
+ "Name": "ns_private_match_last_map",
+ "DefaultValue": "mp_forwardbase_kodai"
}
],
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
index 2b7b90b3b..58d38ce7f 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_loadouts_mp.gnut
@@ -221,14 +221,12 @@ bool function ClientCommandCallback_SetFactionChoicePersistenceSlot( entity play
bool function ClientCommandCallback_LoadoutMenuClosed( entity player, array<string> args )
{
- SavePdataForEntityIndex( player.GetPlayerIndex() )
TryGivePilotLoadoutForGracePeriod( player )
return true
}
bool function ClientCommandCallback_InGameMPMenuClosed( entity player, array<string> args )
{
- SavePdataForEntityIndex( player.GetPlayerIndex() )
//TryGivePilotLoadoutForGracePeriod( player )
return true
}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut b/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut
index c116ac33b..d0820dd6a 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/_menu_callbacks.gnut
@@ -7,11 +7,18 @@ void function MenuCallbacks_Init()
bool function ClientCommandCallback_LeaveMatch( entity player, array<string> args )
{
- // todo: ideally, it'd be nice to get clients to return to lobby here, rather than just dcing them
- // kind of a pain tho, since we'd have to get it to call script code without a remote func, since that'd break compatibility
+ thread WritePersistenceAndLeave( player )
+ return true
+}
- ClientCommand( player, "disconnect" )
- //ClientCommand( player, "setplaylist tdm; map mp_lobby" )
+void function WritePersistenceAndLeave( entity player )
+{
+ // write player persistence before we leave, since leaving player might load local lobby before server writes persistence, so they won't get newest
+ // not super essential, but a nice qol thing
+ NSEarlyWritePlayerPersistenceForLeave( player )
+ while ( NSIsWritingPlayerPersistence() )
+ WaitFrame()
- return true
+ // this is a custom concommand which can be called on clients, it causes them to leave and doesn't have issues if they're host
+ ClientCommand( player, "ns_leave_to_lobby" )
} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut
index ba473cae9..c0242cc19 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/evac/_evac.gnut
@@ -1,315 +1,360 @@
untyped
-
global function Evac_Init
-global function Evac_AddLocation
-global function Evac_SetSpacePosition
-global function Evac_SetEnabled
-global function Evac_IsEnabled
+global function AddEvacNode
+global function SetEvacSpaceNode
global function IsEvacDropship
-global function EvacMain
+global function EvacEpilogueSetup
+global function Evac
+
+const float EVAC_INITIAL_WAIT = 5.0
const float EVAC_ARRIVAL_TIME = 40.0
const float EVAC_WAIT_TIME = 18.0
-struct {
- bool enabled = true
+// we don't use these because they're busted, just keeping them
+const array<string> EVAC_EMBARK_ANIMS_1P = [
+ "ptpov_e3_rescue_side_embark_A",
+ "ptpov_e3_rescue_side_embark_B",
+ "ptpov_e3_rescue_side_embark_C",
+ "ptpov_e3_rescue_side_embark_D",
+ "ptpov_e3_rescue_side_embark_E",
+ "ptpov_e3_rescue_side_embark_F",
+ "ptpov_e3_rescue_side_embark_G",
+ "ptpov_e3_rescue_side_embark_H"
+]
+
+const array<string> EVAC_EMBARK_ANIMS_3P = [
+ "pt_e3_rescue_side_embark_A",
+ "pt_e3_rescue_side_embark_B",
+ "pt_e3_rescue_side_embark_C",
+ "pt_e3_rescue_side_embark_D",
+ "pt_e3_rescue_side_embark_E",
+ "pt_e3_rescue_side_embark_F",
+ "pt_e3_rescue_side_embark_G",
+ "pt_e3_rescue_side_embark_H"
+]
- array<Point> evacPoints
- Point spacePosition
+const array<string> EVAC_IDLE_ANIMS_1P = [
+ "ptpov_e3_rescue_side_embark_A_idle",
+ "ptpov_e3_rescue_side_embark_B_idle",
+ "ptpov_e3_rescue_side_embark_C_idle",
+ "ptpov_e3_rescue_side_embark_D_idle",
+ "ptpov_e3_rescue_side_embark_E_idle",
+ "ptpov_e3_rescue_side_embark_F_idle",
+ "ptpov_e3_rescue_side_embark_G_idle",
+ "ptpov_e3_rescue_side_embark_H_idle"
+]
+
+const array<string> EVAC_IDLE_ANIMS_3P = [
+ "pt_e3_rescue_side_idle_A",
+ "pt_e3_rescue_side_idle_B",
+ "pt_e3_rescue_side_idle_C",
+ "pt_e3_rescue_side_idle_D",
+ "pt_e3_rescue_side_idle_E",
+ "pt_e3_rescue_side_idle_F",
+ "pt_e3_rescue_side_idle_G",
+ "pt_e3_rescue_side_idle_H"
+]
+
+struct {
+ array<entity> evacNodes
+ entity spaceNode
entity evacDropship
- array<entity> evacPlayers
+ entity evacIcon
} file
void function Evac_Init()
{
EvacShared_Init()
-
- AddCallback_GameStateEnter( eGameState.Epilogue, Evac_OnEpilogue )
}
-void function Evac_SetEnabled( bool enabled )
+void function AddEvacNode( entity evacNode )
{
- file.enabled = enabled
+ file.evacNodes.append( evacNode )
}
-bool function Evac_IsEnabled()
+void function SetEvacSpaceNode( entity spaceNode )
{
- return false // shit is busted rn lol
- //return file.enabled && GetClassicMPMode() && !IsRoundBased()
+ file.spaceNode = spaceNode
}
-void function Evac_AddLocation( vector origin, vector angles )
+bool function IsEvacDropship( entity ent )
{
- Point evacPoint
- evacPoint.origin = origin
- evacPoint.angles = angles
-
- file.evacPoints.append( evacPoint )
+ return file.evacDropship == ent && IsValid( file.evacDropship )
}
-void function Evac_SetSpacePosition( vector origin, vector angles )
+// evac epilogue
+void function EvacEpilogueSetup()
{
- file.spacePosition.origin = origin
- file.spacePosition.angles = angles
+ AddCallback_GameStateEnter( eGameState.Epilogue, EvacEpilogue )
}
-bool function IsEvacDropship( entity ent )
+void function EvacEpilogue()
{
- return file.evacDropship == ent && IsValid( file.evacDropship )
+ thread Evac( GetPlayerArray()[0].GetTeam(), EVAC_INITIAL_WAIT, EVAC_ARRIVAL_TIME, EVAC_WAIT_TIME, EvacEpiloguePlayerCanBoard, EvacEpilogueShouldLeaveEarly, EvacEpilogueCompleted )
}
-void function Evac_OnEpilogue()
+bool function EvacEpiloguePlayerCanBoard( entity dropship, entity player )
{
- if ( Evac_IsEnabled() )
- thread EvacMain( GetOtherTeam( GameScore_GetWinningTeam() ) )
+ // can't board a dropship on a different team
+ if ( dropship.GetTeam() != player.GetTeam() )
+ return false
+
+ // check if there are any free slots on the dropship, if there are then they can board
+ foreach ( entity player in dropship.s.evacSlots )
+ if ( !IsValid( player ) )
+ return true
+
+ // no empty slots
+ return false
}
-void function EvacMain( int winningTeam )
+bool function EvacEpilogueShouldLeaveEarly( entity dropship )
{
- if ( file.evacPoints.len() == 0 )
+ int numEvacing
+ foreach ( entity player in dropship.s.evacSlots )
+ if ( IsValid( player ) )
+ numEvacing++
+
+ return GetPlayerArrayOfTeam( dropship.GetTeam() ).len() == numEvacing || numEvacing == dropship.s.evacSlots.len()
+}
+
+void function EvacEpilogueCompleted( entity dropship )
+{
+ wait 5.0
+ print( dropship )
+
+ foreach ( entity player in dropship.s.evacSlots )
{
- // 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 ( !IsValid( player ) )
+ continue
- if ( file.evacPoints.len() == 0 )
- unreachable
+ ScreenFadeToBlackForever( player, 2.0 )
}
- if ( file.spacePosition.origin == < 0, 0, 0 > )
+ wait 2.0
+
+ SetGameState( eGameState.Postmatch )
+}
+
+// global evac func, anything can call this, it's not necessarily an epilogue thing
+void function Evac( int evacTeam, float initialWait, float arrivalTime, float waitTime, bool functionref( entity, entity ) canBoardCallback, bool functionref( entity ) shouldLeaveEarlyCallback, void functionref( entity ) completionCallback )
+{
+ wait initialWait
+
+ // setup evac nodes if not manually registered
+ if ( file.evacNodes.len() == 0 )
{
- // automatically add a space node if not registered yet
- entity defaultSpaceNode = GetEnt( "spaceNode" )
- if ( defaultSpaceNode == null )
- unreachable
-
- Evac_SetSpacePosition( defaultSpaceNode.GetOrigin(), defaultSpaceNode.GetAngles() )
+ for ( int i = 1; ; i++ )
+ {
+ entity newNode = GetEnt( "escape_node" + i )
+ if ( !IsValid( newNode ) )
+ break
+
+ file.evacNodes.append( newNode )
+ }
}
- Point evacPoint = file.evacPoints[ RandomInt( file.evacPoints.len() ) ]
+ // setup space node if not manually registered
+ if ( !IsValid( file.spaceNode ) )
+ file.spaceNode = GetEnt( "spaceNode" )
+
+ entity evacNode = file.evacNodes.getrandom()
+
+ // setup client evac position
+ file.evacIcon = CreateEntity( "info_target" )
+ file.evacIcon.SetOrigin( evacNode.GetOrigin() )
+ file.evacIcon.kv.spawnFlags = SF_INFOTARGET_ALWAYS_TRANSMIT_TO_CLIENT
+ DispatchSpawn( file.evacIcon )
+ file.evacIcon.DisableHibernation()
+
+ wait 0.5 // need to wait here, or the target won't appear on clients for some reason
+ // eta until arrive
+ SetTeamActiveObjective( evacTeam, "EG_DropshipExtract", Time() + arrivalTime, file.evacIcon )
+ SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_StopExtract", Time() + arrivalTime, file.evacIcon )
- // 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
+ // would've liked to use cd_dropship_rescue_side_start length here, but can't since this is done before dropship spawn, can't
+ wait arrivalTime - 4.33333
+ entity dropship = CreateDropship( evacTeam, evacNode.GetOrigin(), evacNode.GetAngles() )
+ dropship.SetModel( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
+ dropship.SetValueForModelKey( $"models/vehicle/crow_dropship/crow_dropship_hero.mdl" )
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.s.evacSlots <- [ null, null, null, null, null, null, null, null ]
+
dropship.EndSignal( "OnDestroy" )
+ OnThreadEnd( function() : ( evacTeam, completionCallback, dropship )
+ {
+ if ( "evacTrigger" in dropship.s )
+ dropship.s.evacTrigger.Destroy()
+
+ // this should be for both teams
+ SetTeamActiveObjective( evacTeam, "EG_DropshipExtractDropshipDestroyed" )
+ SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_DropshipExtractDropshipDestroyed" )
- // calculate time until idle
+ foreach ( entity player in dropship.s.evacSlots )
+ {
+ if ( !IsValid( player ) )
+ continue
+
+ player.ClearInvulnerable()
+ }
+
+ // this is called whether dropship is destroyed or evac finishes, callback can handle this itself
+ thread completionCallback( dropship )
+ })
+
+ // flyin
+ thread PlayAnim( dropship, "cd_dropship_rescue_side_start", evacNode )
+
+ // calculate time until idle start
float sequenceDuration = dropship.GetSequenceDuration( "cd_dropship_rescue_side_start" )
float cycleFrac = dropship.GetScriptedAnimEventCycleFrac( "cd_dropship_rescue_side_start", "ReadyToLoad" )
- float embarkStartDelay = sequenceDuration * cycleFrac
+ wait sequenceDuration * cycleFrac
+
+ thread PlayAnim( dropship, "cd_dropship_rescue_side_idle", evacNode )
+
+ // eta until leave
+ SetTeamActiveObjective( evacTeam, "EG_DropshipExtract2", Time() + EVAC_WAIT_TIME, file.evacIcon )
+ SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_StopExtract2", Time() + EVAC_WAIT_TIME, file.evacIcon )
+
+ // setup evac trigger
+ entity trigger = CreateEntity( "trigger_cylinder" )
+ trigger.SetRadius( 150 )
+ trigger.SetAboveHeight( 100 )
+ trigger.SetBelowHeight( 100 )
+ trigger.SetOrigin( dropship.GetOrigin() )
+ trigger.SetParent( dropship, "ORIGIN" )
+ DispatchSpawn( trigger )
+ // have to do this inline since we capture the completionCallback
+ trigger.SetEnterCallback( void function( entity trigger, entity player ) : ( canBoardCallback, dropship )
+ {
+ if ( !player.IsPlayer() || !IsAlive( player ) || !canBoardCallback( dropship, player ) || PlayerInDropship( player, dropship ) )
+ return
- // play anim
- thread PlayAnim( dropship, "cd_dropship_rescue_side_start", evacPointEntity )
- wait embarkStartDelay
-
- print( "evac flyin done! ready to load players" )
+ thread AddPlayerToEvacDropship( dropship, player )
+ })
- // 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
+ dropship.s.evacTrigger <- trigger
+
+ float waitStartTime = Time()
+ while ( Time() - waitStartTime < waitTime )
+ {
+ if ( shouldLeaveEarlyCallback( dropship ) )
+ break
+
+ WaitFrame()
+ }
- wait EVAC_WAIT_TIME
+ // holster all weapons
+ foreach ( entity player in dropship.s.evacSlots )
+ if ( IsValid( player ) )
+ player.HolsterWeapon()
// fly away
- thread PlayAnim( dropship, "cd_dropship_rescue_side_end", evacPointEntity )
+ thread PlayAnim( dropship, "cd_dropship_rescue_side_end", evacNode )
+
+ SetTeamActiveObjective( evacTeam, "EG_DropshipExtractDropshipFlyingAway" )
+ SetTeamActiveObjective( GetOtherTeam( evacTeam ), "EG_StopExtractDropshipFlyingAway" )
- // set objectives again
- SetTeamActiveObjective( winningTeam, "EG_DropshipExtractDropshipFlyingAway" )
- SetTeamActiveObjective( GetOtherTeam( winningTeam ), "EG_StopExtractDropshipFlyingAway" )
+ // todo: play the warpout effect somewhere here
wait dropship.GetSequenceDuration( "cd_dropship_rescue_side_end" ) - WARPINFXTIME
- foreach ( entity player in file.evacPlayers )
- {
- Remote_CallFunction_Replay( player, "ServerCallback_PlayScreenFXWarpJump" )
- }
+ foreach ( entity player in dropship.s.evacSlots )
+ if ( IsValid( player ) )
+ Remote_CallFunction_NonReplay( 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
+ // go to space
+ // hardcoded angles here are a hack, spacenode position doesn't face the planet in the skybox, for some reason
+ file.spaceNode.SetAngles( < 30, -75, 20 >)
+ dropship.SetOrigin( file.spaceNode.GetOrigin() )
+ dropship.SetAngles( file.spaceNode.GetAngles() )
+ dropship.SetInvulnerable()
+ thread PlayAnim( dropship, "ds_space_flyby_dropshipA", file.spaceNode )
+
+ foreach( entity player in GetPlayerArray() )
+ {
+ // evac-ed players only beyond this point
+ if ( !PlayerInDropship( player, dropship ) )
+ {
+ if ( player.GetTeam() == dropship.GetTeam() )
+ SetPlayerActiveObjective( player, "EG_DropshipExtractFailedEscape" )
+
+ return
+ }
+
+ SetPlayerActiveObjective( player, "EG_DropshipExtractSuccessfulEscape" )
+
+ // skybox
player.SetSkyCamera( GetEnt( "skybox_cam_intro" ) )
Remote_CallFunction_NonReplay( player, "ServerCallback_DisableHudForEvac" )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_SetClassicSkyScale", dropship.GetEncodedEHandle(), 0.7 )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_SetMapSettings", 4.0, false, 0.4, 0.125 )
+
+ // display player [Evacuated] in killfeed
+ foreach ( entity otherPlayer in GetPlayerArray() )
+ Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_EvacObit", player.GetEncodedEHandle() )
}
- 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 )
+void function AddPlayerToEvacDropship( entity dropship, entity player )
{
- 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 )
+ int slot = RandomInt( dropship.s.evacSlots.len() )
+ for ( int i = 0; i < dropship.s.evacSlots.len(); i++ )
{
- foreach ( entity player in GetPlayerArrayOfTeam( dropship.GetTeam() ) )
+ if ( !IsValid( dropship.s.evacSlots[ slot ] ) )
{
- 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 > )
- }
+ dropship.s.evacSlots[ slot ] = player
+ break
}
-
- 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 )
+ slot = ( slot + 1 ) % expect int( dropship.s.evacSlots.len() )
+ }
- 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 )
+ // no slots available
+ if ( !PlayerInDropship( player, dropship ) )
+ return
+
+ player.SetInvulnerable()
+ player.UnforceCrouch()
+ player.ForceStand()
- thread PlayAnim( dropship, "cd_dropship_rescue_side_idle", GetEnt( "escape_node1" ) )
+ FirstPersonSequenceStruct fp
+ //fp.firstPersonAnim = EVAC_EMBARK_ANIMS_1P[ slot ]
+ fp.thirdPersonAnim = EVAC_EMBARK_ANIMS_3P[ slot ]
+ fp.attachment = "RESCUE"
+ fp.teleport = true
+ fp.thirdPersonCameraAttachments = [ "VDU" ] // this seems wrong, firstperson anim has better angles, but no head
+
+ EmitSoundOnEntityOnlyToPlayer( player, player, SHIFTER_START_SOUND_3P )
+ // should play SHIFTER_START_SOUND_1P when they actually arrive in the ship i think, unsure how this is supposed to be done
+ PlayPhaseShiftDisappearFX( player )
+ waitthread FirstPersonSequence( fp, player, dropship )
+
+ FirstPersonSequenceStruct idleFp
+ idleFp.firstPersonAnimIdle = EVAC_IDLE_ANIMS_1P[ slot ]
+ idleFp.thirdPersonAnimIdle = EVAC_IDLE_ANIMS_3P[ slot ]
+ idleFp.attachment = "RESCUE"
+ idleFp.teleport = true
+ idleFp.hideProxy = true
+ idleFp.viewConeFunction = ViewConeWide
+
+ thread FirstPersonSequence( idleFp, player, dropship )
+ ViewConeWide( player ) // gotta do this after for some reason, adding it to idleFp does not work for some reason
}
-void function TestEvacThink( entity dropship )
+bool function PlayerInDropship( entity player, 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()
+ // couldn't get "player in dropship.s.evacSlots" to work for some reason, likely due to static typing?
+ foreach ( entity dropshipPlayer in dropship.s.evacSlots )
+ if ( dropshipPlayer == player )
+ return true
- // 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()
- }
-}*/ \ No newline at end of file
+ return false
+} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut
index 932f14b7d..85b4aefbd 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ffa.nut
@@ -2,7 +2,7 @@ global function FFA_Init
void function FFA_Init()
{
- Evac_SetEnabled( false )
+ ClassicMP_ForceDisableEpilogue( true )
AddCallback_OnPlayerKilled( OnPlayerKilled )
}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
index 60daa4528..63b2c81ac 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/_private_lobby.gnut
@@ -13,6 +13,11 @@ void function PrivateLobby_Init()
print( "PrivateLobby_Init()" )
//ClearPlaylistVarOverrides()
+ file.map = GetConVarString( "ns_private_match_last_map" )
+ file.mode = GetConVarString( "ns_private_match_last_mode" )
+
+ thread SetupPrivateMatchUIVarsWhenReady()
+
AddClientCommandCallback( "PrivateMatchLaunch", ClientCommandCallback_PrivateMatchLaunch )
AddClientCommandCallback( "PrivateMatchSetMode", ClientCommandCallback_PrivateMatchSetMode )
AddClientCommandCallback( "SetCustomMap", ClientCommandCallback_SetCustomMap )
@@ -22,6 +27,14 @@ void function PrivateLobby_Init()
AddClientCommandCallback( "ResetMatchSettingsToDefault", ClientCommandCallback_ResetMatchSettingsToDefault )
}
+void function SetupPrivateMatchUIVarsWhenReady()
+{
+ // have to wait until end of first frame for SetUIVar to work
+ WaitEndFrame()
+ SetUIVar( level, "privatematch_map", GetPrivateMatchMapIndex( file.map ) )
+ SetUIVar( level, "privatematch_mode", GetPrivateMatchModeIndex( file.mode ) )
+}
+
bool function ClientCommandCallback_PrivateMatchLaunch( entity player, array<string> args )
{
if ( file.startState == ePrivateMatchStartState.STARTING )
@@ -127,6 +140,8 @@ void function StartMatch()
RefreshPlayerTeams()
+ SetConVarString( "ns_private_match_last_map", file.map )
+ SetConVarString( "ns_private_match_last_mode", file.mode )
SetConVarBool( "ns_should_return_to_lobby", true ) // potentially temp?
// TEMP for now: start game
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut
index 2c02ebdc2..605b23fd9 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_lobby.gnut
@@ -189,11 +189,32 @@ void function AddPrivateMatchModeSettingEnumEx( string category, string playlist
#endif
}
-array< string > function GetPrivateMatchSettingCategories()
+array< string > function GetPrivateMatchSettingCategories( bool uiAllowAllModeCategories = false )
{
array< string > categories
foreach ( string k, v in file.customMatchSettingsByCategory )
+ {
+ // can only do this in ui because it relies on GetUIVar
+ #if UI
+ bool gamemode = k.find( "#GAMEMODE_" ) == 0
+ if ( !uiAllowAllModeCategories && ( gamemode || k.find( "#PL_" ) == 0 ) )
+ {
+ if ( gamemode )
+ {
+ if ( k.slice( 10 ) != PrivateMatch_GetSelectedMode() )
+ {
+ continue
+ }
+ }
+ else if ( k.slice( 4 ) != PrivateMatch_GetSelectedMode() )
+ {
+ continue
+ }
+ }
+ #endif
+
categories.append( k )
+ }
return categories
}
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut
index 8991ebb0e..5cd4de503 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/lobby/sh_private_lobby_modes_init.gnut
@@ -4,6 +4,8 @@ void function PrivateMatchModesInit()
{
// match settings
// super temp: do localisation strings later
+ AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_MATCH", "classic_mp", [ "Disabled", "Enabled" ], "1" )
+ AddPrivateMatchModeSettingEnum( "#MODE_SETTING_CATEGORY_MATCH", "run_epilogue", [ "Disabled", "Enabled" ], "1" )
AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_MATCH", "scorelimit", "5" ) //, "Score Limit" )
AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_MATCH", "roundscorelimit", "0" ) //, "Score Limit (round-based modes)" )
AddPrivateMatchModeSettingArbitrary( "#MODE_SETTING_CATEGORY_MATCH", "timelimit", "12" ) //, "Time Limit" )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut
index ac0c309b7..4cbab84c2 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_ai_mp.gnut
@@ -30,12 +30,12 @@ bool function IsAutoPopulateEnabled( var team = null )
return true
}
-void function SPMP_UpdateNPCProficiency(entity ent)
+void function SPMP_UpdateNPCProficiency( entity ent )
{
}
-bool function SPMP_Callback_ForceAIMissPlayer(entity npc, entity player)
+bool function SPMP_Callback_ForceAIMissPlayer( entity npc, entity player )
{
return true
} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
index d7db601bc..38803e04c 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_base_gametype_mp.gnut
@@ -219,6 +219,7 @@ void function CodeCallback_OnPlayerRespawned( entity player )
player.s.respawnTime = Time()
Loadouts_TryGivePilotLoadout( player )
+ SetHumanRagdollImpactTable( player )
foreach ( void functionref( entity ) callback in svGlobal.onPlayerRespawnedCallbacks )
callback( player )
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut
index ac8a397f7..66bb3d6a4 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_classic_mp.nut
@@ -1,53 +1,80 @@
untyped
global function ClassicMp_Init
-global function ClassicMP_TryDefaultIntroSetup // called in mp_sh_init
+global function ClassicMP_TryDefaultIntroSetup
+
+// intro setups
+global function ClassicMP_SetLevelIntro
global function ClassicMP_SetCustomIntro
+global function ClassicMP_SetupIntro
+
+// intro funcs
global function ClassicMP_OnIntroStarted
global function ClassicMP_OnIntroFinished
global function ClassicMP_GetIntroLength
+
+// epilogue setups
+global function ClassicMP_ForceDisableEpilogue
+global function ClassicMP_SetEpilogue
+global function ClassicMP_SetupEpilogue
+global function ClassicMP_ShouldRunEpilogue
+
global function GetClassicMPMode
struct {
- void functionref() introSetupFunc
- float introLength
+ // level intros have a lower priority than custom intros
+ // level intros are used only if a custom intro was not specified
+ void functionref() levelIntroSetupFunc
+ float levelIntroLength
+
+ void functionref() customIntroSetupFunc
+ float customIntroLength
+
+ bool epilogueForceDisabled = false
+ void functionref() epilogueSetupFunc
} file
void function ClassicMp_Init()
{
- // literally nothing to do here atm lol
+ // default level intros
+ if ( IsFFAGame() )
+ ClassicMP_SetLevelIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
+ else
+ ClassicMP_SetLevelIntro( ClassicMP_DefaultDropshipIntro_Setup, DROPSHIP_INTRO_LENGTH )
}
+// stub func, called in mp_sh_init
void function ClassicMP_TryDefaultIntroSetup()
{
- if ( file.introSetupFunc == null )
- {
- if ( IsFFAGame() )
- ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
- else
- ClassicMP_SetCustomIntro( ClassicMP_DefaultDropshipIntro_Setup, DROPSHIP_INTRO_LENGTH )
- }
-
- thread DelayedDoDefaultIntroSetup()
+
}
-void function DelayedDoDefaultIntroSetup()
+void function ClassicMP_SetLevelIntro( void functionref() setupFunc, float introLength )
{
- // wait a frame for CodeCallback_MapInit to run which generally sets custom intros
- WaitFrame()
- file.introSetupFunc()
+ file.levelIntroSetupFunc = setupFunc
+ file.levelIntroLength = introLength
}
void function ClassicMP_SetCustomIntro( void functionref() setupFunc, float introLength )
{
- file.introSetupFunc = setupFunc
- file.introLength = introLength
+ file.customIntroSetupFunc = setupFunc
+ file.customIntroLength = introLength
+}
+
+void function ClassicMP_SetupIntro()
+{
+ if ( file.customIntroSetupFunc != null )
+ file.customIntroSetupFunc()
+ else
+ file.levelIntroSetupFunc()
}
void function ClassicMP_OnIntroStarted()
{
print( "started intro!" )
- SetServerVar( "gameStartTime", Time() + file.introLength )
- SetServerVar( "roundStartTime", Time() + file.introLength )
+
+ float introLength = ClassicMP_GetIntroLength()
+ SetServerVar( "gameStartTime", Time() + introLength )
+ SetServerVar( "roundStartTime", Time() + introLength )
}
void function ClassicMP_OnIntroFinished()
@@ -58,10 +85,37 @@ void function ClassicMP_OnIntroFinished()
float function ClassicMP_GetIntroLength()
{
- return file.introLength
+ if ( file.customIntroSetupFunc != null )
+ return file.customIntroLength
+
+ return file.levelIntroLength
+}
+
+void function ClassicMP_ForceDisableEpilogue( bool disabled )
+{
+ file.epilogueForceDisabled = disabled
+}
+
+void function ClassicMP_SetEpilogue( void functionref() setupFunc )
+{
+ file.epilogueSetupFunc = setupFunc
+}
+
+void function ClassicMP_SetupEpilogue()
+{
+ if ( file.epilogueSetupFunc == null ) // default is evac
+ ClassicMP_SetEpilogue( EvacEpilogueSetup )
+
+ file.epilogueSetupFunc()
}
bool function GetClassicMPMode()
{
return GetCurrentPlaylistVarInt( "classic_mp", 1 ) == 1
+}
+
+bool function ClassicMP_ShouldRunEpilogue()
+{
+ // note: there is a run_evac playlist var, but it's unused, and default 0, so use a new one
+ return !file.epilogueForceDisabled && GetClassicMPMode() && !IsRoundBased() && GetCurrentPlaylistVarInt( "run_epilogue", 1 ) == 1
} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
index 197ac5e90..e3f7e0b00 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/_gamestate_mp.nut
@@ -92,7 +92,8 @@ void function SetGameState( int newState )
void function GameState_EntitiesDidLoad()
{
- // nothing of importance to put here, this is referenced in _gamestate though so need it
+ if ( GetClassicMPMode() )
+ ClassicMP_SetupIntro()
}
void function WaittillGameStateOrHigher( int gameState )
@@ -185,9 +186,29 @@ void function GameStateEnter_Prematch()
int timeLimit = GameMode_GetTimeLimit( GAMETYPE ) * 60
if ( file.switchSidesBased )
timeLimit /= 2 // endtime is half of total per side
-
+
SetServerVar( "gameEndTime", Time() + timeLimit + ClassicMP_GetIntroLength() )
SetServerVar( "roundEndTime", Time() + ClassicMP_GetIntroLength() + GameMode_GetRoundTimeLimit( GAMETYPE ) * 60 )
+
+ if ( !GetClassicMPMode() )
+ thread StartGameWithoutClassicMP()
+}
+
+void function StartGameWithoutClassicMP()
+{
+ WaitFrame() // wait for callbacks to finish
+
+ // need these otherwise game will complain
+ SetServerVar( "gameStartTime", Time() )
+ SetServerVar( "roundStartTime", Time() )
+
+ foreach ( entity player in GetPlayerArray() )
+ {
+ RespawnAsPilot( player )
+ ScreenFadeFromBlack( player, 0 )
+ }
+
+ SetGameState( eGameState.Playing )
}
@@ -246,38 +267,53 @@ void function GameStateEnter_WinnerDetermined()
void function GameStateEnter_WinnerDetermined_Threaded()
{
- bool killcamsWereEnabled = KillcamsEnabled()
- if ( killcamsWereEnabled ) // dont want killcams to interrupt stuff
- SetKillcamsEnabled( false )
-
+ // do win announcement
+ int winningTeam = GetWinningTeam()
+
+ foreach ( entity player in GetPlayerArray() )
+ {
+ int announcementSubstr
+ if ( winningTeam != TEAM_UNASSIGNED )
+ announcementSubstr = player.GetTeam() == winningTeam ? file.announceRoundWinnerWinningSubstr : file.announceRoundWinnerLosingSubstr
+
+ if ( IsRoundBased() )
+ Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceRoundWinner", GetWinningTeam(), announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME, GameRules_GetTeamScore2( TEAM_MILITIA ), GameRules_GetTeamScore2( TEAM_IMC ) )
+ else
+ Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceWinner", GetWinningTeam(), announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME )
+ }
+
WaitFrame() // wait a frame so other scripts can setup killreplay stuff
entity replayAttacker = file.roundWinningKillReplayAttacker
- bool doReplay = Replay_IsEnabled() && !( !IsRoundBased() && Evac_IsEnabled() ) && IsRoundWinningKillReplayEnabled() && IsValid( replayAttacker )
+ bool doReplay = Replay_IsEnabled() && !ClassicMP_ShouldRunEpilogue() && IsRoundWinningKillReplayEnabled() && IsValid( replayAttacker )
&& Time() - file.roundWinningKillReplayTime <= ROUND_WINNING_KILL_REPLAY_LENGTH_OF_REPLAY
float replayLength = 2.0 // extra delay if no replay
if ( doReplay )
{
+ bool killcamsWereEnabled = KillcamsEnabled()
+ if ( killcamsWereEnabled ) // dont want killcams to interrupt stuff
+ SetKillcamsEnabled( false )
+
replayLength = ROUND_WINNING_KILL_REPLAY_LENGTH_OF_REPLAY
if ( "respawnTime" in replayAttacker.s && Time() - replayAttacker.s.respawnTime < replayLength )
replayLength += Time() - expect float ( replayAttacker.s.respawnTime )
SetServerVar( "roundWinningKillReplayEntHealthFrac", file.roundWinningKillReplayHealthFrac )
- }
-
- foreach ( entity player in GetPlayerArray() )
- thread PlayerWatchesRoundWinningKillReplay( player, doReplay, replayLength )
-
- wait ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME
- CleanUpEntitiesForRoundEnd() // fade should be done by this point, so cleanup stuff now when people won't see
- wait replayLength
-
- WaitFrame() // prevent a race condition with PlayerWatchesRoundWinningKillReplay
- file.roundWinningKillReplayAttacker = null // clear this
+
+ foreach ( entity player in GetPlayerArray() )
+ thread PlayerWatchesRoundWinningKillReplay( player, doReplay, replayLength )
- if ( killcamsWereEnabled )
- SetKillcamsEnabled( true )
+ wait ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME
+ CleanUpEntitiesForRoundEnd() // fade should be done by this point, so cleanup stuff now when people won't see
+ wait replayLength
+
+ WaitFrame() // prevent a race condition with PlayerWatchesRoundWinningKillReplay
+ file.roundWinningKillReplayAttacker = null // clear this
+
+ if ( killcamsWereEnabled )
+ SetKillcamsEnabled( true )
+ }
if ( IsRoundBased() )
{
@@ -299,8 +335,11 @@ void function GameStateEnter_WinnerDetermined_Threaded()
}
else
{
- if ( Evac_IsEnabled() )
+ if ( ClassicMP_ShouldRunEpilogue() )
+ {
+ ClassicMP_SetupEpilogue()
SetGameState( eGameState.Epilogue )
+ }
else
SetGameState( eGameState.Postmatch )
}
@@ -309,18 +348,8 @@ void function GameStateEnter_WinnerDetermined_Threaded()
void function PlayerWatchesRoundWinningKillReplay( entity player, bool doReplay, float replayLength )
{
player.FreezeControlsOnServer()
-
- int winningTeam = GetWinningTeam()
- int announcementSubstr
- if ( winningTeam != TEAM_UNASSIGNED )
- announcementSubstr = player.GetTeam() == winningTeam ? file.announceRoundWinnerWinningSubstr : file.announceRoundWinnerLosingSubstr
-
- if ( IsRoundBased() )
- Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceRoundWinner", winningTeam, announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME, GameRules_GetTeamScore2( TEAM_MILITIA ), GameRules_GetTeamScore2( TEAM_IMC ) )
- else
- Remote_CallFunction_NonReplay( player, "ServerCallback_AnnounceWinner", winningTeam, announcementSubstr, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME )
- if ( IsRoundBased() || !Evac_IsEnabled() ) // if we're doing evac, then no fades or killreplay
+ if ( IsRoundBased() || !ClassicMP_ShouldRunEpilogue() ) // if we're doing evac, then no fades or killreplay
{
ScreenFadeToBlackForever( player, ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME )
wait ROUND_WINNING_KILL_REPLAY_SCREEN_FADE_TIME
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut
index d61d6baa6..178b6560a 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/_lf_maps_shared.gnut
@@ -4,5 +4,5 @@ global function SetupLiveFireMaps
void function SetupLiveFireMaps()
{
Riff_ForceTitanAvailability( eTitanAvailability.Never )
- ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
+ ClassicMP_SetLevelIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
} \ No newline at end of file
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut
index 68b49ad59..87c9ea985 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/mp/levels/mp_angel_city.nut
@@ -2,12 +2,12 @@ global function CodeCallback_MapInit
void function CodeCallback_MapInit()
{
- Evac_AddLocation( < 2527.889893, -2865.360107, 753.002991 >, < 0, -80.54, 0 > )
- Evac_AddLocation( < 1253.530029, -554.075012, 811.125 >, < 0, 180, 0 > )
- Evac_AddLocation( < 2446.989990, 809.364014, 576.0 >, < 0, 90.253, 0 > )
- Evac_AddLocation( < -2027.430054, 960.395020, 609.007996 >, < 0, 179.604, 0 > )
+ AddEvacNode( CreateScriptRef( < 2527.889893, -2865.360107, 753.002991 >, < 0, -80.54, 0 > ) )
+ AddEvacNode( CreateScriptRef( < 1253.530029, -554.075012, 811.125 >, < 0, 180, 0 > ) )
+ AddEvacNode( CreateScriptRef( < 2446.989990, 809.364014, 576.0 >, < 0, 90.253, 0 > ) )
+ AddEvacNode( CreateScriptRef( < -2027.430054, 960.395020, 609.007996 >, < 0, 179.604, 0 > ) )
- Evac_SetSpacePosition( < -1700, -5500, -7600 >, < -3.620642, 270.307129, 0 > )
+ SetEvacSpaceNode( CreateScriptRef( < -1700, -5500, -7600 >, < -3.620642, 270.307129, 0 > ) )
// todo: also we need to change the powerup spawns on this map, they use a version from an older patch