aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Miller <william-millennium@hotmail.com>2024-09-02 20:33:36 -0300
committerGitHub <noreply@github.com>2024-09-03 01:33:36 +0200
commit957f6a3ac6ff0cca3168e15a362cee80c8e9dcf0 (patch)
tree61aef78ab65bbf7642e16117cf9cb4479f6518d7
parent628e2b39fb53f2b10fa45f58a19b23c21b0439ba (diff)
downloadNorthstarMods-957f6a3ac6ff0cca3168e15a362cee80c8e9dcf0.tar.gz
NorthstarMods-957f6a3ac6ff0cca3168e15a362cee80c8e9dcf0.zip
Complete overhaul for the CTF script (#830)v1.27.7-rc2
Refactors CTF script that was dearly needed for a while
-rw-r--r--Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ctf.nut358
1 files changed, 220 insertions, 138 deletions
diff --git a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ctf.nut b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ctf.nut
index c82dcf8fc..85b80d744 100644
--- a/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ctf.nut
+++ b/Northstar.CustomServers/mod/scripts/vscripts/gamemodes/_gamemode_ctf.nut
@@ -1,5 +1,4 @@
untyped
-// this needs a refactor lol
global function CaptureTheFlag_Init
global function RateSpawnpoints_CTF
@@ -12,16 +11,31 @@ const array<string> SWAP_FLAG_MAPS = [
struct {
entity imcFlagSpawn
entity imcFlag
- entity imcFlagReturnTrigger
entity militiaFlagSpawn
entity militiaFlag
- entity militiaFlagReturnTrigger
array<entity> imcCaptureAssistList
array<entity> militiaCaptureAssistList
} file
+
+
+
+
+
+
+
+
+
+/*
+ ██████ █████ ██████ ████████ ██ ██ ██████ ███████ ████████ ██ ██ ███████ ███████ ██ █████ ██████
+██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+██ ███████ ██████ ██ ██ ██ ██████ █████ ██ ███████ █████ █████ ██ ███████ ██ ███
+██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+ ██████ ██ ██ ██ ██ ██████ ██ ██ ███████ ██ ██ ██ ███████ ██ ███████ ██ ██ ██████
+*/
+
void function CaptureTheFlag_Init()
{
PrecacheModel( CTF_FLAG_MODEL )
@@ -30,30 +44,31 @@ void function CaptureTheFlag_Init()
PrecacheParticleSystem( FLAG_FX_ENEMY )
CaptureTheFlagShared_Init()
+
SetSwitchSidesBased( true )
SetSuddenDeathBased( true )
+
SetShouldUseRoundWinningKillReplay( true )
- SetRoundWinningKillReplayKillClasses( false, false ) // make these fully manual
+ SetRoundWinningKillReplayKillClasses( false, false )
AddCallback_OnClientConnected( CTFInitPlayer )
-
+ AddCallback_OnClientDisconnected( CTFPlayerDisconnected )
+
AddCallback_GameStateEnter( eGameState.Prematch, CreateFlags )
AddCallback_GameStateEnter( eGameState.Epilogue, RemoveFlags )
+ AddCallback_GameStateEnter( eGameState.Playing, OnPlaying )
+
AddCallback_OnTouchHealthKit( "item_flag", OnFlagCollected )
+
AddCallback_OnPlayerKilled( OnPlayerKilled )
AddCallback_OnPilotBecomesTitan( DropFlagForBecomingTitan )
- SetSpawnZoneRatingFunc( DecideSpawnZone_CTF )
AddSpawnpointValidationRule( VerifyCTFSpawnpoint )
- RegisterSignal( "FlagReturnEnded" )
RegisterSignal( "ResetDropTimeout" )
- // setup stuff for the functions in sh_gamemode_ctf
- // don't really like using level for stuff but just how it be
level.teamFlags <- {}
- // setup score event earnmeter values
ScoreEvent_SetEarnMeterValues( "KillPilot", 0.05, 0.20 )
ScoreEvent_SetEarnMeterValues( "Headshot", 0.0, 0.02 )
ScoreEvent_SetEarnMeterValues( "FirstStrike", 0.0, 0.05 )
@@ -67,33 +82,42 @@ void function CaptureTheFlag_Init()
ScoreEvent_SetEarnMeterValues( "FlagReturn", 0.0, 0.20 )
}
+
+
+
+
+
+
+
+
+/*
+███████ ██████ █████ ██ ██ ███ ██ ██ ██████ ██████ ██ ██████
+██ ██ ██ ██ ██ ██ ██ ████ ██ ██ ██ ██ ██ ██ ██
+███████ ██████ ███████ ██ █ ██ ██ ██ ██ ██ ██ ██ ██ ███ ██ ██
+ ██ ██ ██ ██ ██ ███ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+███████ ██ ██ ██ ███ ███ ██ ████ ███████ ██████ ██████ ██ ██████
+*/
+
void function CreateFlags()
{
if ( IsValid( file.imcFlagSpawn ) )
{
file.imcFlagSpawn.Destroy()
file.imcFlag.Destroy()
- file.imcFlagReturnTrigger.Destroy()
}
if ( IsValid( file.militiaFlagSpawn ) )
{
file.militiaFlagSpawn.Destroy()
file.militiaFlag.Destroy()
- file.militiaFlagReturnTrigger.Destroy()
}
foreach ( entity spawn in GetEntArrayByClass_Expensive( "info_spawnpoint_flag" ) )
{
- // on some maps flags are on the opposite side from what they should be
- // likely this is because respawn uses distance checks from spawns to check this in official
- // but i don't like doing that so just using a list of maps to swap them on lol
bool switchedSides = HasSwitchedSides() == 1
-
- // i dont know why this works and whatever we had before didn't, but yeah
+
bool shouldSwap = switchedSides
- if (!shouldSwap && SWAP_FLAG_MAPS.contains( GetMapName() ))
+ if ( !shouldSwap && SWAP_FLAG_MAPS.contains( GetMapName() ) )
shouldSwap = !shouldSwap
-
int flagTeam = spawn.GetTeam()
if ( shouldSwap )
@@ -101,48 +125,33 @@ void function CreateFlags()
flagTeam = GetOtherTeam( flagTeam )
SetTeam( spawn, flagTeam )
}
-
- // create flag base
+
entity base = CreatePropDynamic( CTF_FLAG_BASE_MODEL, spawn.GetOrigin(), spawn.GetAngles(), 0 )
SetTeam( base, spawn.GetTeam() )
svGlobal.flagSpawnPoints[ flagTeam ] = base
- // create flag
entity flag = CreateEntity( "item_flag" )
flag.SetValueForModelKey( CTF_FLAG_MODEL )
SetTeam( flag, flagTeam )
flag.MarkAsNonMovingAttachment()
- flag.Minimap_AlwaysShow( TEAM_IMC, null ) // show flag icon on minimap
+ flag.Minimap_AlwaysShow( TEAM_IMC, null )
flag.Minimap_AlwaysShow( TEAM_MILITIA, null )
flag.Minimap_SetAlignUpright( true )
DispatchSpawn( flag )
flag.SetModel( CTF_FLAG_MODEL )
- flag.SetOrigin( spawn.GetOrigin() + < 0, 0, base.GetBoundingMaxs().z * 2 > ) // ensure flag doesn't spawn clipped into geometry
+ flag.SetOrigin( spawn.GetOrigin() + < 0, 0, base.GetBoundingMaxs().z * 2 > )
flag.SetVelocity( < 0, 0, 1 > )
flag.s.canTake <- true
- flag.s.playersReturning <- []
level.teamFlags[ flag.GetTeam() ] <- flag
-
- entity returnTrigger = CreateEntity( "trigger_cylinder" )
- SetTeam( returnTrigger, flagTeam )
- returnTrigger.SetRadius( CTF_GetFlagReturnRadius() )
- returnTrigger.SetAboveHeight( CTF_GetFlagReturnRadius() )
- returnTrigger.SetBelowHeight( CTF_GetFlagReturnRadius() )
-
- returnTrigger.SetEnterCallback( OnPlayerEntersFlagReturnTrigger )
- returnTrigger.SetLeaveCallback( OnPlayerExitsFlagReturnTrigger )
- DispatchSpawn( returnTrigger )
-
- thread TrackFlagReturnTrigger( flag, returnTrigger )
+ thread FlagProximityTracker( flag )
if ( flagTeam == TEAM_IMC )
{
file.imcFlagSpawn = base
file.imcFlag = flag
- file.imcFlagReturnTrigger = returnTrigger
SetGlobalNetEnt( "imcFlag", file.imcFlag )
SetGlobalNetEnt( "imcFlagHome", file.imcFlagSpawn )
@@ -151,52 +160,76 @@ void function CreateFlags()
{
file.militiaFlagSpawn = base
file.militiaFlag = flag
- file.militiaFlagReturnTrigger = returnTrigger
SetGlobalNetEnt( "milFlag", file.militiaFlag )
SetGlobalNetEnt( "milFlagHome", file.militiaFlagSpawn )
}
}
- // reset the flag states, prevents issues where flag is home but doesnt think it's home when halftime goes
SetFlagStateForTeam( TEAM_MILITIA, eFlagState.None )
SetFlagStateForTeam( TEAM_IMC, eFlagState.None )
-
- foreach ( entity player in GetPlayerArray() )
- CTFInitPlayer( player )
}
void function RemoveFlags()
{
- // destroy all the flag related things
if ( IsValid( file.imcFlagSpawn ) )
{
PlayFX( $"P_phase_shift_main", file.imcFlagSpawn.GetOrigin() )
file.imcFlagSpawn.Destroy()
file.imcFlag.Destroy()
- file.imcFlagReturnTrigger.Destroy()
}
+
if ( IsValid( file.militiaFlagSpawn ) )
{
PlayFX( $"P_phase_shift_main", file.militiaFlagSpawn.GetOrigin() )
file.militiaFlagSpawn.Destroy()
file.militiaFlag.Destroy()
- file.militiaFlagReturnTrigger.Destroy()
}
-
- // unsure if this is needed, since the flags are destroyed? idk
+
SetFlagStateForTeam( TEAM_MILITIA, eFlagState.None )
SetFlagStateForTeam( TEAM_IMC, eFlagState.None )
}
void function RateSpawnpoints_CTF( int checkClass, array<entity> spawnpoints, int team, entity player )
{
- RateSpawnpoints_SpawnZones( checkClass, spawnpoints, team, player )
+ vector allyFlagSpot
+ vector enemyFlagSpot
+ foreach ( entity spawn in GetEntArrayByClass_Expensive( "info_spawnpoint_flag" ) )
+ {
+ if( spawn.GetTeam() == team )
+ allyFlagSpot = spawn.GetOrigin()
+ else
+ enemyFlagSpot = spawn.GetOrigin()
+ }
+
+ foreach ( entity spawn in spawnpoints )
+ {
+ float rating = 0.0
+ float allyFlagDistance = Distance2D( spawn.GetOrigin(), allyFlagSpot )
+ float enemyFlagDistance = Distance2D( spawn.GetOrigin(), enemyFlagSpot )
+
+ if( enemyFlagDistance > allyFlagDistance )
+ {
+ rating += spawn.NearbyAllyScore( team, "ai" )
+ rating += spawn.NearbyAllyScore( team, "titan" )
+ rating += spawn.NearbyAllyScore( team, "pilot" )
+
+ rating += spawn.NearbyEnemyScore( team, "ai" )
+ rating += spawn.NearbyEnemyScore( team, "titan" )
+ rating += spawn.NearbyEnemyScore( team, "pilot" )
+
+ rating = rating / allyFlagDistance
+ }
+
+ if ( spawn == player.p.lastSpawnPoint )
+ rating += GetConVarFloat( "spawnpoint_last_spawn_rating" )
+
+ spawn.CalculateRating( checkClass, team, rating, rating * 0.25 )
+ }
}
bool function VerifyCTFSpawnpoint( entity spawnpoint, int team )
{
- // ensure spawnpoints aren't too close to enemy base
vector allyFlagSpot
vector enemyFlagSpot
foreach ( entity spawn in GetEntArrayByClass_Expensive( "info_spawnpoint_flag" ) )
@@ -213,23 +246,62 @@ bool function VerifyCTFSpawnpoint( entity spawnpoint, int team )
return true
}
+
+
+
+
+
+
+
+
+/*
+██████ ██ █████ ██ ██ ███████ ██████ ██ ██████ ██████ ██ ██████
+██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+██████ ██ ███████ ████ █████ ██████ ██ ██ ██ ██ ███ ██ ██
+██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+██ ███████ ██ ██ ██ ███████ ██ ██ ███████ ██████ ██████ ██ ██████
+*/
+
+void function OnPlaying()
+{
+ foreach ( entity player in GetPlayerArray() )
+ CTFInitPlayer( player )
+}
+
void function CTFInitPlayer( entity player )
{
- if ( !IsValid( file.imcFlagSpawn ) )
+ if ( !GamePlaying() )
return
- vector imcSpawn = file.imcFlagSpawn.GetOrigin()
- Remote_CallFunction_NonReplay( player, "ServerCallback_SetFlagHomeOrigin", TEAM_IMC, imcSpawn.x, imcSpawn.y, imcSpawn.z )
+ if ( IsValid( file.imcFlagSpawn ) )
+ {
+ vector imcSpawn = file.imcFlagSpawn.GetOrigin()
+ Remote_CallFunction_NonReplay( player, "ServerCallback_SetFlagHomeOrigin", TEAM_IMC, imcSpawn.x, imcSpawn.y, imcSpawn.z )
+ }
+
+ if ( IsValid( file.militiaFlagSpawn ) )
+ {
+ vector militiaSpawn = file.militiaFlagSpawn.GetOrigin()
+ Remote_CallFunction_NonReplay( player, "ServerCallback_SetFlagHomeOrigin", TEAM_MILITIA, militiaSpawn.x, militiaSpawn.y, militiaSpawn.z )
+ }
+}
+
+void function CTFPlayerDisconnected( entity player )
+{
+ // This has no validity checks on the player because the disconnection callback happens in the exact last frame the player entity still exists
+ if( !GamePlaying() )
+ return
- vector militiaSpawn = file.militiaFlagSpawn.GetOrigin()
- Remote_CallFunction_NonReplay( player, "ServerCallback_SetFlagHomeOrigin", TEAM_MILITIA, militiaSpawn.x, militiaSpawn.y, militiaSpawn.z )
+ if ( PlayerHasEnemyFlag( player ) )
+ DropFlag( player, false )
}
void function OnPlayerKilled( entity victim, entity attacker, var damageInfo )
{
if ( !IsValid( GetFlagForTeam( GetOtherTeam( victim.GetTeam() ) ) ) ) // getting a crash idk
return
- if ( GetFlagForTeam( GetOtherTeam( victim.GetTeam() ) ).GetParent() == victim )
+
+ if ( PlayerHasEnemyFlag( victim ) )
{
if ( victim != attacker && attacker.IsPlayer() )
AddPlayerScore( attacker, "FlagCarrierKill", victim )
@@ -238,31 +310,35 @@ void function OnPlayerKilled( entity victim, entity attacker, var damageInfo )
}
}
-void function TrackFlagReturnTrigger( entity flag, entity returnTrigger )
-{
- // this is a bit of a hack, it seems parenting the return trigger to the flag actually sets the pickup radius of the flag to be the same as the trigger
- // this isn't wanted since only pickups should use that additional radius
- flag.EndSignal( "OnDestroy" )
-
- while ( true )
- {
- returnTrigger.SetOrigin( flag.GetOrigin() )
- WaitFrame()
- }
-}
+
+
+
+
+
+
+
+
+/*
+███████ ██ █████ ██████ ██ ██████ ██████ ██ ██████
+██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+█████ ██ ███████ ██ ███ ██ ██ ██ ██ ███ ██ ██
+██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██
+██ ███████ ██ ██ ██████ ███████ ██████ ██████ ██ ██████
+*/
+
bool function OnFlagCollected( entity player, entity flag )
{
if ( !IsAlive( player ) || flag.GetParent() != null || player.IsTitan() || player.IsPhaseShifted() )
return false
if ( player.GetTeam() != flag.GetTeam() && flag.s.canTake )
- GiveFlag( player, flag ) // pickup enemy flag
+ GiveFlag( player, flag )
else if ( player.GetTeam() == flag.GetTeam() && IsFlagHome( flag ) && PlayerHasEnemyFlag( player ) )
- CaptureFlag( player, GetFlagForTeam( GetOtherTeam( flag.GetTeam() ) ) ) // cap the flag
+ CaptureFlag( player, GetFlagForTeam( GetOtherTeam( flag.GetTeam() ) ) )
- return false // don't wanna delete the flag entity
+ return false // Don't delete the flag
}
void function GiveFlag( entity player, entity flag )
@@ -271,7 +347,8 @@ void function GiveFlag( entity player, entity flag )
flag.Signal( "ResetDropTimeout" )
flag.SetParent( player, "FLAG" )
- thread DropFlagIfPhased( player, flag )
+ if ( GetCurrentPlaylistVarInt( "phase_shift_drop_flag", 0 ) == 1 )
+ thread DropFlagIfPhased( player, flag )
// do notifications
MessageToPlayer( player, eEventNotifications.YouHaveTheEnemyFlag )
@@ -292,7 +369,7 @@ void function GiveFlag( entity player, entity flag )
void function CaptureFlag( entity player, entity flag )
{
// can only capture flags during normal play or sudden death
- if (GetGameState() != eGameState.Playing && GetGameState() != eGameState.SuddenDeath)
+ if ( GetGameState() != eGameState.Playing && GetGameState() != eGameState.SuddenDeath )
{
printt( player + " tried to capture the flag, but the game state was " + GetGameState() + " not " + eGameState.Playing + " or " + eGameState.SuddenDeath)
return
@@ -344,10 +421,12 @@ void function CaptureFlag( entity player, entity flag )
MessageToTeam( GetOtherTeam( team ), eEventNotifications.PlayerCapturedFriendlyFlag, player, player )
EmitSoundOnEntityToTeam( flag, "UI_CTF_3P_EnemyScores", flag.GetTeam() )
- if ( GameRules_GetTeamScore( team ) == GameMode_GetRoundScoreLimit( GAMETYPE ) - 1 )
+ if ( GameRules_GetTeamScore( team ) == GetScoreLimit_FromPlaylist() - 1 )
{
PlayFactionDialogueToTeam( "ctf_notifyWin1more", team )
PlayFactionDialogueToTeam( "ctf_notifyLose1more", GetOtherTeam( team ) )
+ foreach( entity otherPlayer in GetPlayerArray() )
+ Remote_CallFunction_NonReplay( otherPlayer, "ServerCallback_CTF_PlayMatchNearEndMusic" )
}
}
@@ -355,7 +434,7 @@ void function DropFlag( entity player, bool realDrop = true )
{
entity flag = GetFlagForTeam( GetOtherTeam( player.GetTeam() ) )
- if ( flag.GetParent() != player )
+ if( !IsValid( flag ) || flag.GetParent() != player )
return
print( player + " dropped the flag!" )
@@ -366,94 +445,92 @@ void function DropFlag( entity player, bool realDrop = true )
if ( realDrop )
{
- // start drop timeout countdown
- thread TrackFlagDropTimeout( flag )
-
- // add to capture assists
- if ( player.GetTeam() == TEAM_IMC )
+ if ( player.GetTeam() == TEAM_IMC && !file.imcCaptureAssistList.contains( player ) )
file.imcCaptureAssistList.append( player )
- else
+
+ else if( !file.militiaCaptureAssistList.contains( player ) )
file.militiaCaptureAssistList.append( player )
- // do notifications
MessageToPlayer( player, eEventNotifications.YouDroppedTheEnemyFlag )
EmitSoundOnEntityOnlyToPlayer( player, player, "UI_CTF_1P_FlagDrop" )
MessageToTeam( player.GetTeam(), eEventNotifications.PlayerDroppedEnemyFlag, player, player )
- // todo need a sound here maybe
MessageToTeam( GetOtherTeam( player.GetTeam() ), eEventNotifications.PlayerDroppedFriendlyFlag, player, player )
- // todo need a sound here maybe
}
- SetFlagStateForTeam( flag.GetTeam(), eFlagState.Home ) // used for return prompt
+ thread TrackFlagDropTimeout( flag )
+ SetFlagStateForTeam( flag.GetTeam(), eFlagState.Home )
}
void function ResetFlag( entity flag )
{
- // prevents crash when flag is reset after it's been destroyed due to epilogue
- if (!IsValid(flag))
- return
- // ensure we can't pickup the flag after it's been dropped but before it's been reset
flag.s.canTake = false
if ( flag.GetParent() != null )
DropFlag( flag.GetParent(), false )
- entity spawn
+ entity flagBase
if ( flag.GetTeam() == TEAM_IMC )
- spawn = file.imcFlagSpawn
+ flagBase = file.imcFlagSpawn
else
- spawn = file.militiaFlagSpawn
+ flagBase = file.militiaFlagSpawn
- flag.SetOrigin( spawn.GetOrigin() + < 0, 0, spawn.GetBoundingMaxs().z + 1 > )
+ flag.SetOrigin( flagBase.GetOrigin() + < 0, 0, flagBase.GetBoundingMaxs().z + 1 > )
- // we can take it again now
flag.s.canTake = true
- SetFlagStateForTeam( flag.GetTeam(), eFlagState.None ) // used for home
+ SetFlagStateForTeam( flag.GetTeam(), eFlagState.None )
flag.Signal( "ResetDropTimeout" )
}
-
-void function OnPlayerEntersFlagReturnTrigger( entity trigger, entity player )
+//-----------------------------------------------------------------------------
+// Purpose: Check proximity for flag returns
+// Input : flag - The flag entity
+//-----------------------------------------------------------------------------
+void function FlagProximityTracker( entity flag )
{
- entity flag
- if ( trigger.GetTeam() == TEAM_IMC )
- flag = file.imcFlag
- else
- flag = file.militiaFlag
-
- if( !IsValid( flag ) || !IsValid( player ) )
- return
+ flag.EndSignal( "OnDestroy" )
- if ( !player.IsPlayer() || player.IsTitan() || player.GetTeam() != flag.GetTeam() || IsFlagHome( flag ) || flag.GetParent() != null )
- return
+ array < entity > playerInsidePerimeter
+ while( true )
+ {
+ if( !playerInsidePerimeter.len() )
+ ArrayRemoveDead( playerInsidePerimeter )
- thread TryReturnFlag( player, flag )
-}
-
-void function OnPlayerExitsFlagReturnTrigger( entity trigger, entity player )
-{
- entity flag
- if ( trigger.GetTeam() == TEAM_IMC )
- flag = file.imcFlag
- else
- flag = file.militiaFlag
+ foreach ( player in GetPlayerArrayOfTeam_Alive( flag.GetTeam() ) )
+ {
+ if ( Distance( player.GetOrigin(), flag.GetOrigin() ) < CTF_GetFlagReturnRadius() )
+ {
+ if ( player.IsTitan() || player.GetTeam() != flag.GetTeam() || IsFlagHome( flag ) || flag.GetParent() != null )
+ continue
+
+ if( playerInsidePerimeter.contains( player ) )
+ continue
+
+ playerInsidePerimeter.append( player )
+ thread TryReturnFlag( player, flag )
+ }
+ else
+ {
+ if( playerInsidePerimeter.contains( player ) )
+ {
+ player.Signal( "CTF_LeftReturnTriggerArea" ) // Cut the progress if outside range
+ playerInsidePerimeter.removebyvalue( player )
+ }
+ }
+ }
- if ( !player.IsPlayer() || player.IsTitan() || player.GetTeam() != flag.GetTeam() || IsFlagHome( flag ) || flag.GetParent() != null )
- return
-
- player.Signal( "FlagReturnEnded" )
-}
+ WaitFrame()
+ }
+}
void function TryReturnFlag( entity player, entity flag )
{
- // start return progress bar
Remote_CallFunction_NonReplay( player, "ServerCallback_CTF_StartReturnFlagProgressBar", Time() + CTF_GetFlagReturnTime() )
EmitSoundOnEntityOnlyToPlayer( player, player, "UI_CTF_1P_FlagReturnMeter" )
- OnThreadEnd( function() : ( player )
+ OnThreadEnd( function() : ( flag, player )
{
if ( IsValidPlayer( player ) )
{
@@ -462,35 +539,37 @@ void function TryReturnFlag( entity player, entity flag )
}
})
- player.EndSignal( "FlagReturnEnded" )
- flag.EndSignal( "FlagReturnEnded" ) // avoid multiple players to return one flag at once
+ flag.EndSignal( "CTF_ReturnedFlag" )
+ flag.EndSignal( "OnDestroy" )
+
+ player.EndSignal( "CTF_LeftReturnTriggerArea" )
player.EndSignal( "OnDeath" )
+ player.EndSignal( "OnDestroy" )
wait CTF_GetFlagReturnTime()
- // flag return succeeded
- // return flag
ResetFlag( flag )
- flag.Signal( "FlagReturnEnded" )
-
- // do notifications for return
+
+ MessageToTeam( flag.GetTeam(), eEventNotifications.PlayerReturnedFriendlyFlag, null, player )
+ EmitSoundOnEntityToTeam( flag, "UI_CTF_3P_TeamReturnsFlag", flag.GetTeam() )
+ PlayFactionDialogueToTeam( "ctf_flagReturnedFriendly", flag.GetTeam() )
+
MessageToPlayer( player, eEventNotifications.YouReturnedFriendlyFlag )
AddPlayerScore( player, "FlagReturn", player )
player.AddToPlayerGameStat( PGS_DEFENSE_SCORE, 1 )
- if( !HasPlayerCompletedMeritScore( player ) )
+ if ( !HasPlayerCompletedMeritScore( player ) )
{
AddPlayerScore( player, "ChallengeCTFRetAssist" )
SetPlayerChallengeMeritScore( player )
}
- MessageToTeam( flag.GetTeam(), eEventNotifications.PlayerReturnedFriendlyFlag, null, player )
- EmitSoundOnEntityToTeam( flag, "UI_CTF_3P_TeamReturnsFlag", flag.GetTeam() )
- PlayFactionDialogueToTeam( "ctf_flagReturnedFriendly", flag.GetTeam() )
-
MessageToTeam( GetOtherTeam( flag.GetTeam() ), eEventNotifications.PlayerReturnedEnemyFlag, null, player )
EmitSoundOnEntityToTeam( flag, "UI_CTF_3P_EnemyReturnsFlag", GetOtherTeam( flag.GetTeam() ) )
+ EmitSoundOnEntityOnlyToPlayer( player, player, "UI_CTF_1P_ReturnsFlag" )
PlayFactionDialogueToTeam( "ctf_flagReturnedEnemy", GetOtherTeam( flag.GetTeam() ) )
+
+ flag.Signal( "CTF_ReturnedFlag" )
}
void function SetFlagStateForTeam( int team, int state )
@@ -507,6 +586,7 @@ void function DropFlagIfPhased( entity player, entity flag )
{
player.EndSignal( "StartPhaseShift" )
player.EndSignal( "OnDestroy" )
+ flag.EndSignal( "OnDestroy" )
OnThreadEnd( function() : ( player )
{
@@ -516,8 +596,8 @@ void function DropFlagIfPhased( entity player, entity flag )
DropFlag( player, true )
}
})
- // the IsValid check is purely to prevent a crash due to a destroyed flag (epilogue)
- while( IsValid(flag) && flag.GetParent() == player )
+
+ while( flag.GetParent() == player )
WaitFrame()
}
@@ -528,7 +608,9 @@ void function DropFlagForBecomingTitan( entity pilot, entity titan )
void function TrackFlagDropTimeout( entity flag )
{
+ flag.EndSignal( "CTF_ReturnedFlag" )
flag.EndSignal( "ResetDropTimeout" )
+ flag.EndSignal( "OnDestroy" )
wait CTF_GetDropTimeout()