summaryrefslogtreecommitdiff
path: root/src/game/g_client.c
diff options
context:
space:
mode:
authorBen Millwood <thebenmachine@gmail.com>2011-04-14 21:23:46 +0000
committerTim Angus <tim@ngus.net>2013-01-03 00:18:04 +0000
commitf63617c32ed2252f1ee41f4a2cab8e99fdbdae63 (patch)
tree4d0283fdbb0142b32075913385999b53713deeb3 /src/game/g_client.c
parente7d2b4ed776af4bf8aa8c45461fd5c4aeef65c1d (diff)
* Stop bad array indices in spawn point selection, by removing the arrays entirely
* Merge duplicated code in G_Select{Alien,Human}SpawnPoint into a single G_SelectSpawnBuildable function * Don't initialise some distance variables unnecessarily
Diffstat (limited to 'src/game/g_client.c')
-rw-r--r--src/game/g_client.c130
1 files changed, 41 insertions, 89 deletions
diff --git a/src/game/g_client.c b/src/game/g_client.c
index 39854623..1061043e 100644
--- a/src/game/g_client.c
+++ b/src/game/g_client.c
@@ -156,7 +156,6 @@ G_SelectNearestDeathmatchSpawnPoint
Find the spot that we DON'T want to use
================
*/
-#define MAX_SPAWN_POINTS 128
gentity_t *G_SelectNearestDeathmatchSpawnPoint( vec3_t from )
{
gentity_t *spot;
@@ -164,7 +163,6 @@ gentity_t *G_SelectNearestDeathmatchSpawnPoint( vec3_t from )
float dist, nearestDist;
gentity_t *nearestSpot;
- nearestDist = 999999;
nearestSpot = NULL;
spot = NULL;
@@ -173,7 +171,7 @@ gentity_t *G_SelectNearestDeathmatchSpawnPoint( vec3_t from )
VectorSubtract( spot->s.origin, from, delta );
dist = VectorLength( delta );
- if( dist < nearestDist )
+ if( !nearestSpot || dist < nearestDist )
{
nearestDist = dist;
nearestSpot = spot;
@@ -191,31 +189,32 @@ G_SelectRandomDeathmatchSpawnPoint
go to a random point that doesn't telefrag
================
*/
-#define MAX_SPAWN_POINTS 128
gentity_t *G_SelectRandomDeathmatchSpawnPoint( void )
{
- gentity_t *spot;
+ gentity_t *spot, *search;
int count;
- int selection;
- gentity_t *spots[ MAX_SPAWN_POINTS ];
count = 0;
spot = NULL;
- while( ( spot = G_Find( spot, FOFS( classname ), "info_player_deathmatch" ) ) != NULL )
+ while( ( search = G_Find( search, FOFS( classname ), "info_player_deathmatch" ) ) != NULL )
{
- if( SpotWouldTelefrag( spot ) )
+ if( SpotWouldTelefrag( search ) )
continue;
- spots[ count ] = spot;
count++;
+ // this is the nth spot; choose it with probability 1/n
+ // so we definitely choose the first spot, we then have a 1/2 chance of
+ // replacing it with the second...
+ // it's pretty easy to see by induction that this works for all n
+ if( rand( ) % count == 0 )
+ spot = search;
}
if( !count ) // no spots that won't telefrag
return G_Find( NULL, FOFS( classname ), "info_player_deathmatch" );
- selection = rand( ) % count;
- return spots[ selection ];
+ return spot;
}
@@ -304,102 +303,45 @@ gentity_t *G_SelectRandomFurthestSpawnPoint ( vec3_t avoidPoint, vec3_t origin,
/*
================
-G_SelectAlienSpawnPoint
-
-go to a random point that doesn't telefrag
-================
-*/
-gentity_t *G_SelectAlienSpawnPoint( vec3_t preference )
-{
- gentity_t *spot;
- int count;
- gentity_t *spots[ MAX_SPAWN_POINTS ];
-
- if( level.numAlienSpawns <= 0 )
- return NULL;
-
- count = 0;
- spot = NULL;
-
- while( ( spot = G_Find( spot, FOFS( classname ),
- BG_Buildable( BA_A_SPAWN )->entityName ) ) != NULL )
- {
- if( !spot->spawned )
- continue;
-
- if( spot->health <= 0 )
- continue;
-
- if( !spot->s.groundEntityNum )
- continue;
-
- if( spot->clientSpawnTime > 0 )
- continue;
-
- if( G_CheckSpawnPoint( spot->s.number, spot->s.origin,
- spot->s.origin2, BA_A_SPAWN, NULL ) != NULL )
- continue;
-
- spots[ count ] = spot;
- count++;
- }
-
- if( !count )
- return NULL;
-
- return G_ClosestEnt( preference, spots, count );
-}
-
-
-/*
-================
-G_SelectHumanSpawnPoint
+G_SelectSpawnBuildable
-go to a random point that doesn't telefrag
+find the nearest buildable of the right type that is
+spawned/healthy/unblocked etc.
================
*/
-gentity_t *G_SelectHumanSpawnPoint( vec3_t preference )
+gentity_t *G_SelectSpawnBuildable( vec3_t preference, buildable_t buildable )
{
- gentity_t *spot;
- int count;
- gentity_t *spots[ MAX_SPAWN_POINTS ];
-
- if( level.numHumanSpawns <= 0 )
- return NULL;
+ gentity_t *search, *spot;
- count = 0;
- spot = NULL;
+ search = spot = NULL;
- while( ( spot = G_Find( spot, FOFS( classname ),
- BG_Buildable( BA_H_SPAWN )->entityName ) ) != NULL )
+ while( ( search = G_Find( search, FOFS( classname ),
+ BG_Buildable( buildable )->entityName ) ) != NULL )
{
- if( !spot->spawned )
+ if( !search->spawned )
continue;
- if( spot->health <= 0 )
+ if( search->health <= 0 )
continue;
- if( !spot->s.groundEntityNum )
+ if( !search->s.groundEntityNum )
continue;
- if( spot->clientSpawnTime > 0 )
+ if( search->clientSpawnTime > 0 )
continue;
- if( G_CheckSpawnPoint( spot->s.number, spot->s.origin,
- spot->s.origin2, BA_H_SPAWN, NULL ) != NULL )
+ if( G_CheckSpawnPoint( search->s.number, search->s.origin,
+ search->s.origin2, buildable, NULL ) != NULL )
continue;
- spots[ count ] = spot;
- count++;
+ if( !spot || DistanceSquared( preference, search->s.origin ) <
+ DistanceSquared( preference, spot->s.origin ) )
+ spot = search;
}
- if( !count )
- return NULL;
-
- return G_ClosestEnt( preference, spots, count );
+ return spot;
}
-
/*
===========
G_SelectSpawnPoint
@@ -425,9 +367,19 @@ gentity_t *G_SelectTremulousSpawnPoint( team_t team, vec3_t preference, vec3_t o
gentity_t *spot = NULL;
if( team == TEAM_ALIENS )
- spot = G_SelectAlienSpawnPoint( preference );
+ {
+ if( level.numAlienSpawns <= 0 )
+ return NULL;
+
+ spot = G_SelectSpawnBuildable( preference, BA_A_SPAWN );
+ }
else if( team == TEAM_HUMANS )
- spot = G_SelectHumanSpawnPoint( preference );
+ {
+ if( level.numHumanSpawns <= 0 )
+ return NULL;
+
+ spot = G_SelectSpawnBuildable( preference, BA_H_SPAWN );
+ }
//no available spots
if( !spot )