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);
179 return _MapInfo_FilterGametype(pGametype.gametype_flags, pFeatures, pFlagsRequired, pFlagsForbidden, pAbortOnGenerate);
195 LOG_TRACE(
"Autogenerated a .mapinfo, doing the rest later.");
258 for(
float i = 0; i < l; ++i)
261 if((ch !=
" ") && (ch !=
"\""))
263 for(
float j = l - i - 1; j > 0; --j)
266 if(ch !=
" ")
if(ch !=
"\"")
291 float diameter, spawnpoints;
293 bool is_q3df_map =
false;
300 bool success =
false;
319 fn =
strcat(
"maps/", pFilename,
".ent");
324 fn =
strcat(
"maps/", pFilename,
".bsp");
329 LOG_INFO(
"Generating ", pFilename,
".mapinfo: analyzing ", fn);
340 if (!((s =
fgets(fh))))
342 if(inWorldspawn == 1)
349 if(k ==
"classname" && v ==
"worldspawn")
351 else if(k ==
"author")
353 else if(k ==
"_description")
355 else if(k ==
"music")
357 else if(k ==
"noise")
367 mapMins.x =
min(mapMins.x, o.x);
368 mapMins.y =
min(mapMins.y, o.y);
369 mapMins.z =
min(mapMins.z, o.z);
370 mapMaxs.x =
max(mapMaxs.x, o.x);
371 mapMaxs.y =
max(mapMaxs.y, o.y);
372 mapMaxs.z =
max(mapMaxs.z, o.z);
374 else if(k ==
"race_place")
379 else if(k ==
"classname")
381 if(v ==
"info_player_team1")
383 else if(v ==
"info_player_team2")
385 else if(v ==
"info_player_start")
387 else if(v ==
"info_player_deathmatch")
389 else if(v ==
"weapon_nex")
391 else if(v ==
"weapon_railgun")
401 else if(v ==
"target_music" || v ==
"trigger_music")
403 else if(v ==
"target_stopTimer")
406 FOREACH(Gametypes,
true, it.m_generate_mapinfo(it, v));
412 LOG_WARN(fn,
" ended still in worldspawn, BUG");
415 diameter =
vlen(mapMaxs - mapMins);
417 vector twoBaseModes =
'0 0 0';
418 FOREACH(Gametypes, it.m_isTwoBaseMode(), twoBaseModes |= it.gametype_flags);
423 else if(!is_q3df_map)
468 if(!(pThisType.gametype_flags & pWantedType.gametype_flags))
474 if(!pWantedType.
frags)
491 if(pWantedType.m_setTeams)
495 pWantedType.m_setTeams(sa);
500 if(pWantedType == MAPINFO_TYPE_RACE)
505 cvar_set(
"g_race_qualifying_timelimit", sa);
510 if(
cvar(
"g_race_teams") < 2)
516 if(
cvar(
"g_race_teams") >= 2)
521 if(!pWantedType.
frags)
536 return t ? t.model2 :
"";
541 return t ? t.
team :
false;
547 if (!(pThisType.gametype_flags & pWantedType.gametype_flags))
562 if (sa ==
"")
continue;
589 fraglimit_normal = v;
592 case "teampointlimit":
604 FOREACH(Gametypes,
true, handled |= it.m_parse_mapinfo(k, v));
609 if (pWantedType == MAPINFO_TYPE_RACE &&
cvar(
"g_race_teams") >= 2)
612 cvar_set(
"fraglimit", fraglimit_teams);
617 cvar_set(
"fraglimit", fraglimit_normal);
623 string replacement =
"";
627 case "nexball": replacement =
"nb";
break;
628 case "freezetag": replacement =
"ft";
break;
629 case "keepaway": replacement =
"ka";
break;
630 case "invasion": replacement =
"inv";
break;
631 case "assault": replacement =
"as";
break;
632 case "race": replacement =
"rc";
break;
634 case "ffa": replacement =
"dm";
break;
636 case "oneflag": replacement =
"ctf";
break;
637 case "tourney": replacement =
"duel";
break;
639 if(is_q3compat) { replacement =
"ca"; }
break;
641 if (replacement !=
"")
644 LOG_WARNF(
"MapInfo_Type_FromString (probably %s): using deprecated name '%s'. Should use '%s'.",
MapInfo_Map_bspname, gtype, replacement);
647 FOREACH(Gametypes, it.mdl == gtype,
return it);
653 return t ? t.m_description :
"";
658 return t ? t.mdl :
"";
664 return t ? t.message : _(
"@!#%'n Tuba Throwing");
672 s = strreplace(
"\t",
"", s);
711 LOG_WARN(
"Map ", pFilename,
" references not existing config file ", s);
715 while((s =
fgets(fh)))
717 s = strreplace(
"\t",
"", s);
739 LOG_WARN(
"Map ", pFilename,
" uses too many levels of inclusion");
747 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful setting, ignored");
752 LOG_WARN(
"Map ", pFilename,
" contains a denied setting, ignored");
758 LOG_TRACE(
"Applying temporary setting ", t,
" := ", s);
760 if(
cvar(
"g_campaign"))
768 LOG_TRACE(
"Applying temporary client setting ", t,
" := ", s);
782 if ((offset =
strstrofs(title,
" by ", 0)) >= 0)
788 else if ((offset =
strstrofs(title,
" (by ", 0)) >= 0 || (offset =
strstrofs(title,
" [by ", 0)) >= 0)
794 else if ((offset =
strstrofs(title,
"Made By ", 0)) >= 0)
801 return title !=
"" ? title :
"<TITLE>";
807 fn = strreplace(
"_",
"", fn);
808 fn = strreplace(
"-",
"", fn);
811 t = strreplace(
":",
"", t);
812 t = strreplace(
" ",
"", t);
813 t = strreplace(
"_",
"", t);
814 t = strreplace(
"-",
"", t);
815 t = strreplace(
"'",
"", t);
816 t = strdecolorize(t);
830 bool in_brackets =
false;
832 string stored_Map_description =
"";
833 string stored_Map_title =
"";
834 string stored_Map_author =
"";
835 vector stored_supportedGametypes =
'0 0 0';
836 int stored_supportedFeatures = 0;
837 int stored_flags = 0;
841 LOG_INFO(
"Generating ", pFilename,
".mapinfo: analyzing ", arena_filename);
845 if (!((s =
fgets(fh))))
860 else if(!in_brackets)
873 if(stored_Map_title !=
"")
875 if(stored_Map_author !=
"")
882 FOREACH(Gametypes, it.gametype_flags & stored_supportedGametypes,
884 _MapInfo_Map_ApplyGametype (
"", pGametypeToSet, it, true);
894 stored_Map_description =
"";
895 stored_Map_title =
"";
896 stored_Map_author =
"";
897 stored_supportedGametypes =
'0 0 0';
898 stored_supportedFeatures = 0;
904 s = strreplace(
"\t",
" ", s);
936 stored_Map_title = s;
937 else if(t ==
"author")
938 stored_Map_author = s;
946 types = strreplace(
"team",
"tdm ft", types);
947 types = strreplace(
"ffa",
"dm lms ka", types);
948 types = strreplace(
"tourney",
"duel", types);
950 types =
cons(types,
"ca kh");
955 stored_supportedGametypes |= f.gametype_flags;
958 else if(t ==
"style" && isdefi)
962 stored_supportedGametypes |= MAPINFO_TYPE_CTS.gametype_flags;
969 else if(t ==
"quote")
970 stored_Map_description = s;
985 for(
string s; (s =
fgets(fh)); )
987 s = strreplace(
"\t",
"", s);
1019 string base_pack = whichpack(
strcat(
"maps/", pFilename,
".bsp"));
1022 int glob = search_packfile_begin(
strcat(
"scripts/*", extension),
true,
true, base_pack);
1026 for(
int j = 0; j < n; ++j)
1054 LOG_WARN(
"Invalid character in map name, ignored");
1058 if(pGametypeToSet ==
NULL)
1067 fn =
strcat(
"maps/", pFilename,
".mapinfo");
1074 bool success =
false;
1091 goto mapinfo_handled;
1094 fn =
strcat(
"maps/autogenerated/", pFilename,
".mapinfo");
1129 fputs(fh,
"has weapons\n");
1131 fputs(fh,
"// uncomment this if you added weapon pickups: has weapons\n");
1133 fputs(fh,
"has turrets\n");
1135 fputs(fh,
"// uncomment this if you added turrets: has turrets\n");
1137 fputs(fh,
"has vehicles\n");
1139 fputs(fh,
"// uncomment this if you added vehicles: has vehicles\n");
1141 fputs(fh,
"frustrating\n");
1144 fputs(fh, sprintf(
"gametype %s // defaults: %s\n", MapInfo_Type_ToString(it), _MapInfo_GetDefaultEx(it)));
1147 fputs(fh,
"// optional: fog density red green blue alpha mindist maxdist\n");
1148 fputs(fh,
"// optional: settemp_for_type (all|gametypename) cvarname value\n");
1149 fputs(fh,
"// optional: clientsettemp_for_type (all|gametypename) cvarname value\n");
1150 fputs(fh,
"// optional: size mins_x mins_y mins_z maxs_x maxs_y maxs_z\n");
1151 fputs(fh,
"// optional: hidden\n");
1158 error(
"... but I just wrote it!");
1162 LOG_WARN(
"autogenerated mapinfo file ", fn,
" has been loaded; please edit that file and move it to maps/", pFilename,
".mapinfo");
1168 if (!((s =
fgets(fh))))
1188 else if(t ==
"description")
1190 else if(t ==
"author")
1201 LOG_WARN(
"Map ", pFilename,
" supports unknown feature ", t,
", ignored");
1203 else if(t ==
"hidden")
1207 else if(t ==
"forbidden")
1211 else if(t ==
"frustrating")
1215 else if(t ==
"donotwant" || t ==
"noautomaplist")
1219 else if(t ==
"gameversion_min")
1224 else if(t ==
"type")
1233 LOG_DEBUG(
"Map ", pFilename,
" supports unknown gametype ", t,
", ignored");
1235 else if(t ==
"gametype")
1242 LOG_DEBUG(
"Map ", pFilename,
" supports unknown gametype ", t,
", ignored");
1244 else if(t ==
"size")
1246 float a, b, c, d, e;
1255 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");
1263 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");
1267 if(a >= d || b >= e || c >= f)
1270 LOG_WARN(
"Map ", pFilename,
" contains an incorrect size line, mins have to be < maxs");
1284 else if(t ==
"settemp_for_type")
1287 bool all = t ==
"all";
1291 if((all ?
MAPINFO_TYPE_ALL : f.gametype_flags) & pGametypeToSet.gametype_flags)
1298 LOG_DEBUG(
"Map ", pFilename,
" has a setting for unknown gametype ", t,
", ignored");
1301 else if(t ==
"clientsettemp_for_type")
1304 bool all = t ==
"all";
1308 if((all ?
MAPINFO_TYPE_ALL : f.gametype_flags) & pGametypeToSet.gametype_flags)
1315 LOG_DEBUG(
"Map ", pFilename,
" has a client setting for unknown gametype ", t,
", ignored");
1323 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful fog setting, ignored");
1328 else if(t ==
"cdtrack")
1342 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful cdtrack, ignored");
1351 LOG_WARN(
"Map ", pFilename,
" provides unknown info item ", t,
", ignored");
1355LABEL(mapinfo_handled)
1361 if (
world.message !=
"")
1387 LOG_WARN(
"Map ", pFilename,
" supports no gametypes, ignored");
1400 error(
"Can't select the requested gametype. This should never happen as the caller should prevent it!\n");
1412 string readsize_msg =
strcat(
"MapReadSizes ", map);
1437 m =
floor((l + r) / 2);
1484 if(!(
cvar(
"g_instagib") ||
cvar(
"g_overkill") ||
cvar(
"g_nix") ||
cvar(
"g_weaponarena") || !
cvar(
"g_pickup_items") || !
cvar(
"g_melee_only")
1494 return prev ?
prev : MAPINFO_TYPE_DEATHMATCH;
1520 FOREACH(Gametypes,
true,
cvar_set(it.netname, (it == t) ?
"1" :
"0"));
1587 if(
cvar(
"g_mapinfo_allow_unsupported_modes_and_let_stuff_break"))
1589 LOG_SEVERE(
"can't play the selected map in the given gametype. Working with only the override settings.");
1597 FOREACH(Gametypes, it.m_priority == 2,
1599 MapInfo_Map_supportedGametypes |= it.gametype_flags;
1600 RandomSelection_AddEnt(it, 1, 1);
1604 LOG_SEVEREF(
"Mapinfo system is not functional at all. Falling back to a preferred mode (%s).", t.mdl);
1624 RandomSelection_AddEnt(it, 1, it.m_priority);
1630 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);
1634 LOG_WARNF(
"the selected map lacks features required by current settings; playing anyway.");
1669 if (!
cvar(
"g_maplist_allow_hidden"))
1673 if (!
cvar(
"g_maplist_allow_frustrating"))
1683 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)