aboutsummaryrefslogtreecommitdiff
path: root/Northstar.CustomServers/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'Northstar.CustomServers/scripts')
-rw-r--r--Northstar.CustomServers/scripts/vscripts/_loadouts_mp.gnut2
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_lts.nut71
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_speedball.nut2
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_ttdm.nut67
-rw-r--r--Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemode_mfd.nut66
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/_base_gametype_mp.gnut61
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/_classic_mp.nut2
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut2
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_no_intro.gnut56
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/_gamestate_mp.nut46
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/_score.nut103
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/levels/_lf_maps_shared.gnut2
-rw-r--r--Northstar.CustomServers/scripts/vscripts/mp/spawn.nut11
13 files changed, 290 insertions, 201 deletions
diff --git a/Northstar.CustomServers/scripts/vscripts/_loadouts_mp.gnut b/Northstar.CustomServers/scripts/vscripts/_loadouts_mp.gnut
index fdba12da9..74f5e0476 100644
--- a/Northstar.CustomServers/scripts/vscripts/_loadouts_mp.gnut
+++ b/Northstar.CustomServers/scripts/vscripts/_loadouts_mp.gnut
@@ -167,7 +167,7 @@ bool function ClientCommandCallback_SwapSecondaryAndWeapon3PersistentLoadoutData
bool function ClientCommandCallback_SetBurnCardPersistenceSlot( entity player, array<string> args )
{
- if ( args.len() != 1 )
+ if ( args.len() != 1 || GetGameState() >= eGameState.Playing )
return true
print( player + " SetBurnCardPersistenceSlot " + args[0] )
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_lts.nut b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_lts.nut
index 82c304b69..b9d5aa49d 100644
--- a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_lts.nut
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_lts.nut
@@ -18,57 +18,26 @@ void function GamemodeLts_Init()
SetRoundBased( true )
SetRespawnsEnabled( false )
Riff_ForceSetEliminationMode( eEliminationMode.PilotsTitans )
+ Riff_ForceSetSpawnAsTitan( eSpawnAsTitan.Always )
SetShouldUseRoundWinningKillReplay( true )
SetRoundWinningKillReplayKillClasses( true, true ) // both titan and pilot kills are tracked
-
- AddDamageCallback( "player", OnPlayerDamaged )
- AddDamageCallback( "npc_titan", OnTitanDamaged )
-
+
AddCallback_OnPilotBecomesTitan( RefreshThirtySecondWallhackHighlight )
AddCallback_OnTitanBecomesPilot( RefreshThirtySecondWallhackHighlight )
SetTimeoutWinnerDecisionFunc( CheckTitanHealthForDraw )
+ TrackTitanDamageInPlayerGameStat( PGS_ASSAULT_SCORE )
- ClassicMP_SetCustomIntro( GamemodeLTS_Intro, 0.0 ) // dont any sorta timer
+ ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
+ AddCallback_GameStateEnter( eGameState.Playing, WaitForThirtySecondsLeft )
}
-// this should also probably be moved into a generic intro rather than being lts-specific
-void function GamemodeLTS_Intro()
+void function WaitForThirtySecondsLeft()
{
- AddCallback_GameStateEnter( eGameState.Prematch, LTSIntroOnPrematchStart )
+ thread WaitForThirtySecondsLeftThreaded()
}
-void function LTSIntroOnPrematchStart()
-{
- ClassicMP_OnIntroStarted()
-
- foreach ( entity player in GetPlayerArray() )
- thread LTSIntroSpawnPlayer( player )
-
- wait 2.0 // literally a guess number for how long the drop might take
-
- ClassicMP_OnIntroFinished()
-
- thread GamemodeLTS_PlayingThink()
-}
-
-void function LTSIntroSpawnPlayer( entity player )
-{
- if ( IsAlive( player ) )
- {
- player.Die()
- WaitFrame() // this doesn't work for some reason but the player will die in roundend anyway so not really an issue
- }
-
- thread RespawnAsTitan( player, false )
-
- while ( !player.IsTitan() )
- WaitFrame()
-
- TryGameModeAnnouncement( player )
-}
-
-void function GamemodeLTS_PlayingThink()
+void function WaitForThirtySecondsLeftThreaded()
{
svGlobal.levelEnt.EndSignal( "RoundEnd" ) // end this on round end
@@ -121,7 +90,7 @@ int function CheckTitanHealthForDraw()
}
}
- // note: due to how stuff is set up rn, there's actually no way to do win/loss reasons in timeout decision funcs
+ // note: due to how stuff is set up rn, there's actually no way to do win/loss reasons outside of a SetWinner call, i.e. not in timeout winner decision
// as soon as there is, strings in question are "#GAMEMODE_TITAN_TITAN_ADVANTAGE" and "#GAMEMODE_TITAN_TITAN_DISADVANTAGE"
if ( militiaTitans != imcTitans )
@@ -130,26 +99,4 @@ int function CheckTitanHealthForDraw()
return militiaHealth > imcHealth ? TEAM_MILITIA : TEAM_IMC
return TEAM_UNASSIGNED
-}
-
-// this should be generic, not restricted to a specific gamemode
-void function AddToTitanDamageStat( entity victim, var damageInfo )
-{
- // todo: this needs to not count selfdamage
- entity attacker = DamageInfo_GetAttacker( damageInfo )
- float amount = DamageInfo_GetDamage( damageInfo )
-
- if ( attacker.IsPlayer() && attacker != victim )
- attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, amount ) // titan damage on
-}
-
-void function OnPlayerDamaged( entity player, var damageInfo )
-{
- if ( player.IsTitan() )
- AddToTitanDamageStat( player, damageInfo )
-}
-
-void function OnTitanDamaged( entity titan, var damageInfo )
-{
- AddToTitanDamageStat( titan, damageInfo )
} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_speedball.nut b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_speedball.nut
index 91ebf8c69..4532fb972 100644
--- a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_speedball.nut
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_speedball.nut
@@ -25,7 +25,7 @@ void function GamemodeSpeedball_Init()
AddCallback_OnPlayerKilled( OnPlayerKilled )
SetTimeoutWinnerDecisionFunc( TimeoutCheckFlagHolder )
- ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, NOINTRO_INTRO_LENGTH )
+ ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
}
void function CreateFlag( entity flagSpawn )
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_ttdm.nut b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_ttdm.nut
index 92119c1cc..faf3e5cad 100644
--- a/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_ttdm.nut
+++ b/Northstar.CustomServers/scripts/vscripts/gamemodes/_gamemode_ttdm.nut
@@ -1,6 +1,73 @@
global function GamemodeTTDM_Init
+const float TTDMIntroLength = 15.0
+
void function GamemodeTTDM_Init()
{
+ Riff_ForceSetSpawnAsTitan( eSpawnAsTitan.Always )
+ Riff_ForceTitanExitEnabled( eTitanExitEnabled.Never )
+ TrackTitanDamageInPlayerGameStat( PGS_ASSAULT_SCORE )
+
+ ClassicMP_SetCustomIntro( TTDMIntroSetup, TTDMIntroLength )
+
+ AddCallback_OnPlayerKilled( AddTeamScoreForPlayerKilled ) // dont have to track autotitan kills since you cant leave your titan in this mode
+
+ // probably needs scoreevent earnmeter values
+}
+
+void function TTDMIntroSetup()
+{
+ // this should show intermission cam for 15 sec in prematch, before spawning players as titans
+ AddCallback_GameStateEnter( eGameState.Prematch, TTDMIntroStart )
+ AddCallback_OnClientConnected( TTDMIntroShowIntermissionCam )
+}
+
+void function TTDMIntroStart()
+{
+ thread TTDMIntroStartThreaded()
+}
+
+void function TTDMIntroStartThreaded()
+{
+ ClassicMP_OnIntroStarted()
+
+ foreach ( entity player in GetPlayerArray() )
+ TTDMIntroShowIntermissionCam( player )
+
+ wait TTDMIntroLength
+
+ ClassicMP_OnIntroFinished()
+}
+void function TTDMIntroShowIntermissionCam( entity player )
+{
+ if ( GetGameState() != eGameState.Prematch )
+ return
+
+ thread PlayerWatchesTTDMIntroIntermissionCam( player )
+}
+
+void function PlayerWatchesTTDMIntroIntermissionCam( entity player )
+{
+ ScreenFadeFromBlack( player )
+
+ entity intermissionCam = GetEntArrayByClass_Expensive( "info_intermission" )[ 0 ]
+
+ // the angle set here seems sorta inconsistent as to whether it actually works or just stays at 0 for some reason
+ player.SetObserverModeStaticPosition( intermissionCam.GetOrigin() )
+ player.SetObserverModeStaticAngles( intermissionCam.GetAngles() )
+ player.StartObserverMode( OBS_MODE_STATIC_LOCKED )
+
+ wait TTDMIntroLength
+
+ RespawnAsTitan( player, false )
+ TryGameModeAnnouncement( player )
+}
+
+void function AddTeamScoreForPlayerKilled( entity victim, entity attacker, var damageInfo )
+{
+ if ( victim == attacker || !victim.IsPlayer() || !attacker.IsPlayer() )
+ return
+
+ AddTeamScore( GetOtherTeam( victim.GetTeam() ), 1 )
} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemode_mfd.nut b/Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemode_mfd.nut
deleted file mode 100644
index 4410a5136..000000000
--- a/Northstar.CustomServers/scripts/vscripts/gamemodes/sh_gamemode_mfd.nut
+++ /dev/null
@@ -1,66 +0,0 @@
-untyped
-
-global function GamemodeMfdShared_Init
-global function GetMarked
-global function GetPendingMarked
-global function FillMFDMarkers
-global function TargetsMarkedImmediately
-global function IsTitanMarkedForDeathMode
-
-void function GamemodeMfdShared_Init()
-{
- // mfd mfdActiveMarkedPlayerEnt are server side entities with a boss player that marks the marked
- level.mfdActiveMarkedPlayerEnt <- {}
- level.mfdActiveMarkedPlayerEnt[ TEAM_IMC ] <- null
- level.mfdActiveMarkedPlayerEnt[ TEAM_MILITIA ] <- null
-
- level.mfdPendingMarkedPlayerEnt <- {}
- level.mfdPendingMarkedPlayerEnt[ TEAM_IMC ] <- null
- level.mfdPendingMarkedPlayerEnt[ TEAM_MILITIA ] <- null
-
- SetWaveSpawnInterval( 8.0 )
-}
-
-entity function GetMarked( int team )
-{
- if ( IsValid( level.mfdActiveMarkedPlayerEnt[ team ] ) )
- return expect entity( level.mfdActiveMarkedPlayerEnt[ team ] ).GetOwner()
-
- return null
-}
-
-entity function GetPendingMarked( int team )
-{
- if ( IsValid( level.mfdPendingMarkedPlayerEnt[ team ] ) )
- return expect entity( level.mfdPendingMarkedPlayerEnt[ team ] ).GetOwner()
-
- return null
-}
-
-function FillMFDMarkers( entity ent ) //Ent used for kill replay related issues...
-{
- print( "FillMFDMarkers " + ent )
-
- if ( ent.GetTargetName() == MARKET_ENT_MARKED_NAME )
- {
- Assert( ent.GetTeam() != TEAM_UNASSIGNED )
- level.mfdActiveMarkedPlayerEnt[ ent.GetTeam() ] = ent
- }
- else if ( ent.GetTargetName() == MARKET_ENT_PENDING_MARKED_NAME )
- {
- Assert( ent.GetTeam() != TEAM_UNASSIGNED )
- level.mfdPendingMarkedPlayerEnt[ ent.GetTeam() ] = ent
- }
-
- return
-}
-
-function TargetsMarkedImmediately()
-{
- return IsRoundBased() && IsPilotEliminationBased()
-}
-
-bool function IsTitanMarkedForDeathMode()
-{
- return GetCurrentPlaylistVarInt( "titan_marked_for_death", 0 ) == 1
-} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/_base_gametype_mp.gnut b/Northstar.CustomServers/scripts/vscripts/mp/_base_gametype_mp.gnut
index 69fcfb501..5a684f20f 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/_base_gametype_mp.gnut
+++ b/Northstar.CustomServers/scripts/vscripts/mp/_base_gametype_mp.gnut
@@ -13,6 +13,7 @@ global function TryGameModeAnnouncement
global function SetKillcamsEnabled
global function KillcamsEnabled
global function SetPlayerDeathsHidden
+global function TrackTitanDamageInPlayerGameStat
global function ShouldEntTakeDamage_SPMP
global function GetTitanBuildTime
@@ -21,6 +22,7 @@ global function TitanPlayerHotDropsIntoLevel
struct {
bool killcamsEnabled = true
bool playerDeathsHidden = false
+ int titanDamageGameStat = -1
entity intermissionCamera
array<entity> specCams
@@ -35,6 +37,9 @@ void function BaseGametype_Init_MPSP()
AddClientCommandCallback( "spec_next", ClientCommandCallback_spec_next )
AddClientCommandCallback( "spec_prev", ClientCommandCallback_spec_prev )
AddClientCommandCallback( "spec_mode", ClientCommandCallback_spec_mode )
+
+ AddDamageCallback( "player", AddToTitanDamageStat )
+ AddDamageCallback( "npc_titan", AddToTitanDamageStat )
}
void function SetIntermissionCamera( entity camera )
@@ -222,10 +227,6 @@ void function CodeCallback_OnPlayerRespawned( entity player )
void function CodeCallback_OnPlayerKilled( entity player, var damageInfo )
{
PlayerOrNPCKilled( player, damageInfo )
-
- if ( player.IsTitan() )
- SoulDies( player.GetTitanSoul(), damageInfo ) // cleanup some titan stuff, no idea where else to put this
-
thread PostDeathThread_MP( player, damageInfo )
}
@@ -253,6 +254,11 @@ void function PostDeathThread_MP( entity player, var damageInfo ) // based on ga
player.SetNoTargetSmartAmmo( false )
player.ClearExtraWeaponMods()
+ player.AddToPlayerGameStat( PGS_DEATHS, 1 )
+
+ if ( player.IsTitan() )
+ SoulDies( player.GetTitanSoul(), damageInfo ) // cleanup some titan stuff, no idea where else to put this
+
ClearRespawnAvailable( player )
OnThreadEnd( function() : ( player )
@@ -285,24 +291,24 @@ void function PostDeathThread_MP( entity player, var damageInfo ) // based on ga
thread TrackDestroyTimeForReplay( attacker, replayTracker )
int damageSource = DamageInfo_GetDamageSourceIdentifier( damageInfo )
- if ( damageSource == eDamageSourceId.fall )
- {
- // this is straight up just incorrect lol, based off tf1 stuff
-
- player.SetObserverModeStaticPosition( player.GetOrigin() )
- player.SetObserverModeStaticAngles( player.GetVelocity() * -1 )
-
- player.StartObserverMode( OBS_MODE_STATIC_LOCKED )
- player.SetObserverTarget( null )
- }
- else
- {
+ //if ( damageSource == eDamageSourceId.fall )
+ //{
+ // // this is straight up just incorrect lol, based off tf1 stuff
+ //
+ // player.SetObserverModeStaticPosition( player.GetOrigin() )
+ // player.SetObserverModeStaticAngles( player.GetVelocity() * -1 )
+ //
+ // player.StartObserverMode( OBS_MODE_STATIC_LOCKED )
+ // player.SetObserverTarget( null )
+ //}
+ //else
+ //{
player.StartObserverMode( OBS_MODE_DEATHCAM )
if ( ShouldSetObserverTarget( attacker ) )
player.SetObserverTarget( attacker )
else
player.SetObserverTarget( null )
- }
+ //}
if ( !file.playerDeathsHidden )
Remote_CallFunction_NonReplay( player, "ServerCallback_YouDied", attacker.GetEncodedEHandle(), GetHealthFrac( attacker ), methodOfDeath )
@@ -356,7 +362,7 @@ void function PostDeathThread_MP( entity player, var damageInfo ) // based on ga
player.WaitSignal( "RespawnMe" ) // set in base_gametype: ClientCommand_RespawnPlayer
ClearRespawnAvailable( player ) // need so the respawn icon doesn't show for like a frame on next death
- if ( ( expect bool( player.GetPersistentVar( "spawnAsTitan" ) ) && IsTitanAvailable( player ) ) || Riff_SpawnAsTitan() == 1 ) // spawn as titan
+ if ( ( expect bool( player.GetPersistentVar( "spawnAsTitan" ) ) && IsTitanAvailable( player ) ) || ( Riff_SpawnAsTitan() > 0 && Riff_ShouldSpawnAsTitan( player ) ) ) // spawn as titan
thread RespawnAsTitan( player )
else // spawn as pilot
RespawnAsPilot( player )
@@ -562,6 +568,25 @@ void function SetPlayerDeathsHidden( bool hidden )
file.playerDeathsHidden = hidden
}
+void function TrackTitanDamageInPlayerGameStat( int playerGameStat )
+{
+ file.titanDamageGameStat = playerGameStat
+}
+
+// this should be generic, not restricted to a specific gamemode
+void function AddToTitanDamageStat( entity victim, var damageInfo )
+{
+ if ( !victim.IsTitan() || file.titanDamageGameStat == -1 )
+ return
+
+ // todo: this needs to not count selfdamage
+ entity attacker = DamageInfo_GetAttacker( damageInfo )
+ float amount = DamageInfo_GetDamage( damageInfo )
+
+ if ( attacker.IsPlayer() && attacker != victim )
+ attacker.AddToPlayerGameStat( PGS_ASSAULT_SCORE, amount ) // titan damage on
+}
+
// stuff to change later
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp.nut b/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp.nut
index d6ac8f55a..ac8a397f7 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp.nut
+++ b/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp.nut
@@ -22,7 +22,7 @@ void function ClassicMP_TryDefaultIntroSetup()
if ( file.introSetupFunc == null )
{
if ( IsFFAGame() )
- ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, NOINTRO_INTRO_LENGTH )
+ ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
else
ClassicMP_SetCustomIntro( ClassicMP_DefaultDropshipIntro_Setup, DROPSHIP_INTRO_LENGTH )
}
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut b/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut
index 20455c696..d4712cf1b 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut
+++ b/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_dropship_intro.gnut
@@ -104,7 +104,7 @@ void function OnPrematchStart()
array<entity> dropshipSpawns = GetEntArrayByClass_Expensive( "info_spawnpoint_dropship_start" )
foreach ( entity dropshipSpawn in dropshipSpawns )
{
- if ( GameModeRemove( dropshipSpawn ) )
+ if ( GameModeRemove( dropshipSpawn ) || ( GetSpawnpointGamemodeOverride() != GAMETYPE && dropshipSpawn.kv[ "gamemode_" + GetSpawnpointGamemodeOverride() ] == "0" ) )
continue
// todo: possibly make this only spawn dropships if we've got enough players to need them
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_no_intro.gnut b/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_no_intro.gnut
index 50e9e9a07..106f867b1 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_no_intro.gnut
+++ b/Northstar.CustomServers/scripts/vscripts/mp/_classic_mp_no_intro.gnut
@@ -1,7 +1,11 @@
untyped
global function ClassicMP_DefaultNoIntro_Setup
-global const float NOINTRO_INTRO_LENGTH = 10.0
+global function ClassicMP_DefaultNoIntro_GetLength
+
+global const float NOINTRO_INTRO_PILOT_LENGTH = 10.0
+global const float TITAN_DROP_SPAWN_INTRO_LENGTH = 0.0 // this intro shouldn't have a countdown visually, so we have to set the length of this intro to 0
+global const float TITAN_DROP_SPAWN_INTRO_REAL_LENGTH = 2.0 // we wait roughly this long during the intro, even when it's technically over
void function ClassicMP_DefaultNoIntro_Setup()
{
@@ -9,20 +13,35 @@ void function ClassicMP_DefaultNoIntro_Setup()
AddCallback_GameStateEnter( eGameState.Prematch, ClassicMP_DefaultNoIntro_Start )
}
+float function ClassicMP_DefaultNoIntro_GetLength()
+{
+ if ( ShouldIntroSpawnAsTitan() )
+ return TITAN_DROP_SPAWN_INTRO_LENGTH
+ else
+ return NOINTRO_INTRO_PILOT_LENGTH
+
+ unreachable
+}
+
void function ClassicMP_DefaultNoIntro_Start()
{
ClassicMP_OnIntroStarted()
foreach ( entity player in GetPlayerArray() )
- thread ClassicMP_DefaultNoIntro_SpawnPlayer( player )
+ ClassicMP_DefaultNoIntro_SpawnPlayer( player )
- wait NOINTRO_INTRO_LENGTH
-
- foreach ( entity player in GetPlayerArray() )
+ if ( ShouldIntroSpawnAsTitan() )
+ wait TITAN_DROP_SPAWN_INTRO_REAL_LENGTH
+ else
{
- player.UnfreezeControlsOnServer()
- RemoveCinematicFlag( player, CE_FLAG_CLASSIC_MP_SPAWNING )
- TryGameModeAnnouncement( player )
+ wait NOINTRO_INTRO_PILOT_LENGTH
+
+ foreach ( entity player in GetPlayerArray() )
+ {
+ player.UnfreezeControlsOnServer()
+ RemoveCinematicFlag( player, CE_FLAG_CLASSIC_MP_SPAWNING )
+ TryGameModeAnnouncement( player )
+ }
}
ClassicMP_OnIntroFinished()
@@ -34,13 +53,28 @@ void function ClassicMP_DefaultNoIntro_SpawnPlayer( entity player )
return
if ( IsAlive( player ) )
- {
player.Die()
- WaitFrame()
- }
+ if ( ShouldIntroSpawnAsTitan() )
+ thread ClassicMP_DefaultNoIntro_TitanSpawnPlayer( player )
+ else
+ thread ClassicMP_DefaultNoIntro_PilotSpawnPlayer( player )
+}
+
+
+// spawn as pilot for intro
+void function ClassicMP_DefaultNoIntro_PilotSpawnPlayer( entity player )
+{
RespawnAsPilot( player )
player.FreezeControlsOnServer()
AddCinematicFlag( player, CE_FLAG_CLASSIC_MP_SPAWNING )
ScreenFadeFromBlack( player, 0.5, 0.5 )
+}
+
+// spawn as titan for intro
+void function ClassicMP_DefaultNoIntro_TitanSpawnPlayer( entity player )
+{
+ // blocking call
+ RespawnAsTitan( player, false )
+ TryGameModeAnnouncement( player )
} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/_gamestate_mp.nut b/Northstar.CustomServers/scripts/vscripts/mp/_gamestate_mp.nut
index 97e06377b..bbeb72fbb 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/_gamestate_mp.nut
+++ b/Northstar.CustomServers/scripts/vscripts/mp/_gamestate_mp.nut
@@ -417,6 +417,8 @@ void function PlayerWatchesSwitchingSidesKillReplay( entity player, bool doRepla
{
player.SetPredictionEnabled( false ) // prediction fucks with replays
+ // delay seems weird for switchingsides? ends literally the frame the flag is collected
+
entity attacker = file.roundWinningKillReplayAttacker
player.SetKillReplayDelay( Time() - replayLength, THIRD_PERSON_KILL_REPLAY_ALWAYS )
player.SetKillReplayInflictorEHandle( attacker.GetEncodedEHandle() )
@@ -452,34 +454,6 @@ void function GameStateEnter_SuddenDeath()
SetRespawnsEnabled( false )
}
-void function GameStateEnter_SuddenDeath_Threaded()
-{
- while ( GetGameState() == eGameState.SuddenDeath )
- {
- // todo this really ought to work for ffa in the future
- int imcPlayers
- int militiaPlayers
-
- foreach ( entity player in GetPlayerArray() )
- {
- if ( IsAlive( player ) )
- {
- if ( player.GetTeam() == TEAM_IMC )
- imcPlayers++
- else
- militiaPlayers++
- }
- }
-
- if ( imcPlayers == 0 )
- SetWinner( TEAM_MILITIA )
- else if ( militiaPlayers == 0 )
- SetWinner( TEAM_IMC )
-
- WaitFrame()
- }
-}
-
// eGameState.Postmatch
void function GameStateEnter_Postmatch()
@@ -502,6 +476,9 @@ void function GameStateEnter_Postmatch_Threaded()
void function ForceFadeToBlack( entity player )
{
+ // todo: check if this is still necessary
+ player.EndSignal( "OnDestroy" )
+
// hack until i figure out what deathcam stuff is causing fadetoblacks to be cleared
while ( true )
{
@@ -518,8 +495,9 @@ void function OnPlayerKilled( entity victim, entity attacker, var damageInfo )
if ( !GamePlayingOrSuddenDeath() )
return
- // set round winning killreplay info here if no custom replaydelay
- if ( file.roundWinningKillReplayTrackPilotKills && victim != attacker )
+ // set round winning killreplay info here if we're tracking pilot kills
+ // todo: make this not count environmental deaths like falls, unsure how to prevent this
+ if ( file.roundWinningKillReplayTrackPilotKills && victim != attacker && attacker != svGlobal.worldspawn && IsValid( attacker ) )
{
file.roundWinningKillReplayTime = Time()
file.roundWinningKillReplayVictim = victim
@@ -563,9 +541,10 @@ void function OnTitanKilled( entity victim, var damageInfo )
if ( !GamePlayingOrSuddenDeath() )
return
- // set round winning killreplay info here if no custom replaydelay
+ // set round winning killreplay info here if we're tracking titan kills
+ // todo: make this not count environmental deaths like falls, unsure how to prevent this
entity attacker = DamageInfo_GetAttacker( damageInfo )
- if ( file.roundWinningKillReplayTrackTitanKills && victim != attacker )
+ if ( file.roundWinningKillReplayTrackTitanKills && victim != attacker && attacker != svGlobal.worldspawn && IsValid( attacker ) )
{
file.roundWinningKillReplayTime = Time()
file.roundWinningKillReplayVictim = victim
@@ -625,7 +604,8 @@ void function CleanUpEntitiesForRoundEnd()
}
foreach ( entity npc in GetNPCArray() )
- npc.Die()
+ if ( IsAlive( npc ) )
+ npc.Die() // need this because getnpcarray includes the pettitans we just killed at this point
// allow other scripts to clean stuff up too
svGlobal.levelEnt.Signal( "CleanUpEntitiesForRoundEnd" )
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/_score.nut b/Northstar.CustomServers/scripts/vscripts/mp/_score.nut
index b8ea6074b..9f1e59789 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/_score.nut
+++ b/Northstar.CustomServers/scripts/vscripts/mp/_score.nut
@@ -17,7 +17,14 @@ struct {
void function Score_Init()
{
+ AddCallback_OnClientConnected( InitPlayerForScoreEvents )
+}
+void function InitPlayerForScoreEvents( entity player )
+{
+ player.s.currentKillstreak <- 0
+ player.s.lastKillTime <- 0.0
+ player.s.currentTimedKillstreak <- 0
}
void function AddPlayerScore( entity targetPlayer, string scoreEventName, entity associatedEnt = null, string noideawhatthisis = "", int pointValueOverride = -1 )
@@ -33,13 +40,29 @@ void function AddPlayerScore( entity targetPlayer, string scoreEventName, entity
if ( pointValueOverride != -1 )
event.pointValue = pointValueOverride
-
- float scale = targetPlayer.IsTitan() ? event.coreMeterScalar : 1.0
+
+ float scale = targetPlayer.IsTitan() ? event.coreMeterScalar : 1.0
+
float earnValue = event.earnMeterEarnValue * scale
float ownValue = event.earnMeterOwnValue * scale
PlayerEarnMeter_AddEarnedAndOwned( targetPlayer, earnValue * scale, ownValue * scale )
+ // PlayerEarnMeter_AddEarnedAndOwned handles this scaling by itself, we just need to do this for the visual stuff
+ float pilotScaleVar = ( expect string ( GetCurrentPlaylistVarOrUseValue( "earn_meter_pilot_multiplier", "1" ) ) ).tofloat()
+ float titanScaleVar = ( expect string ( GetCurrentPlaylistVarOrUseValue( "earn_meter_titan_multiplier", "1" ) ) ).tofloat()
+
+ if ( targetPlayer.IsTitan() )
+ {
+ earnValue *= titanScaleVar
+ ownValue *= titanScaleVar
+ }
+ else
+ {
+ earnValue *= pilotScaleVar
+ ownValue *= pilotScaleVar
+ }
+
Remote_CallFunction_NonReplay( targetPlayer, "ServerCallback_ScoreEvent", event.eventId, event.pointValue, event.displayType, associatedHandle, ownValue, earnValue )
if ( event.displayType & eEventDisplayType.CALLINGCARD ) // callingcardevents are shown to all players
@@ -54,24 +77,90 @@ void function AddPlayerScore( entity targetPlayer, string scoreEventName, entity
}
if ( ScoreEvent_HasConversation( event ) )
- thread Delayed_PlayConversationToPlayer( event.conversation, targetPlayer, event.conversationDelay )
+ PlayFactionDialogueToPlayer( event.conversation, targetPlayer )
}
void function ScoreEvent_PlayerKilled( entity victim, entity attacker, var damageInfo )
{
+ // reset killstreaks and stuff
+ victim.s.currentKillstreak = 0
+ victim.s.lastKillTime = 0.0
+ victim.s.currentTimedKillstreak = 0
+
+ victim.p.numberOfDeathsSinceLastKill++ // this is reset on kill
+
+ // have to do this early before we reset victim's player killstreaks
+ // nemesis when you kill a player that is dominating you
+ if ( attacker.IsPlayer() && attacker in victim.p.playerKillStreaks && victim.p.playerKillStreaks[ attacker ] == NEMESIS_KILL_REQUIREMENT )
+ AddPlayerScore( attacker, "Nemesis" )
+
+ // reset killstreaks on specific players
+ foreach ( entity killstreakPlayer, int numKills in victim.p.playerKillStreaks )
+ delete victim.p.playerKillStreaks[ killstreakPlayer ]
+
+ if ( victim.IsTitan() )
+ ScoreEvent_TitanKilled( victim, attacker, damageInfo )
+
+ if ( !attacker.IsPlayer() )
+ return
+
+
+ // pilot kill
AddPlayerScore( attacker, "KillPilot", victim )
+ // headshot
if ( DamageInfo_GetCustomDamageType( damageInfo ) & DF_HEADSHOT )
AddPlayerScore( attacker, "Headshot", victim )
-
+
+ // first strike
if ( !file.firstStrikeDone )
{
file.firstStrikeDone = true
AddPlayerScore( attacker, "FirstStrike", attacker )
}
- if ( victim.IsTitan() )
- ScoreEvent_TitanKilled( victim, attacker, damageInfo )
+ // comeback
+ if ( attacker.p.numberOfDeathsSinceLastKill >= COMEBACK_DEATHS_REQUIREMENT )
+ {
+ AddPlayerScore( attacker, "Comeback" )
+ attacker.p.numberOfDeathsSinceLastKill = 0
+ }
+
+
+ // untimed killstreaks
+ attacker.s.currentKillstreak++
+ if ( attacker.s.currentKillstreak == 3 )
+ AddPlayerScore( attacker, "KillingSpree" )
+ else if ( attacker.s.currentKillstreak == 5 )
+ AddPlayerScore( attacker, "Rampage" )
+
+ // increment untimed killstreaks against specific players
+ if ( !( victim in attacker.p.playerKillStreaks ) )
+ attacker.p.playerKillStreaks[ victim ] <- 1
+ else
+ attacker.p.playerKillStreaks[ victim ]++
+
+ // dominating
+ if ( attacker.p.playerKillStreaks[ victim ] == DOMINATING_KILL_REQUIREMENT )
+ AddPlayerScore( attacker, "Dominating" )
+
+
+ // timed killstreaks
+ if ( Time() - attacker.s.lastKillTime <= CASCADINGKILL_REQUIREMENT_TIME )
+ {
+ attacker.s.currentTimedKillstreak++
+
+ if ( attacker.s.currentTimedKillstreak == DOUBLEKILL_REQUIREMENT_KILLS )
+ AddPlayerScore( attacker, "DoubleKill" )
+ else if ( attacker.s.currentTimedKillstreak == TRIPLEKILL_REQUIREMENT_KILLS )
+ AddPlayerScore( attacker, "TripleKill" )
+ else if ( attacker.s.currentTimedKillstreak == MEGAKILL_REQUIREMENT_KILLS )
+ AddPlayerScore( attacker, "MegaKill" )
+ }
+ else
+ attacker.s.currentTimedKillstreak = 0 // reset if a kill took too long
+
+ attacker.s.lastKillTime = Time()
}
void function ScoreEvent_TitanDoomed( entity titan, entity attacker, var damageInfo )
@@ -87,6 +176,8 @@ void function ScoreEvent_TitanDoomed( entity titan, entity attacker, var damageI
void function ScoreEvent_TitanKilled( entity victim, entity attacker, var damageInfo )
{
// will this handle npc titans with no owners well? i have literally no idea
+ if ( !attacker.IsPlayer() )
+ return
if ( attacker.IsTitan() )
AddPlayerScore( attacker, "TitanKillTitan", victim.GetTitanSoul().GetOwner() )
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/levels/_lf_maps_shared.gnut b/Northstar.CustomServers/scripts/vscripts/mp/levels/_lf_maps_shared.gnut
index 69ec56fb5..d61d6baa6 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/levels/_lf_maps_shared.gnut
+++ b/Northstar.CustomServers/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, NOINTRO_INTRO_LENGTH )
+ ClassicMP_SetCustomIntro( ClassicMP_DefaultNoIntro_Setup, ClassicMP_DefaultNoIntro_GetLength() )
} \ No newline at end of file
diff --git a/Northstar.CustomServers/scripts/vscripts/mp/spawn.nut b/Northstar.CustomServers/scripts/vscripts/mp/spawn.nut
index b7a50453e..26e4c7135 100644
--- a/Northstar.CustomServers/scripts/vscripts/mp/spawn.nut
+++ b/Northstar.CustomServers/scripts/vscripts/mp/spawn.nut
@@ -7,6 +7,7 @@ global function SetSpawnsUseFrontline
global function SetRespawnsEnabled
global function RespawnsEnabled
global function SetSpawnpointGamemodeOverride
+global function GetSpawnpointGamemodeOverride
global function CreateNoSpawnArea
global function DeleteNoSpawnArea
@@ -121,6 +122,16 @@ void function SetSpawnpointGamemodeOverride( string gamemode )
file.spawnpointGamemodeOverride = gamemode
}
+string function GetSpawnpointGamemodeOverride()
+{
+ if ( file.spawnpointGamemodeOverride != "" )
+ return file.spawnpointGamemodeOverride
+ else
+ return GAMETYPE
+
+ unreachable
+}
+
void function SetSpawnsUseFrontline( bool useFrontline )
{
file.frontlineBased = useFrontline