mirror of
https://github.com/ioquake/ioq3.git
synced 2024-11-10 07:11:46 +00:00
Fix bug where game freezes in infinite loop because it doesn't find a spawn point on maps with many bot/human-only spawnpoints. Thanks Pan for reporting this
This commit is contained in:
parent
018de1dd2e
commit
f5d79ea066
6 changed files with 89 additions and 62 deletions
|
@ -625,7 +625,7 @@ void ClientEvents( gentity_t *ent, int oldEventSequence ) {
|
|||
}
|
||||
}
|
||||
#endif
|
||||
SelectSpawnPoint( ent->client->ps.origin, origin, angles );
|
||||
SelectSpawnPoint( ent->client->ps.origin, origin, angles, qfalse );
|
||||
TeleportPlayer( ent, origin, angles );
|
||||
break;
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ go to a random point that doesn't telefrag
|
|||
================
|
||||
*/
|
||||
#define MAX_SPAWN_POINTS 128
|
||||
gentity_t *SelectRandomDeathmatchSpawnPoint( void ) {
|
||||
gentity_t *SelectRandomDeathmatchSpawnPoint(qboolean isbot) {
|
||||
gentity_t *spot;
|
||||
int count;
|
||||
int selection;
|
||||
|
@ -149,11 +149,19 @@ gentity_t *SelectRandomDeathmatchSpawnPoint( void ) {
|
|||
count = 0;
|
||||
spot = NULL;
|
||||
|
||||
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
|
||||
if ( SpotWouldTelefrag( spot ) ) {
|
||||
while((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL && count < MAX_SPAWN_POINTS)
|
||||
{
|
||||
if(SpotWouldTelefrag(spot))
|
||||
continue;
|
||||
|
||||
if(((spot->flags & FL_NO_BOTS) && isbot) ||
|
||||
((spot->flags & FL_NO_HUMANS) && !isbot))
|
||||
{
|
||||
// spot is not for this human/bot player
|
||||
continue;
|
||||
}
|
||||
spots[ count ] = spot;
|
||||
|
||||
spots[count] = spot;
|
||||
count++;
|
||||
}
|
||||
|
||||
|
@ -172,49 +180,68 @@ SelectRandomFurthestSpawnPoint
|
|||
Chooses a player start, deathmatch start, etc
|
||||
============
|
||||
*/
|
||||
gentity_t *SelectRandomFurthestSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles ) {
|
||||
gentity_t *SelectRandomFurthestSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles, qboolean isbot ) {
|
||||
gentity_t *spot;
|
||||
vec3_t delta;
|
||||
float dist;
|
||||
float list_dist[64];
|
||||
gentity_t *list_spot[64];
|
||||
float list_dist[MAX_SPAWN_POINTS];
|
||||
gentity_t *list_spot[MAX_SPAWN_POINTS];
|
||||
int numSpots, rnd, i, j;
|
||||
|
||||
numSpots = 0;
|
||||
spot = NULL;
|
||||
|
||||
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
|
||||
if ( SpotWouldTelefrag( spot ) ) {
|
||||
while((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
|
||||
{
|
||||
if(SpotWouldTelefrag(spot))
|
||||
continue;
|
||||
|
||||
if(((spot->flags & FL_NO_BOTS) && isbot) ||
|
||||
((spot->flags & FL_NO_HUMANS) && !isbot))
|
||||
{
|
||||
// spot is not for this human/bot player
|
||||
continue;
|
||||
}
|
||||
|
||||
VectorSubtract( spot->s.origin, avoidPoint, delta );
|
||||
dist = VectorLength( delta );
|
||||
for (i = 0; i < numSpots; i++) {
|
||||
if ( dist > list_dist[i] ) {
|
||||
if ( numSpots >= 64 )
|
||||
numSpots = 64-1;
|
||||
for (j = numSpots; j > i; j--) {
|
||||
|
||||
for (i = 0; i < numSpots; i++)
|
||||
{
|
||||
if(dist > list_dist[i])
|
||||
{
|
||||
if (numSpots >= MAX_SPAWN_POINTS)
|
||||
numSpots = MAX_SPAWN_POINTS - 1;
|
||||
|
||||
for(j = numSpots; j > i; j--)
|
||||
{
|
||||
list_dist[j] = list_dist[j-1];
|
||||
list_spot[j] = list_spot[j-1];
|
||||
}
|
||||
|
||||
list_dist[i] = dist;
|
||||
list_spot[i] = spot;
|
||||
|
||||
numSpots++;
|
||||
if (numSpots > 64)
|
||||
numSpots = 64;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= numSpots && numSpots < 64) {
|
||||
|
||||
if(i >= numSpots && numSpots < MAX_SPAWN_POINTS)
|
||||
{
|
||||
list_dist[numSpots] = dist;
|
||||
list_spot[numSpots] = spot;
|
||||
numSpots++;
|
||||
}
|
||||
}
|
||||
if (!numSpots) {
|
||||
spot = G_Find( NULL, FOFS(classname), "info_player_deathmatch");
|
||||
|
||||
if(!numSpots)
|
||||
{
|
||||
spot = G_Find(NULL, FOFS(classname), "info_player_deathmatch");
|
||||
|
||||
if (!spot)
|
||||
G_Error( "Couldn't find a spawn point" );
|
||||
|
||||
VectorCopy (spot->s.origin, origin);
|
||||
origin[2] += 9;
|
||||
VectorCopy (spot->s.angles, angles);
|
||||
|
@ -238,8 +265,8 @@ SelectSpawnPoint
|
|||
Chooses a player start, deathmatch start, etc
|
||||
============
|
||||
*/
|
||||
gentity_t *SelectSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles ) {
|
||||
return SelectRandomFurthestSpawnPoint( avoidPoint, origin, angles );
|
||||
gentity_t *SelectSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles, qboolean isbot ) {
|
||||
return SelectRandomFurthestSpawnPoint( avoidPoint, origin, angles, isbot );
|
||||
|
||||
/*
|
||||
gentity_t *spot;
|
||||
|
@ -278,19 +305,25 @@ Try to find a spawn point marked 'initial', otherwise
|
|||
use normal spawn selection.
|
||||
============
|
||||
*/
|
||||
gentity_t *SelectInitialSpawnPoint( vec3_t origin, vec3_t angles ) {
|
||||
gentity_t *SelectInitialSpawnPoint( vec3_t origin, vec3_t angles, qboolean isbot ) {
|
||||
gentity_t *spot;
|
||||
|
||||
spot = NULL;
|
||||
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
|
||||
if ( spot->spawnflags & 1 ) {
|
||||
break;
|
||||
|
||||
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
|
||||
{
|
||||
if(((spot->flags & FL_NO_BOTS) && isbot) ||
|
||||
((spot->flags & FL_NO_HUMANS) && !isbot))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if((spot->spawnflags & 0x01))
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !spot || SpotWouldTelefrag( spot ) ) {
|
||||
return SelectSpawnPoint( vec3_origin, origin, angles );
|
||||
}
|
||||
if (!spot || SpotWouldTelefrag(spot))
|
||||
return SelectSpawnPoint(vec3_origin, origin, angles, isbot);
|
||||
|
||||
VectorCopy (spot->s.origin, origin);
|
||||
origin[2] += 9;
|
||||
|
@ -1050,6 +1083,8 @@ void ClientSpawn(gentity_t *ent) {
|
|||
index = ent - g_entities;
|
||||
client = ent->client;
|
||||
|
||||
VectorClear(spawn_origin);
|
||||
|
||||
// find a spawn point
|
||||
// do it before setting health back up, so farthest
|
||||
// ranging doesn't count this client
|
||||
|
@ -1061,33 +1096,25 @@ void ClientSpawn(gentity_t *ent) {
|
|||
spawnPoint = SelectCTFSpawnPoint (
|
||||
client->sess.sessionTeam,
|
||||
client->pers.teamState.state,
|
||||
spawn_origin, spawn_angles);
|
||||
} else {
|
||||
do {
|
||||
// the first spawn should be at a good looking spot
|
||||
if ( !client->pers.initialSpawn && client->pers.localClient ) {
|
||||
client->pers.initialSpawn = qtrue;
|
||||
spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles );
|
||||
} else {
|
||||
// don't spawn near existing origin if possible
|
||||
spawnPoint = SelectSpawnPoint (
|
||||
client->ps.origin,
|
||||
spawn_origin, spawn_angles);
|
||||
}
|
||||
|
||||
// Tim needs to prevent bots from spawning at the initial point
|
||||
// on q3dm0...
|
||||
if ( ( spawnPoint->flags & FL_NO_BOTS ) && ( ent->r.svFlags & SVF_BOT ) ) {
|
||||
continue; // try again
|
||||
}
|
||||
// just to be symetric, we have a nohumans option...
|
||||
if ( ( spawnPoint->flags & FL_NO_HUMANS ) && !( ent->r.svFlags & SVF_BOT ) ) {
|
||||
continue; // try again
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
} while ( 1 );
|
||||
spawn_origin, spawn_angles,
|
||||
!!(ent->r.svFlags & SVF_BOT));
|
||||
}
|
||||
else
|
||||
{
|
||||
// the first spawn should be at a good looking spot
|
||||
if ( !client->pers.initialSpawn && client->pers.localClient )
|
||||
{
|
||||
client->pers.initialSpawn = qtrue;
|
||||
spawnPoint = SelectInitialSpawnPoint(spawn_origin, spawn_angles,
|
||||
!!(ent->r.svFlags & SVF_BOT));
|
||||
}
|
||||
else
|
||||
{
|
||||
// don't spawn near existing origin if possible
|
||||
spawnPoint = SelectSpawnPoint (
|
||||
client->ps.origin,
|
||||
spawn_origin, spawn_angles, !!(ent->r.svFlags & SVF_BOT));
|
||||
}
|
||||
}
|
||||
client->pers.teamState.state = TEAM_ACTIVE;
|
||||
|
||||
|
|
|
@ -572,7 +572,7 @@ team_t TeamCount( int ignoreClientNum, int team );
|
|||
int TeamLeader( int team );
|
||||
team_t PickTeam( int ignoreClientNum );
|
||||
void SetClientViewAngle( gentity_t *ent, vec3_t angle );
|
||||
gentity_t *SelectSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles );
|
||||
gentity_t *SelectSpawnPoint (vec3_t avoidPoint, vec3_t origin, vec3_t angles, qboolean isbot);
|
||||
void CopyToBodyQue( gentity_t *ent );
|
||||
void respawn (gentity_t *ent);
|
||||
void BeginIntermission (void);
|
||||
|
|
|
@ -934,7 +934,7 @@ void FindIntermissionPoint( void ) {
|
|||
// find the intermission spot
|
||||
ent = G_Find (NULL, FOFS(classname), "info_player_intermission");
|
||||
if ( !ent ) { // the map creator forgot to put in an intermission point...
|
||||
SelectSpawnPoint ( vec3_origin, level.intermission_origin, level.intermission_angle );
|
||||
SelectSpawnPoint ( vec3_origin, level.intermission_origin, level.intermission_angle, qfalse );
|
||||
} else {
|
||||
VectorCopy (ent->s.origin, level.intermission_origin);
|
||||
VectorCopy (ent->s.angles, level.intermission_angle);
|
||||
|
|
|
@ -977,7 +977,7 @@ qboolean Team_GetLocationMsg(gentity_t *ent, char *loc, int loclen)
|
|||
|
||||
/*
|
||||
================
|
||||
SelectRandomDeathmatchSpawnPoint
|
||||
SelectRandomTeamSpawnPoint
|
||||
|
||||
go to a random point that doesn't telefrag
|
||||
================
|
||||
|
@ -1033,13 +1033,13 @@ SelectCTFSpawnPoint
|
|||
|
||||
============
|
||||
*/
|
||||
gentity_t *SelectCTFSpawnPoint ( team_t team, int teamstate, vec3_t origin, vec3_t angles ) {
|
||||
gentity_t *SelectCTFSpawnPoint ( team_t team, int teamstate, vec3_t origin, vec3_t angles, qboolean isbot ) {
|
||||
gentity_t *spot;
|
||||
|
||||
spot = SelectRandomTeamSpawnPoint ( teamstate, team );
|
||||
|
||||
if (!spot) {
|
||||
return SelectSpawnPoint( vec3_origin, origin, angles );
|
||||
return SelectSpawnPoint( vec3_origin, origin, angles, isbot );
|
||||
}
|
||||
|
||||
VectorCopy (spot->s.origin, origin);
|
||||
|
|
|
@ -79,7 +79,7 @@ void Team_CheckHurtCarrier(gentity_t *targ, gentity_t *attacker);
|
|||
void Team_InitGame(void);
|
||||
void Team_ReturnFlag(int team);
|
||||
void Team_FreeEntity(gentity_t *ent);
|
||||
gentity_t *SelectCTFSpawnPoint ( team_t team, int teamstate, vec3_t origin, vec3_t angles );
|
||||
gentity_t *SelectCTFSpawnPoint ( team_t team, int teamstate, vec3_t origin, vec3_t angles, qboolean isbot );
|
||||
gentity_t *Team_GetLocation(gentity_t *ent);
|
||||
qboolean Team_GetLocationMsg(gentity_t *ent, char *loc, int loclen);
|
||||
void TeamplayInfoMessage( gentity_t *ent );
|
||||
|
|
Loading…
Reference in a new issue