diff options
author | Ben Millwood <thebenmachine@gmail.com> | 2011-04-14 21:23:46 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2013-01-03 00:18:04 +0000 |
commit | f63617c32ed2252f1ee41f4a2cab8e99fdbdae63 (patch) | |
tree | 4d0283fdbb0142b32075913385999b53713deeb3 /src/game/g_client.c | |
parent | e7d2b4ed776af4bf8aa8c45461fd5c4aeef65c1d (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.c | 130 |
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 ) |