15 #define WARN_COND (!autocvar_g_mapinfo_ignore_warnings && MapInfo_Map_bspname == mi_shortname)
17 #define WARN_COND false
30 return '0 0 1' *
BIT(a);
32 return '0 1 0' *
BIT(a);
34 return '1 0 0' *
BIT(a);
178 return _MapInfo_FilterGametype(pGametype.gametype_flags, pFeatures, pFlagsRequired, pFlagsForbidden, pAbortOnGenerate);
194 LOG_TRACE(
"Autogenerated a .mapinfo, doing the rest later.");
257 for(
float i = 0; i < l; ++i)
260 if((ch !=
" ") && (ch !=
"\""))
262 for(
float j = l - i - 1; j > 0; --j)
265 if(ch !=
" ")
if(ch !=
"\"")
290 float diameter, spawnpoints;
292 bool is_q3df_map =
false;
299 bool success =
false;
318 fn =
strcat(
"maps/", pFilename,
".ent");
323 fn =
strcat(
"maps/", pFilename,
".bsp");
328 LOG_INFO(
"Generating ", pFilename,
".mapinfo: analyzing ", fn);
339 if (!((s =
fgets(fh))))
341 if(inWorldspawn == 1)
348 if(k ==
"classname" && v ==
"worldspawn")
350 else if(k ==
"author")
352 else if(k ==
"_description")
354 else if(k ==
"music")
356 else if(k ==
"noise")
366 mapMins.x =
min(mapMins.x, o.x);
367 mapMins.y =
min(mapMins.y, o.y);
368 mapMins.z =
min(mapMins.z, o.z);
369 mapMaxs.x =
max(mapMaxs.x, o.x);
370 mapMaxs.y =
max(mapMaxs.y, o.y);
371 mapMaxs.z =
max(mapMaxs.z, o.z);
373 else if(k ==
"race_place")
378 else if(k ==
"classname")
380 if(v ==
"info_player_team1")
382 else if(v ==
"info_player_team2")
384 else if(v ==
"info_player_start")
386 else if(v ==
"info_player_deathmatch")
388 else if(v ==
"weapon_nex")
390 else if(v ==
"weapon_railgun")
400 else if(v ==
"target_music" || v ==
"trigger_music")
402 else if(v ==
"target_stopTimer")
405 FOREACH(Gametypes,
true, it.m_generate_mapinfo(it, v));
411 LOG_WARN(fn,
" ended still in worldspawn, BUG");
414 diameter =
vlen(mapMaxs - mapMins);
416 vector twoBaseModes =
'0 0 0';
417 FOREACH(Gametypes, it.m_isTwoBaseMode(), twoBaseModes |= it.gametype_flags);
422 else if(!is_q3df_map)
467 if(!(pThisType.gametype_flags & pWantedType.gametype_flags))
473 if(!pWantedType.
frags)
490 if(pWantedType.m_setTeams)
494 pWantedType.m_setTeams(sa);
499 if(pWantedType == MAPINFO_TYPE_RACE)
504 cvar_set(
"g_race_qualifying_timelimit", sa);
509 if(
cvar(
"g_race_teams") < 2)
515 if(
cvar(
"g_race_teams") >= 2)
520 if(!pWantedType.
frags)
535 return t ? t.model2 :
"";
540 return t ? t.
team :
false;
546 if (!(pThisType.gametype_flags & pWantedType.gametype_flags))
561 if (sa ==
"")
continue;
588 fraglimit_normal = v;
591 case "teampointlimit":
603 FOREACH(Gametypes,
true, handled |= it.m_parse_mapinfo(k, v));
608 if (pWantedType == MAPINFO_TYPE_RACE &&
cvar(
"g_race_teams") >= 2)
611 cvar_set(
"fraglimit", fraglimit_teams);
616 cvar_set(
"fraglimit", fraglimit_normal);
622 string replacement =
"";
626 case "nexball": replacement =
"nb";
break;
627 case "freezetag": replacement =
"ft";
break;
628 case "keepaway": replacement =
"ka";
break;
629 case "invasion": replacement =
"inv";
break;
630 case "assault": replacement =
"as";
break;
631 case "race": replacement =
"rc";
break;
633 case "ffa": replacement =
"dm";
break;
635 case "oneflag": replacement =
"ctf";
break;
636 case "tourney": replacement =
"duel";
break;
638 if(is_q3compat) { replacement =
"ca"; }
break;
640 if (replacement !=
"")
643 LOG_WARNF(
"MapInfo_Type_FromString (probably %s): using deprecated name '%s'. Should use '%s'.",
MapInfo_Map_bspname, gtype, replacement);
646 FOREACH(Gametypes, it.mdl == gtype,
return it);
652 return t ? t.m_description :
"";
657 return t ? t.mdl :
"";
663 return t ? t.message : _(
"@!#%'n Tuba Throwing");
671 s = strreplace(
"\t",
"", s);
710 LOG_WARN(
"Map ", pFilename,
" references not existing config file ", s);
714 while((s =
fgets(fh)))
716 s = strreplace(
"\t",
"", s);
738 LOG_WARN(
"Map ", pFilename,
" uses too many levels of inclusion");
746 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful setting, ignored");
751 LOG_WARN(
"Map ", pFilename,
" contains a denied setting, ignored");
757 LOG_TRACE(
"Applying temporary setting ", t,
" := ", s);
762 LOG_TRACE(
"Applying temporary client setting ", t,
" := ", s);
776 if ((offset =
strstrofs(title,
" by ", 0)) >= 0)
782 else if ((offset =
strstrofs(title,
" (by ", 0)) >= 0 || (offset =
strstrofs(title,
" [by ", 0)) >= 0)
788 else if ((offset =
strstrofs(title,
"Made By ", 0)) >= 0)
795 return title !=
"" ? title :
"<TITLE>";
801 fn = strreplace(
"_",
"", fn);
802 fn = strreplace(
"-",
"", fn);
805 t = strreplace(
":",
"", t);
806 t = strreplace(
" ",
"", t);
807 t = strreplace(
"_",
"", t);
808 t = strreplace(
"-",
"", t);
809 t = strreplace(
"'",
"", t);
810 t = strdecolorize(t);
824 bool in_brackets =
false;
826 string stored_Map_description =
"";
827 string stored_Map_title =
"";
828 string stored_Map_author =
"";
829 vector stored_supportedGametypes =
'0 0 0';
830 int stored_supportedFeatures = 0;
831 int stored_flags = 0;
835 LOG_INFO(
"Generating ", pFilename,
".mapinfo: analyzing ", arena_filename);
839 if (!((s =
fgets(fh))))
854 else if(!in_brackets)
867 if(stored_Map_title !=
"")
869 if(stored_Map_author !=
"")
876 FOREACH(Gametypes, it.gametype_flags & stored_supportedGametypes,
878 _MapInfo_Map_ApplyGametype (
"", pGametypeToSet, it, true);
888 stored_Map_description =
"";
889 stored_Map_title =
"";
890 stored_Map_author =
"";
891 stored_supportedGametypes =
'0 0 0';
892 stored_supportedFeatures = 0;
898 s = strreplace(
"\t",
" ", s);
930 stored_Map_title = s;
931 else if(t ==
"author")
932 stored_Map_author = s;
940 types = strreplace(
"team",
"tdm ft", types);
941 types = strreplace(
"ffa",
"dm lms ka", types);
942 types = strreplace(
"tourney",
"duel", types);
944 types =
cons(types,
"ca kh");
949 stored_supportedGametypes |= f.gametype_flags;
952 else if(t ==
"style" && isdefi)
956 stored_supportedGametypes |= MAPINFO_TYPE_CTS.gametype_flags;
963 else if(t ==
"quote")
964 stored_Map_description = s;
979 for(
string s; (s =
fgets(fh)); )
981 s = strreplace(
"\t",
"", s);
1013 string base_pack = whichpack(
strcat(
"maps/", pFilename,
".bsp"));
1016 int glob = search_packfile_begin(
strcat(
"scripts/*", extension),
true,
true, base_pack);
1020 for(
int j = 0; j < n; ++j)
1046 LOG_WARN(
"Invalid character in map name, ignored");
1050 if(pGametypeToSet ==
NULL)
1059 fn =
strcat(
"maps/", pFilename,
".mapinfo");
1066 bool success =
false;
1083 goto mapinfo_handled;
1086 fn =
strcat(
"maps/autogenerated/", pFilename,
".mapinfo");
1121 fputs(fh,
"has weapons\n");
1123 fputs(fh,
"// uncomment this if you added weapon pickups: has weapons\n");
1125 fputs(fh,
"has turrets\n");
1127 fputs(fh,
"// uncomment this if you added turrets: has turrets\n");
1129 fputs(fh,
"has vehicles\n");
1131 fputs(fh,
"// uncomment this if you added vehicles: has vehicles\n");
1133 fputs(fh,
"frustrating\n");
1136 fputs(fh, sprintf(
"gametype %s // defaults: %s\n", MapInfo_Type_ToString(it), _MapInfo_GetDefaultEx(it)));
1139 fputs(fh,
"// optional: fog density red green blue alpha mindist maxdist\n");
1140 fputs(fh,
"// optional: settemp_for_type (all|gametypename) cvarname value\n");
1141 fputs(fh,
"// optional: clientsettemp_for_type (all|gametypename) cvarname value\n");
1142 fputs(fh,
"// optional: size mins_x mins_y mins_z maxs_x maxs_y maxs_z\n");
1143 fputs(fh,
"// optional: hidden\n");
1150 error(
"... but I just wrote it!");
1154 LOG_WARN(
"autogenerated mapinfo file ", fn,
" has been loaded; please edit that file and move it to maps/", pFilename,
".mapinfo");
1160 if (!((s =
fgets(fh))))
1180 else if(t ==
"description")
1182 else if(t ==
"author")
1193 LOG_WARN(
"Map ", pFilename,
" supports unknown feature ", t,
", ignored");
1195 else if(t ==
"hidden")
1199 else if(t ==
"forbidden")
1203 else if(t ==
"frustrating")
1207 else if(t ==
"donotwant" || t ==
"noautomaplist")
1211 else if(t ==
"gameversion_min")
1216 else if(t ==
"type")
1225 LOG_DEBUG(
"Map ", pFilename,
" supports unknown gametype ", t,
", ignored");
1227 else if(t ==
"gametype")
1234 LOG_DEBUG(
"Map ", pFilename,
" supports unknown gametype ", t,
", ignored");
1236 else if(t ==
"size")
1238 float a, b, c, d, e;
1247 LOG_WARN(
"Map ", pFilename,
" contains an incorrect size line (not enough params), syntax: size mins_x mins_y mins_z maxs_x maxs_y maxs_z");
1255 LOG_WARN(
"Map ", pFilename,
" contains an incorrect size line (too many params), syntax: size mins_x mins_y mins_z maxs_x maxs_y maxs_z");
1259 if(a >= d || b >= e || c >= f)
1262 LOG_WARN(
"Map ", pFilename,
" contains an incorrect size line, mins have to be < maxs");
1276 else if(t ==
"settemp_for_type")
1279 bool all = t ==
"all";
1283 if((all ?
MAPINFO_TYPE_ALL : f.gametype_flags) & pGametypeToSet.gametype_flags)
1290 LOG_DEBUG(
"Map ", pFilename,
" has a setting for unknown gametype ", t,
", ignored");
1293 else if(t ==
"clientsettemp_for_type")
1296 bool all = t ==
"all";
1300 if((all ?
MAPINFO_TYPE_ALL : f.gametype_flags) & pGametypeToSet.gametype_flags)
1307 LOG_DEBUG(
"Map ", pFilename,
" has a client setting for unknown gametype ", t,
", ignored");
1315 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful fog setting, ignored");
1320 else if(t ==
"cdtrack")
1334 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful cdtrack, ignored");
1343 LOG_WARN(
"Map ", pFilename,
" provides unknown info item ", t,
", ignored");
1347LABEL(mapinfo_handled)
1353 if (
world.message !=
"")
1379 LOG_WARN(
"Map ", pFilename,
" supports no gametypes, ignored");
1392 error(
"Can't select the requested gametype. This should never happen as the caller should prevent it!\n");
1404 string readsize_msg =
strcat(
"MapReadSizes ", map);
1429 m =
floor((l + r) / 2);
1476 if(!(
cvar(
"g_instagib") ||
cvar(
"g_overkill") ||
cvar(
"g_nix") ||
cvar(
"g_weaponarena") || !
cvar(
"g_pickup_items") || !
cvar(
"g_melee_only")
1486 return prev ?
prev : MAPINFO_TYPE_DEATHMATCH;
1511 FOREACH(Gametypes,
true,
cvar_set(it.netname, (it == t) ?
"1" :
"0"));
1578 if(
cvar(
"g_mapinfo_allow_unsupported_modes_and_let_stuff_break"))
1580 LOG_SEVERE(
"can't play the selected map in the given gametype. Working with only the override settings.");
1588 FOREACH(Gametypes, it.m_priority == 2,
1590 MapInfo_Map_supportedGametypes |= it.gametype_flags;
1591 RandomSelection_AddEnt(it, 1, 1);
1595 LOG_SEVEREF(
"Mapinfo system is not functional at all. Falling back to a preferred mode (%s).", t.mdl);
1615 RandomSelection_AddEnt(it, 1, it.m_priority);
1621 LOG_WARNF(
"can't play the selected map in the given gametype (%s). Falling back to a supported mode (%s).", t_prev.mdl, t.mdl);
1625 LOG_WARNF(
"the selected map lacks features required by current settings; playing anyway.");
1660 if (!
cvar(
"g_maplist_allow_hidden"))
1664 if (!
cvar(
"g_maplist_allow_frustrating"))
1674 if(
cvar(
"g_maplist_allow_frustrating") > 1)
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
string m_legacydefaults
DO NOT USE, this is compatibility for legacy maps!
bool team
does this gametype support teamplay?
bool frags
does this gametype use a point limit?
float matchacl(string acl, string str)
int cvar_settemp_restore()
float cvar_settemp(string tmp_cvar, string tmp_value)
string strtolower(string s)
ERASEABLE bool cvar_value_issafe(string s)
#define pass(name, colormin, colormax)
#define FOREACH_WORD(words, cond, body)
#define FOREACH(list, cond, body)
ERASEABLE void db_close(int db)
ERASEABLE int db_create()
ERASEABLE string db_get(int db, string key)
ERASEABLE void db_put(int db, string key, string value)
void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s, float recurse)
bool MapReadSizes(string map)
float MapInfo_CheckMap(string s)
void _MapInfo_Map_ApplyGametypeEx(string s, Gametype pWantedType, Gametype pThisType)
int _MapInfo_Cache_DB_NameToIndex
void MapInfo_LoadMapSettings_SaveGameType(Gametype t)
float MapInfo_FilterGametype(Gametype pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
string _MapInfo_CheckArenaFile(string pFilename, string pMapname)
bool MapInfo_isRedundant(string fn, string t)
float MapInfo_FindName(string s)
bool MapInfo_Get_ByID(int i)
int MapInfo_RequiredFlags()
string MapInfo_Type_ToString(Gametype t)
string MapInfo_BSPName_ByID(float i)
void _MapInfo_FilterList_swap(float i, float j, entity pass)
bool autocvar_g_mapinfo_ignore_warnings
float _MapInfo_FilterGametype(vector pGametype, int pFeatures, int pFlagsRequired, int pFlagsForbidden, bool pAbortOnGenerate)
string MapInfo_title_sans_author(string title)
Removes author string from title (if found) and copies it to MapInfo_Map_author if that wasn't set.
string _MapInfo_GlobItem(float i)
void MapInfo_FilterString(string sf)
void MapInfo_Filter_Free()
void MapInfo_LoadMap(string s, float reinit)
float _MapInfo_globhandle
vector _GametypeFlags_FromGametype(int a)
string MapInfo_Type_Description(Gametype t)
float _MapInfo_Generate(string pFilename)
string MapInfo_ListAllAllowedMaps(float pRequiredFlags, float pForbiddenFlags)
int autocvar_g_mapinfo_q3compat
Gametype MapInfo_CurrentGametype()
void MapInfo_Cache_Destroy()
string _MapInfo_GetDefault(Gametype t)
void MapInfo_Cache_Store()
void MapInfo_Cache_Create()
string _MapInfo_GetDefaultEx(Gametype t)
string _MapInfo_FindArenaFile(string pFilename, string extension)
float _MapInfo_FilterList_cmp(float i, float j, entity pass)
string _MapInfo_Map_worldspawn_music
int MapInfo_Get_ByName(string pFilename, float pAllowGenerate, Gametype pGametypeToSet)
int MapInfo_ForbiddenFlags()
int MapInfo_CurrentFeatures()
int _MapInfo_Cache_Buf_IndexToMapData
float MapInfo_Cache_Retrieve(string map)
string MapInfo_Type_ToText(Gametype t)
string MapInfo_ListAllowedMaps(Gametype type, float pRequiredFlags, float pForbiddenFlags)
int _MapInfo_Cache_Active
float _MapInfo_CheckMap(string s, bool gametype_only)
void _MapInfo_Map_ApplyGametype(string s, Gametype pWantedType, Gametype pThisType, int load_default)
void MapInfo_SwitchGameType(Gametype t)
void MapInfo_LoadMapSettings(string s)
void MapInfo_ClearTemps()
float MapInfo_FilterList_Lookup(float i)
float _MapInfo_GetTeamPlayBool(Gametype t)
Gametype MapInfo_Type_FromString(string gtype, bool dowarn, bool is_q3compat)
void MapInfo_Cache_Invalidate()
float _MapInfo_filtered_allocated
float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gametype pGametypeToSet)
void _MapInfo_Map_Reset()
bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gametype pGametypeToSet, bool isdefi, bool isgenerator)
string MapInfo_FixName(string s)
const int MAPINFO_FEATURE_MONSTERS
vector MapInfo_Map_supportedGametypes
#define MAPINFO_SETTEMP_ACL_USER
string MapInfo_FindName_match
float MapInfo_FindName_firstResult
Gametype MapInfo_LoadedGametype
const int MAPINFO_FLAG_FORBIDDEN
string MapInfo_Map_bspname
int MapInfo_Map_supportedFeatures
string MapInfo_Map_author
const int MAPINFO_FEATURE_WEAPONS
const int MAPINFO_FLAG_HIDDEN
const int MAPINFO_FEATURE_VEHICLES
#define MAPINFO_SETTEMP_ACL_SYSTEM
string MapInfo_Map_titlestring
const int MAPINFO_FEATURE_TURRETS
string MapInfo_Map_clientstuff
string MapInfo_Map_description
const int MAPINFO_FLAG_FRUSTRATING
const int MAPINFO_FLAG_DONOTWANT
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
ERASEABLE void RandomSelection_Init()
entity RandomSelection_chosen_ent
string GetField_fullspawndata(entity e, string fieldname, bool vfspath)
Retrieves the value of a map entity field from fullspawndata.
ERASEABLE void heapsort(int n, swapfunc_t swap, comparefunc_t cmp, entity pass)
ERASEABLE string car(string s)
returns first word
ERASEABLE string cdr(string s)
returns all but first word
#define startsWith(haystack, needle)
ERASEABLE bool startsWithNocase(string haystack, string needle)
ERASEABLE string cons(string a, string b)