.bool notvq3;
.bool notcpm;
.string gametype;
+.string not_gametype;
bool DoesQ3ARemoveThisEntity(entity this)
{
// Q3 style filters (DO NOT USE, THIS IS COMPAT ONLY)
+ if (!this.classname)
+ return true;
+
// DeFRaG mappers use "notcpm" or "notvq3" to disable an entity in CPM or VQ3 physics
// Xonotic is usually played with a CPM-based physics so we default to CPM mode
if(cvar_string("g_mod_physics") == "Q3")
if(this.notta)
return true;
- // FIXME: singleplayer does not use maxclients 1 as that would prevent bots
+ // FIXME: singleplayer does not use maxclients 1 as that would prevent bots,
+ // this is the case in Q3 also, it uses another method to block clients.
+ // Only accessible in VQ3, via the `spmap` command.
if(this.notsingle)
- if(maxclients == 1)
+ if(maxclients == 1 && IS_GAMETYPE(DEATHMATCH))
return true;
if(this.notteam)
if(!teamplay)
return true;
- if(this.gametype)
+ if(this.gametype || this.not_gametype)
{
- string gametypename;
- // From ioq3 g_spawn.c: static char *gametypeNames[] = {"ffa", "tournament", "single", "team", "ctf", "oneflag", "obelisk", "harvester"};
- gametypename = "ffa";
+ // Q3 checks these with strstr(): case-sensitive, no gametype can be a substring of another,
+ // any separator is allowed (conventions are: spaces, commas, or commas with spaces).
+ // QL's entities.def says they're space delineated.
+
+ // Q3 gametype entity fields: ffa tournament single team ctf oneflag obelisk harvester (game/g_spawn.c)
+ // Q3 arena file 'type' key: ffa tourney ctf oneflag overload harvester (ui/ui_gameinfo.c)
+
+ // QL gametype entity fields: ffa duel tdm ca ft rr ctf ad dom har 1f race ob
+ // QL arena file 'type' key: ffa duel tdm ca ft rr ctf ad dom har oneflag race
+
+ string gametypename_q3, gametypename_ql;
+
+ // One of these will apply if our gametype has no Q3/QL equivalent
if(teamplay)
- gametypename = "team";
+ {
+ gametypename_q3 = "team";
+ gametypename_ql = "tdm";
+ }
+ else
+ gametypename_q3 = gametypename_ql = "ffa";
+
if(g_ctf)
- gametypename = "ctf";
- if(g_ctf && ctf_oneflag)
- gametypename = "oneflag";
- if(g_duel)
- gametypename = "tournament";
- if(maxclients == 1)
- gametypename = "single";
- // we do not have the other types (obelisk, harvester)
- if(strstrofs(this.gametype, gametypename, 0) < 0)
+ {
+ if (ctf_oneflag)
+ {
+ gametypename_q3 = "oneflag";
+ gametypename_ql = "1f";
+ }
+ else
+ gametypename_q3 = gametypename_ql = "ctf";
+ }
+ else if(g_duel)
+ {
+ gametypename_q3 = "tournament";
+ gametypename_ql = "duel";
+ }
+ else if(IS_GAMETYPE(DEATHMATCH) && maxclients == 1)
+ gametypename_q3 = "single";
+ else if(g_ca)
+ gametypename_ql = "ql";
+ else if(IS_GAMETYPE(FREEZETAG))
+ gametypename_ql = "ft";
+ else if(IS_GAMETYPE(DOMINATION))
+ gametypename_ql = "dom";
+ else if(g_race || g_cts)
+ gametypename_ql = "race";
+
+ if(this.gametype)
+ if(strstrofs(this.gametype, gametypename_q3, 0) < 0
+ && strstrofs(this.gametype, gametypename_ql, 0) < 0)
+ return true;
+
+ // Only supported by QL
+ if(strstrofs(this.not_gametype, gametypename_ql, 0) >= 0)
return true;
}