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);
763 LOG_TRACE(
"Applying temporary client setting ", t,
" := ", s);
777 if ((offset =
strstrofs(title,
" by ", 0)) >= 0)
783 else if ((offset =
strstrofs(title,
" (by ", 0)) >= 0 || (offset =
strstrofs(title,
" [by ", 0)) >= 0)
789 else if ((offset =
strstrofs(title,
"Made By ", 0)) >= 0)
796 return title !=
"" ? title :
"<TITLE>";
802 fn = strreplace(
"_",
"", fn);
803 fn = strreplace(
"-",
"", fn);
806 t = strreplace(
":",
"", t);
807 t = strreplace(
" ",
"", t);
808 t = strreplace(
"_",
"", t);
809 t = strreplace(
"-",
"", t);
810 t = strreplace(
"'",
"", t);
811 t = strdecolorize(t);
825 bool in_brackets =
false;
827 string stored_Map_description =
"";
828 string stored_Map_title =
"";
829 string stored_Map_author =
"";
830 vector stored_supportedGametypes =
'0 0 0';
831 int stored_supportedFeatures = 0;
832 int stored_flags = 0;
836 LOG_INFO(
"Generating ", pFilename,
".mapinfo: analyzing ", arena_filename);
840 if (!((s =
fgets(fh))))
855 else if(!in_brackets)
868 if(stored_Map_title !=
"")
870 if(stored_Map_author !=
"")
877 FOREACH(Gametypes, it.gametype_flags & stored_supportedGametypes,
879 _MapInfo_Map_ApplyGametype (
"", pGametypeToSet, it, true);
889 stored_Map_description =
"";
890 stored_Map_title =
"";
891 stored_Map_author =
"";
892 stored_supportedGametypes =
'0 0 0';
893 stored_supportedFeatures = 0;
899 s = strreplace(
"\t",
" ", s);
931 stored_Map_title = s;
932 else if(t ==
"author")
933 stored_Map_author = s;
941 types = strreplace(
"team",
"tdm ft", types);
942 types = strreplace(
"ffa",
"dm lms ka", types);
943 types = strreplace(
"tourney",
"duel", types);
945 types =
cons(types,
"ca kh");
950 stored_supportedGametypes |= f.gametype_flags;
953 else if(t ==
"style" && isdefi)
957 stored_supportedGametypes |= MAPINFO_TYPE_CTS.gametype_flags;
964 else if(t ==
"quote")
965 stored_Map_description = s;
980 for(
string s; (s =
fgets(fh)); )
982 s = strreplace(
"\t",
"", s);
1014 string base_pack = whichpack(
strcat(
"maps/", pFilename,
".bsp"));
1017 int glob = search_packfile_begin(
strcat(
"scripts/*", extension),
true,
true, base_pack);
1021 for(
int j = 0; j < n; ++j)
1049 LOG_WARN(
"Invalid character in map name, ignored");
1053 if(pGametypeToSet ==
NULL)
1062 fn =
strcat(
"maps/", pFilename,
".mapinfo");
1069 bool success =
false;
1086 goto mapinfo_handled;
1089 fn =
strcat(
"maps/autogenerated/", pFilename,
".mapinfo");
1124 fputs(fh,
"has weapons\n");
1126 fputs(fh,
"// uncomment this if you added weapon pickups: has weapons\n");
1128 fputs(fh,
"has turrets\n");
1130 fputs(fh,
"// uncomment this if you added turrets: has turrets\n");
1132 fputs(fh,
"has vehicles\n");
1134 fputs(fh,
"// uncomment this if you added vehicles: has vehicles\n");
1136 fputs(fh,
"frustrating\n");
1139 fputs(fh, sprintf(
"gametype %s // defaults: %s\n", MapInfo_Type_ToString(it), _MapInfo_GetDefaultEx(it)));
1142 fputs(fh,
"// optional: fog density red green blue alpha mindist maxdist\n");
1143 fputs(fh,
"// optional: settemp_for_type (all|gametypename) cvarname value\n");
1144 fputs(fh,
"// optional: clientsettemp_for_type (all|gametypename) cvarname value\n");
1145 fputs(fh,
"// optional: size mins_x mins_y mins_z maxs_x maxs_y maxs_z\n");
1146 fputs(fh,
"// optional: hidden\n");
1153 error(
"... but I just wrote it!");
1157 LOG_WARN(
"autogenerated mapinfo file ", fn,
" has been loaded; please edit that file and move it to maps/", pFilename,
".mapinfo");
1163 if (!((s =
fgets(fh))))
1183 else if(t ==
"description")
1185 else if(t ==
"author")
1196 LOG_WARN(
"Map ", pFilename,
" supports unknown feature ", t,
", ignored");
1198 else if(t ==
"hidden")
1202 else if(t ==
"forbidden")
1206 else if(t ==
"frustrating")
1210 else if(t ==
"donotwant" || t ==
"noautomaplist")
1214 else if(t ==
"gameversion_min")
1219 else if(t ==
"type")
1228 LOG_DEBUG(
"Map ", pFilename,
" supports unknown gametype ", t,
", ignored");
1230 else if(t ==
"gametype")
1237 LOG_DEBUG(
"Map ", pFilename,
" supports unknown gametype ", t,
", ignored");
1239 else if(t ==
"size")
1241 float a, b, c, d, e;
1250 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");
1258 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");
1262 if(a >= d || b >= e || c >= f)
1265 LOG_WARN(
"Map ", pFilename,
" contains an incorrect size line, mins have to be < maxs");
1279 else if(t ==
"settemp_for_type")
1282 bool all = t ==
"all";
1286 if((all ?
MAPINFO_TYPE_ALL : f.gametype_flags) & pGametypeToSet.gametype_flags)
1293 LOG_DEBUG(
"Map ", pFilename,
" has a setting for unknown gametype ", t,
", ignored");
1296 else if(t ==
"clientsettemp_for_type")
1299 bool all = t ==
"all";
1303 if((all ?
MAPINFO_TYPE_ALL : f.gametype_flags) & pGametypeToSet.gametype_flags)
1310 LOG_DEBUG(
"Map ", pFilename,
" has a client setting for unknown gametype ", t,
", ignored");
1318 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful fog setting, ignored");
1323 else if(t ==
"cdtrack")
1337 LOG_WARN(
"Map ", pFilename,
" contains a potentially harmful cdtrack, ignored");
1346 LOG_WARN(
"Map ", pFilename,
" provides unknown info item ", t,
", ignored");
1350LABEL(mapinfo_handled)
1356 if (
world.message !=
"")
1382 LOG_WARN(
"Map ", pFilename,
" supports no gametypes, ignored");
1395 error(
"Can't select the requested gametype. This should never happen as the caller should prevent it!\n");
1407 string readsize_msg =
strcat(
"MapReadSizes ", map);
1432 m =
floor((l + r) / 2);
1479 if(!(
cvar(
"g_instagib") ||
cvar(
"g_overkill") ||
cvar(
"g_nix") ||
cvar(
"g_weaponarena") || !
cvar(
"g_pickup_items") || !
cvar(
"g_melee_only")
1489 return prev ?
prev : MAPINFO_TYPE_DEATHMATCH;
1515 FOREACH(Gametypes,
true,
cvar_set(it.netname, (it == t) ?
"1" :
"0"));
1582 if(
cvar(
"g_mapinfo_allow_unsupported_modes_and_let_stuff_break"))
1584 LOG_SEVERE(
"can't play the selected map in the given gametype. Working with only the override settings.");
1592 FOREACH(Gametypes, it.m_priority == 2,
1594 MapInfo_Map_supportedGametypes |= it.gametype_flags;
1595 RandomSelection_AddEnt(it, 1, 1);
1599 LOG_SEVEREF(
"Mapinfo system is not functional at all. Falling back to a preferred mode (%s).", t.mdl);
1619 RandomSelection_AddEnt(it, 1, it.m_priority);
1625 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);
1629 LOG_WARNF(
"the selected map lacks features required by current settings; playing anyway.");
1664 if (!
cvar(
"g_maplist_allow_hidden"))
1668 if (!
cvar(
"g_maplist_allow_frustrating"))
1678 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)