// race only (middle of the race)
g_race_qualifying = false;
pl_race_place = 0;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for respawning in race) - bailing out"));
}
// qualifying only
g_race_qualifying = 1;
pl_race_place = race_lowest_place_spawn;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
}
g_race_qualifying = 0;
for (int p = 1; p <= race_highest_place_spawn; ++p) {
pl_race_place = p;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint ", ftos(i), " misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for initially spawning in race) - bailing out"));
}
}
pl_race_checkpoint = race_NextCheckpoint(0);
g_race_qualifying = 1;
pl_race_place = race_lowest_place_spawn;
- if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false)) {
+ if (!Spawn_FilterOutBadSpots(this, findchain(classname, "info_player_deathmatch"), 0, false, true)) {
error(strcat("Checkpoint 0 misses a spawnpoint with race_place==", ftos(pl_race_place), " (used for qualifying) - bailing out"));
}
} else {
// Returns:
// _x: prio (-1 if unusable)
// _y: weight
-vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck)
+vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck, bool targetcheck)
{
// filter out spots for the wrong team
if(teamcheck >= 0)
return '-1 0 0';
if(race_spawns)
- if(spot.target == "")
+ if(!spot.target || spot.target == "")
return '-1 0 0';
if(IS_REAL_CLIENT(this))
vector spawn_score = prio * '1 0 0' + shortest * '0 1 0';
// filter out spots for assault
- if(spot.target && spot.target != "")
+ if(spot.target && spot.target != "" && targetcheck)
{
int found = 0;
for(entity targ = findchain(targetname, spot.target); targ; targ = targ.chain)
return spawn_score;
}
-void Spawn_ScoreAll(entity this, entity firstspot, float mindist, float teamcheck)
+void Spawn_ScoreAll(entity this, entity firstspot, float mindist, float teamcheck, bool targetcheck)
{
entity spot;
for(spot = firstspot; spot; spot = spot.chain)
- spot.spawnpoint_score = Spawn_Score(this, spot, mindist, teamcheck);
+ spot.spawnpoint_score = Spawn_Score(this, spot, mindist, teamcheck, targetcheck);
}
-entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck)
+entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck, bool targetcheck)
{
entity spot, spotlist, spotlistend;
spotlist = NULL;
spotlistend = NULL;
- Spawn_ScoreAll(this, firstspot, mindist, teamcheck);
+ Spawn_ScoreAll(this, firstspot, mindist, teamcheck, targetcheck);
for(spot = firstspot; spot; spot = spot.chain)
{
}
else
{
- firstspot = Spawn_FilterOutBadSpots(this, firstspot, 100, teamcheck);
+ firstspot = Spawn_FilterOutBadSpots(this, firstspot, 100, teamcheck, true);
+
+ // emergency fallback! double check without targets
+ // fixes some crashes with improperly repacked maps
+ if(!firstspot)
+ {
+ firstspot = IL_FIRST(g_spawnpoints);
+ prev = NULL;
+ IL_EACH(g_spawnpoints, true,
+ {
+ if(prev)
+ prev.chain = it;
+ it.chain = NULL;
+ prev = it;
+ });
+ firstspot = Spawn_FilterOutBadSpots(this, firstspot, 100, teamcheck, false);
+ }
// there is 50/50 chance of choosing a random spot or the furthest spot
// (this means that roughly every other spawn will be furthest, so you
.vector spawnpoint_score;
float spawnpoint_nag;
bool SpawnEvent_Send(entity this, entity to, int sf);
-entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck);
+entity Spawn_FilterOutBadSpots(entity this, entity firstspot, float mindist, float teamcheck, bool targetcheck);
entity SelectSpawnPoint(entity this, bool anypoint);
spawnfunc(info_player_deathmatch);
void spawnpoint_use(entity this, entity actor, entity trigger);