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
|
#endif
|
||||||
SelectSpawnPoint( ent->client->ps.origin, origin, angles );
|
SelectSpawnPoint( ent->client->ps.origin, origin, angles, qfalse );
|
||||||
TeleportPlayer( ent, origin, angles );
|
TeleportPlayer( ent, origin, angles );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,7 @@ go to a random point that doesn't telefrag
|
||||||
================
|
================
|
||||||
*/
|
*/
|
||||||
#define MAX_SPAWN_POINTS 128
|
#define MAX_SPAWN_POINTS 128
|
||||||
gentity_t *SelectRandomDeathmatchSpawnPoint( void ) {
|
gentity_t *SelectRandomDeathmatchSpawnPoint(qboolean isbot) {
|
||||||
gentity_t *spot;
|
gentity_t *spot;
|
||||||
int count;
|
int count;
|
||||||
int selection;
|
int selection;
|
||||||
|
@ -149,10 +149,18 @@ gentity_t *SelectRandomDeathmatchSpawnPoint( void ) {
|
||||||
count = 0;
|
count = 0;
|
||||||
spot = NULL;
|
spot = NULL;
|
||||||
|
|
||||||
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
|
while((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL && count < MAX_SPAWN_POINTS)
|
||||||
if ( SpotWouldTelefrag( spot ) ) {
|
{
|
||||||
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
spots[count] = spot;
|
spots[count] = spot;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -172,49 +180,68 @@ SelectRandomFurthestSpawnPoint
|
||||||
Chooses a player start, deathmatch start, etc
|
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;
|
gentity_t *spot;
|
||||||
vec3_t delta;
|
vec3_t delta;
|
||||||
float dist;
|
float dist;
|
||||||
float list_dist[64];
|
float list_dist[MAX_SPAWN_POINTS];
|
||||||
gentity_t *list_spot[64];
|
gentity_t *list_spot[MAX_SPAWN_POINTS];
|
||||||
int numSpots, rnd, i, j;
|
int numSpots, rnd, i, j;
|
||||||
|
|
||||||
numSpots = 0;
|
numSpots = 0;
|
||||||
spot = NULL;
|
spot = NULL;
|
||||||
|
|
||||||
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
|
while((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
|
||||||
if ( SpotWouldTelefrag( spot ) ) {
|
{
|
||||||
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorSubtract( spot->s.origin, avoidPoint, delta );
|
VectorSubtract( spot->s.origin, avoidPoint, delta );
|
||||||
dist = VectorLength( delta );
|
dist = VectorLength( delta );
|
||||||
for (i = 0; i < numSpots; i++) {
|
|
||||||
if ( dist > list_dist[i] ) {
|
for (i = 0; i < numSpots; i++)
|
||||||
if ( numSpots >= 64 )
|
{
|
||||||
numSpots = 64-1;
|
if(dist > list_dist[i])
|
||||||
for (j = numSpots; j > i; j--) {
|
{
|
||||||
|
if (numSpots >= MAX_SPAWN_POINTS)
|
||||||
|
numSpots = MAX_SPAWN_POINTS - 1;
|
||||||
|
|
||||||
|
for(j = numSpots; j > i; j--)
|
||||||
|
{
|
||||||
list_dist[j] = list_dist[j-1];
|
list_dist[j] = list_dist[j-1];
|
||||||
list_spot[j] = list_spot[j-1];
|
list_spot[j] = list_spot[j-1];
|
||||||
}
|
}
|
||||||
|
|
||||||
list_dist[i] = dist;
|
list_dist[i] = dist;
|
||||||
list_spot[i] = spot;
|
list_spot[i] = spot;
|
||||||
|
|
||||||
numSpots++;
|
numSpots++;
|
||||||
if (numSpots > 64)
|
|
||||||
numSpots = 64;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i >= numSpots && numSpots < 64) {
|
|
||||||
|
if(i >= numSpots && numSpots < MAX_SPAWN_POINTS)
|
||||||
|
{
|
||||||
list_dist[numSpots] = dist;
|
list_dist[numSpots] = dist;
|
||||||
list_spot[numSpots] = spot;
|
list_spot[numSpots] = spot;
|
||||||
numSpots++;
|
numSpots++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!numSpots) {
|
|
||||||
|
if(!numSpots)
|
||||||
|
{
|
||||||
spot = G_Find(NULL, FOFS(classname), "info_player_deathmatch");
|
spot = G_Find(NULL, FOFS(classname), "info_player_deathmatch");
|
||||||
|
|
||||||
if (!spot)
|
if (!spot)
|
||||||
G_Error( "Couldn't find a spawn point" );
|
G_Error( "Couldn't find a spawn point" );
|
||||||
|
|
||||||
VectorCopy (spot->s.origin, origin);
|
VectorCopy (spot->s.origin, origin);
|
||||||
origin[2] += 9;
|
origin[2] += 9;
|
||||||
VectorCopy (spot->s.angles, angles);
|
VectorCopy (spot->s.angles, angles);
|
||||||
|
@ -238,8 +265,8 @@ SelectSpawnPoint
|
||||||
Chooses a player start, deathmatch start, etc
|
Chooses a player start, deathmatch start, etc
|
||||||
============
|
============
|
||||||
*/
|
*/
|
||||||
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 ) {
|
||||||
return SelectRandomFurthestSpawnPoint( avoidPoint, origin, angles );
|
return SelectRandomFurthestSpawnPoint( avoidPoint, origin, angles, isbot );
|
||||||
|
|
||||||
/*
|
/*
|
||||||
gentity_t *spot;
|
gentity_t *spot;
|
||||||
|
@ -278,20 +305,26 @@ Try to find a spawn point marked 'initial', otherwise
|
||||||
use normal spawn selection.
|
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;
|
gentity_t *spot;
|
||||||
|
|
||||||
spot = NULL;
|
spot = NULL;
|
||||||
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL) {
|
|
||||||
if ( spot->spawnflags & 1 ) {
|
while ((spot = G_Find (spot, FOFS(classname), "info_player_deathmatch")) != NULL)
|
||||||
break;
|
{
|
||||||
}
|
if(((spot->flags & FL_NO_BOTS) && isbot) ||
|
||||||
|
((spot->flags & FL_NO_HUMANS) && !isbot))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !spot || SpotWouldTelefrag( spot ) ) {
|
if((spot->spawnflags & 0x01))
|
||||||
return SelectSpawnPoint( vec3_origin, origin, angles );
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!spot || SpotWouldTelefrag(spot))
|
||||||
|
return SelectSpawnPoint(vec3_origin, origin, angles, isbot);
|
||||||
|
|
||||||
VectorCopy (spot->s.origin, origin);
|
VectorCopy (spot->s.origin, origin);
|
||||||
origin[2] += 9;
|
origin[2] += 9;
|
||||||
VectorCopy (spot->s.angles, angles);
|
VectorCopy (spot->s.angles, angles);
|
||||||
|
@ -1050,6 +1083,8 @@ void ClientSpawn(gentity_t *ent) {
|
||||||
index = ent - g_entities;
|
index = ent - g_entities;
|
||||||
client = ent->client;
|
client = ent->client;
|
||||||
|
|
||||||
|
VectorClear(spawn_origin);
|
||||||
|
|
||||||
// find a spawn point
|
// find a spawn point
|
||||||
// do it before setting health back up, so farthest
|
// do it before setting health back up, so farthest
|
||||||
// ranging doesn't count this client
|
// ranging doesn't count this client
|
||||||
|
@ -1061,33 +1096,25 @@ void ClientSpawn(gentity_t *ent) {
|
||||||
spawnPoint = SelectCTFSpawnPoint (
|
spawnPoint = SelectCTFSpawnPoint (
|
||||||
client->sess.sessionTeam,
|
client->sess.sessionTeam,
|
||||||
client->pers.teamState.state,
|
client->pers.teamState.state,
|
||||||
spawn_origin, spawn_angles);
|
spawn_origin, spawn_angles,
|
||||||
} else {
|
!!(ent->r.svFlags & SVF_BOT));
|
||||||
do {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// the first spawn should be at a good looking spot
|
// the first spawn should be at a good looking spot
|
||||||
if ( !client->pers.initialSpawn && client->pers.localClient ) {
|
if ( !client->pers.initialSpawn && client->pers.localClient )
|
||||||
|
{
|
||||||
client->pers.initialSpawn = qtrue;
|
client->pers.initialSpawn = qtrue;
|
||||||
spawnPoint = SelectInitialSpawnPoint( spawn_origin, spawn_angles );
|
spawnPoint = SelectInitialSpawnPoint(spawn_origin, spawn_angles,
|
||||||
} else {
|
!!(ent->r.svFlags & SVF_BOT));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// don't spawn near existing origin if possible
|
// don't spawn near existing origin if possible
|
||||||
spawnPoint = SelectSpawnPoint (
|
spawnPoint = SelectSpawnPoint (
|
||||||
client->ps.origin,
|
client->ps.origin,
|
||||||
spawn_origin, spawn_angles);
|
spawn_origin, spawn_angles, !!(ent->r.svFlags & SVF_BOT));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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 );
|
|
||||||
}
|
}
|
||||||
client->pers.teamState.state = TEAM_ACTIVE;
|
client->pers.teamState.state = TEAM_ACTIVE;
|
||||||
|
|
||||||
|
|
|
@ -572,7 +572,7 @@ team_t TeamCount( int ignoreClientNum, int team );
|
||||||
int TeamLeader( int team );
|
int TeamLeader( int team );
|
||||||
team_t PickTeam( int ignoreClientNum );
|
team_t PickTeam( int ignoreClientNum );
|
||||||
void SetClientViewAngle( gentity_t *ent, vec3_t angle );
|
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 CopyToBodyQue( gentity_t *ent );
|
||||||
void respawn (gentity_t *ent);
|
void respawn (gentity_t *ent);
|
||||||
void BeginIntermission (void);
|
void BeginIntermission (void);
|
||||||
|
|
|
@ -934,7 +934,7 @@ void FindIntermissionPoint( void ) {
|
||||||
// find the intermission spot
|
// find the intermission spot
|
||||||
ent = G_Find (NULL, FOFS(classname), "info_player_intermission");
|
ent = G_Find (NULL, FOFS(classname), "info_player_intermission");
|
||||||
if ( !ent ) { // the map creator forgot to put in an intermission point...
|
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 {
|
} else {
|
||||||
VectorCopy (ent->s.origin, level.intermission_origin);
|
VectorCopy (ent->s.origin, level.intermission_origin);
|
||||||
VectorCopy (ent->s.angles, level.intermission_angle);
|
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
|
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;
|
gentity_t *spot;
|
||||||
|
|
||||||
spot = SelectRandomTeamSpawnPoint ( teamstate, team );
|
spot = SelectRandomTeamSpawnPoint ( teamstate, team );
|
||||||
|
|
||||||
if (!spot) {
|
if (!spot) {
|
||||||
return SelectSpawnPoint( vec3_origin, origin, angles );
|
return SelectSpawnPoint( vec3_origin, origin, angles, isbot );
|
||||||
}
|
}
|
||||||
|
|
||||||
VectorCopy (spot->s.origin, origin);
|
VectorCopy (spot->s.origin, origin);
|
||||||
|
|
|
@ -79,7 +79,7 @@ void Team_CheckHurtCarrier(gentity_t *targ, gentity_t *attacker);
|
||||||
void Team_InitGame(void);
|
void Team_InitGame(void);
|
||||||
void Team_ReturnFlag(int team);
|
void Team_ReturnFlag(int team);
|
||||||
void Team_FreeEntity(gentity_t *ent);
|
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);
|
gentity_t *Team_GetLocation(gentity_t *ent);
|
||||||
qboolean Team_GetLocationMsg(gentity_t *ent, char *loc, int loclen);
|
qboolean Team_GetLocationMsg(gentity_t *ent, char *loc, int loclen);
|
||||||
void TeamplayInfoMessage( gentity_t *ent );
|
void TeamplayInfoMessage( gentity_t *ent );
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue