Skip to content

Commit

Permalink
Unfuck the Spawns (#808)
Browse files Browse the repository at this point in the history
1. Get rid of the odd logic of limiting the algorithm to 3 spawn points
2. Changes the specific CTF algorithm to calculate the spawn points from the flag bases themselves rather than the initial spawn points which was causing severe inconsistencies.
3. Remove some checks in regards to map side swapping when matches reaches half-times due to odd behaviour in native code
4. Mitigate usage of `GetOtherTeam` for certain checks since that function might return Unreachable when it's a gamemode with more than 2 Teams and intentionally script crash the server.
  • Loading branch information
Zanieon authored Jul 5, 2024
1 parent 8181dd7 commit 0198d3f
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,27 +75,20 @@ void function RateSpawnpoints_CTF( int checkClass, array<entity> spawnpoints, in
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" ) )
{
if( spawn.GetTeam() == team )
allyFlagSpot = spawn.GetOrigin()
else
enemyFlagSpot = spawn.GetOrigin()
}

if ( HasSwitchedSides() )
team = GetOtherTeam( team )

array<entity> startSpawns = SpawnPoints_GetPilotStart( team )
array<entity> enemyStartSpawns = SpawnPoints_GetPilotStart( GetOtherTeam( team ) )

vector averageFriendlySpawns
vector averageEnemySpawns

foreach ( entity spawn in startSpawns )
averageFriendlySpawns += spawn.GetOrigin()

averageFriendlySpawns /= startSpawns.len()

foreach ( entity spawn in enemyStartSpawns )
averageEnemySpawns += spawn.GetOrigin()

averageEnemySpawns /= startSpawns.len()
if( Distance2D( spawnpoint.GetOrigin(), allyFlagSpot ) > Distance2D( spawnpoint.GetOrigin(), enemyFlagSpot ) )
return false

return Distance2D( spawnpoint.GetOrigin(), averageEnemySpawns ) / Distance2D( averageFriendlySpawns, averageEnemySpawns ) > 0.35
return true
}

void function CTFInitPlayer( entity player )
Expand Down
48 changes: 19 additions & 29 deletions Northstar.CustomServers/mod/scripts/vscripts/mp/spawn.nut
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ entity function FindSpawnPoint( entity player, bool isTitan, bool useStartSpawnp
{
int team = player.GetTeam()
if ( HasSwitchedSides() )
team = GetOtherTeam( team )
team = ( team == TEAM_MILITIA ) ? TEAM_IMC : TEAM_MILITIA

array<entity> spawnpoints
if ( useStartSpawnpoint )
Expand Down Expand Up @@ -181,29 +181,19 @@ entity function GetBestSpawnpoint( entity player, array<entity> spawnpoints )
foreach ( entity spawnpoint in spawnpoints )
{
if ( IsSpawnpointValid( spawnpoint, player.GetTeam() ) )
{
validSpawns.append( spawnpoint )

if ( validSpawns.len() == 3 ) // arbitrary small sample size
break
}
}

if ( validSpawns.len() == 0 )
if ( !validSpawns.len() )
{
// no valid spawns, very bad, so dont care about spawns being valid anymore
print( "found no valid spawns! spawns may be subpar!" )
foreach ( entity spawnpoint in spawnpoints )
{
validSpawns.append( spawnpoint )

if ( validSpawns.len() == 3 ) // arbitrary small sample size
break
}
}

// last resort
if ( validSpawns.len() == 0 )
if ( !validSpawns.len() )
{
print( "map has literally 0 spawnpoints, as such everything is fucked probably, attempting to use info_player_start if present" )
entity start = GetEnt( "info_player_start" )
Expand All @@ -215,7 +205,7 @@ entity function GetBestSpawnpoint( entity player, array<entity> spawnpoints )
}
}

return validSpawns[ RandomInt( validSpawns.len() ) ] // slightly randomize it
return validSpawns.getrandom() // slightly randomize it
}

bool function IsSpawnpointValid( entity spawnpoint, int team )
Expand All @@ -232,15 +222,18 @@ bool function IsSpawnpointValid( entity spawnpoint, int team )
return false
}

if( IsFFAGame() && !spawnpoint.IsVisibleToEnemies( team ) )
return true

int compareTeam = spawnpoint.GetTeam()
if ( HasSwitchedSides() && ( compareTeam == TEAM_MILITIA || compareTeam == TEAM_IMC ) )
compareTeam = GetOtherTeam( compareTeam )
if ( HasSwitchedSides() )
compareTeam = ( compareTeam == TEAM_MILITIA ) ? TEAM_IMC : TEAM_MILITIA

foreach ( bool functionref( entity, int ) customValidationRule in file.customSpawnpointValidationRules )
if ( !customValidationRule( spawnpoint, team ) )
return false

if ( spawnpoint.GetTeam() > 0 && compareTeam != team && !IsFFAGame() )
if ( spawnpoint.GetTeam() > 0 && compareTeam != team )
return false

if ( spawnpoint.IsOccupied() )
Expand All @@ -261,13 +254,12 @@ bool function IsSpawnpointValid( entity spawnpoint, int team )
return false
}

const minEnemyDist = 1000.0 // about 20 meters?
// in rsquirrel extend returns null unlike in vanilla squirrel
array< entity > spawnBlockers = GetPlayerArrayEx( "any", TEAM_ANY, TEAM_ANY, spawnpoint.GetOrigin(), minEnemyDist )
spawnBlockers.extend( GetProjectileArrayEx( "any", TEAM_ANY, TEAM_ANY, spawnpoint.GetOrigin(), minEnemyDist ) )
foreach ( entity blocker in spawnBlockers )
if ( blocker.GetTeam() != team )
return false
const minEnemyDist = 1200.0
array< entity > spawnBlockers = GetPlayerArrayEx( "any", TEAM_ANY, spawnpoint.GetTeam(), spawnpoint.GetOrigin(), minEnemyDist )
spawnBlockers.extend( GetProjectileArrayEx( "any", TEAM_ANY, spawnpoint.GetTeam(), spawnpoint.GetOrigin(), minEnemyDist ) )
spawnBlockers.extend( GetNPCArrayEx( "any", TEAM_ANY, spawnpoint.GetTeam(), spawnpoint.GetOrigin(), minEnemyDist ) )
if ( spawnBlockers.len() )
return false

// los check
return !spawnpoint.IsVisibleToEnemies( team )
Expand Down Expand Up @@ -399,11 +391,9 @@ void function InitPreferSpawnNodes()
// frontline
void function RateSpawnpoints_Frontline( int checkClass, array<entity> spawnpoints, int team, entity player )
{
float rating = RandomFloatRange( 0.0, 100.0 )
foreach ( entity spawnpoint in spawnpoints )
{
float rating = spawnpoint.CalculateFrontlineRating()
spawnpoint.CalculateRating( checkClass, player.GetTeam(), rating, rating > 0 ? rating * 0.25 : rating )
}
spawnpoint.CalculateRating( checkClass, player.GetTeam(), rating, rating )
}

// spawnzones
Expand Down

0 comments on commit 0198d3f

Please sign in to comment.