]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/q3compat_sanity
authorMario <mario.mario@y7mail.com>
Mon, 10 Jan 2022 00:53:37 +0000 (10:53 +1000)
committerMario <mario.mario@y7mail.com>
Mon, 10 Jan 2022 00:53:37 +0000 (10:53 +1000)
15 files changed:
qcsrc/client/mapvoting.qc
qcsrc/common/mapinfo.qc
qcsrc/common/mapinfo.qh
qcsrc/common/mapobjects/target/changelevel.qc
qcsrc/menu/draw.qc
qcsrc/menu/draw.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc
qcsrc/menu/xonotic/maplist.qc
qcsrc/server/campaign.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/mapvoting.qc
qcsrc/server/world.qc
qcsrc/server/world.qh
xonotic-common.cfg

index 2a6f39f8a5ff50dcbe63c7fdc628328bcc1eb449..16aef864997bae2951b22df57865d83d012ecdde 100644 (file)
@@ -637,7 +637,7 @@ void GameTypeVote_ReadOption(int i)
        }
        else
        {
-               Gametype type = MapInfo_Type_FromString(gt, false);
+               Gametype type = MapInfo_Type_FromString(gt, false, false);
                mv_pk3[i] = strzone(MapInfo_Type_ToText(type));
                mv_desc[i] = MapInfo_Type_Description(type);
        }
index c0b67ff4d535e97e9752132fafd7134c28c9ae6d..e893e3b668cdf60603509fa205e60c16d82940b8 100644 (file)
@@ -8,6 +8,9 @@
        #include <common/monsters/_mod.qh>
 #endif
 
+bool autocvar_g_mapinfo_arena_compat = true;
+bool autocvar_g_mapinfo_arena_generate = false;
+
 #ifdef MENUQC
 #define WARN_COND false
 #else
@@ -296,6 +299,25 @@ float _MapInfo_Generate(string pFilename) // 0: failure, 1: ok ent, 2: ok bsp
        mapMins = '0 0 0';
        mapMaxs = '0 0 0';
 
+       if(autocvar_g_mapinfo_arena_generate)
+       {
+               // try for .arena or .defi files, as they may have more accurate information
+               bool isdefi = false;
+               string arena_fn = _MapInfo_FindArenaFile(pFilename, ".arena");
+               int arena_fh = fopen(arena_fn, FILE_READ);
+               if(arena_fh < 0)
+               {
+                       isdefi = true;
+                       arena_fn = _MapInfo_FindArenaFile(pFilename, ".defi");
+                       arena_fh = fopen(arena_fn, FILE_READ);
+               }
+               if(arena_fh >= 0)
+               {
+                       _MapInfo_ParseArena(arena_fn, arena_fh, pFilename, NULL, isdefi, true);
+                       fclose(arena_fh);
+               }
+       }
+
        for (;;)
        {
                if (!((s = fgets(fh))))
@@ -586,9 +608,10 @@ void _MapInfo_Map_ApplyGametypeEx(string s, Gametype pWantedType, Gametype pThis
        }
 }
 
-Gametype MapInfo_Type_FromString(string gtype, bool dowarn)
+Gametype MapInfo_Type_FromString(string gtype, bool dowarn, bool is_q3compat)
 {
        string replacement = "";
+       bool do_warn = true;
        switch (gtype)
        {
                case "nexball":   replacement = "nb"; break;
@@ -597,6 +620,12 @@ Gametype MapInfo_Type_FromString(string gtype, bool dowarn)
                case "invasion":  replacement = "inv"; break;
                case "assault":   replacement = "as"; break;
                case "race":      replacement = "rc"; break;
+               // quake 3 compat
+               case "ffa":       replacement = "dm"; do_warn = false; break;
+               case "cctf":
+               case "oneflag":   replacement = "ctf"; do_warn = false; break;
+               case "tourney":   replacement = "duel"; do_warn = false; break;
+               case "arena":     if(is_q3compat) { replacement = "ca"; do_warn = false; } break;
        }
        if (replacement != "")
        {
@@ -755,6 +784,193 @@ float MapInfo_isRedundant(string fn, string t)
        return false;
 }
 
+bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gametype pGametypeToSet, bool isdefi, bool isgenerator)
+{
+       // NOTE: .arena files can hold more than 1 map's information!
+       // to handle this, we're going to store gathered information in local variables and save it if we encounter the correct map name
+       bool in_brackets = false; // testing a potential mapinfo section (within brackets)
+       bool dosave = (arena_filename == strcat("scripts/", pFilename, ((isdefi) ? ".defi" : ".arena"))); // if the map is using the fallback, just accept the first found mapinfo (it's probably correct!)
+       string stored_Map_description = "";
+       string stored_Map_title = "";
+       string stored_Map_author = "";
+       int stored_supportedGametypes = 0;
+       int stored_supportedFeatures = 0;
+       int stored_flags = 0;
+       string t, s;
+       for (;;)
+       {
+               if (!((s = fgets(fh))))
+                       break;
+
+               // catch different sorts of comments
+               if(s == "")                    // empty lines
+                       continue;
+               if(substring(s, 0, 1) == "#")  // UNIX style
+                       continue;
+               if(substring(s, 0, 2) == "//") // C++ style
+                       continue;
+               if(substring(s, 0, 1) == "_")  // q3map style
+                       continue;
+               if(strstrofs(s, "{", 0) >= 0)
+               {
+                       if(in_brackets)
+                               return false; // edge case? already in a bracketed section!
+                       in_brackets = true;
+                       continue;
+               }
+               else if(!in_brackets)
+               {
+                       // if we're not inside a bracket, don't process map info
+                       continue;
+               }
+               if(strstrofs(s, "}", 0) >= 0)
+               {
+                       if(!in_brackets)
+                               return false; // no starting bracket! let the mapinfo generation system handle it
+                       in_brackets = false;
+                       if(dosave)
+                       {
+                               MapInfo_Map_description = stored_Map_description;
+                               if(stored_Map_title != "")
+                                       MapInfo_Map_title = stored_Map_title;
+                               MapInfo_Map_author = stored_Map_author;
+                               if(isgenerator)
+                                       MapInfo_Map_supportedGametypes = stored_supportedGametypes;
+                               else
+                               {
+                                       FOREACH(Gametypes, it.m_flags & stored_supportedGametypes,
+                                       {
+                                               _MapInfo_Map_ApplyGametype ("", pGametypeToSet, it, true);
+                                       });
+                               }
+                               MapInfo_Map_supportedFeatures = stored_supportedFeatures;
+                               MapInfo_Map_flags = stored_flags;
+                               return true; // no need to continue through the file, we have our map!
+                       }
+                       else
+                       {
+                               // discard any gathered locals, we're not using the correct map!
+                               stored_Map_description = "";
+                               stored_Map_title = "";
+                               stored_Map_author = "";
+                               stored_supportedGametypes = 0;
+                               stored_supportedFeatures = 0;
+                               stored_flags = 0;
+                               continue;
+                       }
+               }
+
+               s = strreplace("\t", " ", s);
+
+               float p = strstrofs(s, "//", 0);
+               if(p >= 0)
+                       s = substring(s, 0, p);
+
+               // perform an initial trim to ensure the first argument is properly obtained
+               //   remove leading spaces
+               while(substring(s, 0, 1) == " ")
+                       s = substring(s, 1, -1);
+
+               t = car(s); s = cdr(s);
+               t = strtolower(t); // apparently some q3 maps use capitalized parameters
+
+               //   remove trailing spaces
+               while(substring(t, -1, 1) == " ")
+                       t = substring(t, 0, -2);
+
+               //   remove trailing spaces
+               while(substring(s, -1, 1) == " ")
+                       s = substring(s, 0, -2);
+               //   remove leading spaces
+               while(substring(s, 0, 1) == " ")
+                       s = substring(s, 1, -1);
+               // limited support of ""
+               //   remove trailing and leading " of s
+               if(substring(s, 0, 1) == "\"")
+               {
+                       if(substring(s, -1, 1) == "\"")
+                               s = substring(s, 1, -2);
+               }
+               if(t == "longname")
+                       stored_Map_title = s;
+               else if(t == "author")
+                       stored_Map_author = s;
+               else if(t == "type")
+               {
+                       // if there is a valid gametype in this .arena file, include it in the menu
+                       stored_supportedFeatures |= MAPINFO_FEATURE_WEAPONS;
+                       // type in quake 3 holds all the supported gametypes, so we must loop through all of them
+                       string types = strreplace("team", "tdm ft", s); // TODO: handle support here better to include more Xonotic teamplay modes
+                       FOREACH_WORD(types, true,
+                       {
+                               Gametype f = MapInfo_Type_FromString(it, false, true);
+                               if(f)
+                                       stored_supportedGametypes |= f.m_flags;
+                       });
+               }
+               else if(t == "style" && isdefi)
+               {
+                       // we have a defrag map on our hands, add CTS!
+                       // TODO: styles
+                       stored_supportedGametypes |= MAPINFO_TYPE_CTS.m_flags;
+               }
+               else if(t == "map")
+               {
+                       if(strtolower(s) == strtolower(pFilename))
+                               dosave = true; // yay, found our map!
+               }
+               else if(t == "quote")
+                       stored_Map_description = s;
+               // TODO: fraglimit
+       }
+
+       // if the map wasn't found in the .arena, fall back to generated .mapinfo
+       return false;
+}
+
+#if defined(CSQC) || defined(MENUQC)
+string(string filename) whichpack = #503;
+#endif
+string _MapInfo_FindArenaFile(string pFilename, string extension)
+{
+       string fallback = strcat("scripts/", pFilename, extension);
+       if(!checkextension("DP_QC_FS_SEARCH_PACKFILE"))
+               return fallback;
+       string base_pack = whichpack(strcat("maps/", pFilename, ".bsp"));
+       if(base_pack == "") // this map isn't packaged!
+               return fallback;
+
+       int glob = search_packfile_begin(strcat("scripts/*", extension), true, true, base_pack);
+       if(glob < 0)
+               return fallback;
+       int n = search_getsize(glob);
+       for(int j = 0; j < n; ++j)
+       {
+               string file = search_getfilename(glob, j);
+
+               int fh = fopen(file, FILE_READ);
+               if(fh < 0)
+                       continue; // how?
+               for(string s; (s = fgets(fh)); )
+               {
+                       int offset = strstrofs(s, "map", 0);
+                       if(offset >= 0)
+                       {
+                               if(strstrofs(strtolower(s), strcat("\"", strtolower(pFilename), "\""), offset) >= 0) // quake 3 is case insensitive
+                               {
+                                       fclose(fh);
+                                       search_end(glob);
+                                       return file; // FOUND IT!
+                               }
+                       }
+               }
+               fclose(fh);
+       }
+
+       search_end(glob);
+       return fallback; // if we get here, a valid .arena file could not be found
+}
+
 // load info about a map by name into the MapInfo_Map_* globals
 float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gametype pGametypeToSet)
 {
@@ -762,7 +978,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
        string s, t;
        float fh;
        int f, i;
-       float r, n, p;
+       float r, n;
        string acl;
 
        acl = MAPINFO_SETTEMP_ACL_USER;
@@ -786,6 +1002,26 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
        fh = fopen(fn, FILE_READ);
        if(fh < 0)
        {
+               if(autocvar_g_mapinfo_arena_compat)
+               {
+                       // try for .arena or .defi files if no .mapinfo exists
+                       bool isdefi = false;
+                       fn = _MapInfo_FindArenaFile(pFilename, ".arena");
+                       fh = fopen(fn, FILE_READ);
+                       if(fh < 0)
+                       {
+                               isdefi = true;
+                               fn = _MapInfo_FindArenaFile(pFilename, ".defi");
+                               fh = fopen(fn, FILE_READ);
+                       }
+                       if(fh >= 0)
+                       {
+                               _MapInfo_Map_Reset();
+                               if(_MapInfo_ParseArena(fn, fh, pFilename, pGametypeToSet, isdefi, false))
+                                       goto mapinfo_handled; // skip generation
+                       }
+               }
+
                fn = strcat("maps/autogenerated/", pFilename, ".mapinfo");
                fh = fopen(fn, FILE_READ);
                if(fh < 0)
@@ -876,7 +1112,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                if(substring(s, 0, 1) == "_")  // q3map style
                        continue;
 
-               p = strstrofs(s, "//", 0);
+               float p = strstrofs(s, "//", 0);
                if(p >= 0)
                        s = substring(s, 0, p);
 
@@ -922,7 +1158,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                else if(t == "type")
                {
                        t = car(s); s = cdr(s);
-                       Gametype f = MapInfo_Type_FromString(t, true);
+                       Gametype f = MapInfo_Type_FromString(t, true, false);
                        //if(WARN_COND)
                                //LOG_WARN("Map ", pFilename, " contains the legacy 'type' keyword which is deprecated and will be removed in the future. Please migrate the mapinfo file to 'gametype'.");
                        if(f)
@@ -933,7 +1169,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                else if(t == "gametype")
                {
                        t = car(s); s = cdr(s);
-                       Gametype f = MapInfo_Type_FromString(t, true);
+                       Gametype f = MapInfo_Type_FromString(t, true, false);
                        if(f)
                                _MapInfo_Map_ApplyGametypeEx (s, pGametypeToSet, f);
                        else if(WARN_COND)
@@ -984,7 +1220,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                        t = car(s); s = cdr(s);
                        bool all = t == "all";
                        Gametype f = NULL;
-                       if(all || (f = MapInfo_Type_FromString(t, true)))
+                       if(all || (f = MapInfo_Type_FromString(t, true, false)))
                        {
                                if((all ? MAPINFO_TYPE_ALL : f.m_flags) & pGametypeToSet.m_flags)
                                {
@@ -1001,7 +1237,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                        t = car(s); s = cdr(s);
                        bool all = t == "all";
                        Gametype f = NULL;
-                       if(all || (f = MapInfo_Type_FromString(t, true)))
+                       if(all || (f = MapInfo_Type_FromString(t, true, false)))
                        {
                                if((all ? MAPINFO_TYPE_ALL : f.m_flags) & pGametypeToSet.m_flags)
                                {
@@ -1048,6 +1284,7 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                else if(WARN_COND)
                        LOG_WARN("Map ", pFilename, " provides unknown info item ", t, ", ignored");
        }
+       LABEL(mapinfo_handled)
        fclose(fh);
 
        if(MapInfo_Map_title == "<TITLE>")
@@ -1149,7 +1386,7 @@ int MapInfo_CurrentFeatures()
 
 Gametype MapInfo_CurrentGametype()
 {
-       Gametype prev = MapInfo_Type_FromString(cvar_string("gamecfg"), false);
+       Gametype prev = MapInfo_Type_FromString(cvar_string("gamecfg"), false, false);
        FOREACH(Gametypes, cvar(it.netname) && it != prev, return it);
        return prev ? prev : MAPINFO_TYPE_DEATHMATCH;
 }
index 0ac0c6230548692303cf5c685cdd10dddbb6f882..30a3b63b09031e4b72575cd043f451c6a1f53e65 100644 (file)
@@ -182,7 +182,7 @@ string MapInfo_ListAllAllowedMaps(float pFlagsRequired, float pFlagsForbidden);
 // gets a gametype from a string
 string _MapInfo_GetDefaultEx(Gametype t);
 float _MapInfo_GetTeamPlayBool(Gametype t);
-Gametype MapInfo_Type_FromString(string t, bool dowarn);
+Gametype MapInfo_Type_FromString(string t, bool dowarn, bool is_q3compat);
 string MapInfo_Type_Description(Gametype t);
 string MapInfo_Type_ToString(Gametype t);
 string MapInfo_Type_ToText(Gametype t);
@@ -196,6 +196,10 @@ void MapInfo_Cache_Destroy(); // disable caching
 void MapInfo_Cache_Create(); // enable caching
 void MapInfo_Cache_Invalidate(); // delete cache if any, but keep enabled
 
+bool _MapInfo_ParseArena(string arena_filename, int fh, string pFilename, Gametype pGametypeToSet, bool isdefi, bool isgenerator);
+
+string _MapInfo_FindArenaFile(string pFilename, string extension);
+
 void _MapInfo_Parse_Settemp(string pFilename, string acl, float type, string s, float recurse);
 
 void MapInfo_ClearTemps(); // call this when done with mapinfo for this frame
index 876fed7a7306cab48686a8adef6c1e18caf94e0c..2cc3c58ba4f32479b8213528b3fd4aea6adfb655 100644 (file)
@@ -28,7 +28,7 @@ void target_changelevel_use(entity this, entity actor, entity trigger)
        }
 
        if(this.gametype != "")
-               MapInfo_SwitchGameType(MapInfo_Type_FromString(this.gametype, false));
+               MapInfo_SwitchGameType(MapInfo_Type_FromString(this.gametype, false, false));
 
        if (this.chmap == "")
        {
index 0b29572bee644865b70ebc3ddc6815bdc3806fa0..2bfb955c575017ca614e100e40ff82d79b0eb201 100644 (file)
@@ -83,6 +83,17 @@ vector draw_PictureSize(string pic)
        return drawgetimagesize(pic);
 }
 
+bool draw_PictureExists(string pic)
+{
+       pic = draw_UseSkinFor(pic);
+       if (fexists(strcat(pic, ".tga"))) return true;
+       if (fexists(strcat(pic, ".png"))) return true;
+       if (fexists(strcat(pic, ".jpg"))) return true;
+       if (fexists(strcat(pic, ".pcx"))) return true;
+
+       return false;
+}
+
 void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha)
 {
        drawfill(boxToGlobal(theOrigin, draw_shift, draw_scale), boxToGlobalSize(theSize, draw_scale), theColor, theAlpha * draw_alpha, 0);
index 69178cb03eedb522c29a0597b22c9f09303133cb..611281913d8d8ed209123a8ae4ec4813f8d5cf81 100644 (file)
@@ -21,6 +21,7 @@ void draw_VertButtonPicture(vector theOrigin, string pic, vector theSize, vector
 void draw_BorderPicture(vector theOrigin, string pic, vector theSize, vector theColor, float theAlpha, vector theBorderSize);
 void draw_Picture(vector origin, string pic, vector size, vector color, float alpha);
 vector draw_PictureSize(string pic);
+bool draw_PictureExists(string pic);
 void draw_Fill(vector theOrigin, vector theSize, vector theColor, float theAlpha);
 void draw_Text(vector origin, string text, vector size, vector color, float alpha, float allowColorCodes);
 void draw_CenterText(vector origin, string text, vector size, vector color, float alpha, float allowColorCodes);
@@ -40,3 +41,4 @@ vector globalToBoxSize(vector v, vector scale);
 
 float draw_TextWidth_WithColors(string s, vector size);
 float draw_TextWidth_WithoutColors(string s, vector size);
+
index 87ffadf3831d8015641eb7b3b9e50e7d8e95ecc7..57c2c61e6908ed5a8d4175cf23634bc459eee629 100644 (file)
@@ -17,12 +17,14 @@ void XonoticMapInfoDialog_loadMapInfo(entity me, int i, entity mlb)
        strcpy(me.currentMapAuthor, strdecolorize(MapInfo_Map_author));
        strcpy(me.currentMapDescription, MapInfo_Map_description);
        strcpy(me.currentMapPreviewImage, strcat("/maps/", MapInfo_Map_bspname));
+       if(!draw_PictureExists(me.currentMapPreviewImage)) // Quake 3 compatibility
+               strcpy(me.currentMapPreviewImage, strcat("/levelshots/", MapInfo_Map_bspname));
 
        me.frame.setText(me.frame, me.currentMapBSPName);
        me.titleLabel.setText(me.titleLabel, me.currentMapTitle);
        me.authorLabel.setText(me.authorLabel, me.currentMapAuthor);
        me.descriptionLabel.setText(me.descriptionLabel, me.currentMapDescription);
-       if(draw_PictureSize(me.currentMapPreviewImage) == '0 0 0')
+       if(!draw_PictureExists(me.currentMapPreviewImage))
                me.previewImage.src = "nopreview_map";
        else
                me.previewImage.src = me.currentMapPreviewImage;
index cf542f39c8f47d0d6120c6ef1e56336a07676e90..a4577d31f2704f614d0cd8732a72088b69afb3fe 100644 (file)
@@ -84,7 +84,7 @@ void XonoticServerInfoDialog_loadServerInfo(entity me, float i)
        if(s != "data")
                modname = sprintf("%s (%s)", modname, s);
 
-       Gametype j = MapInfo_Type_FromString(typestr, false); // try and get the real name of the game type
+       Gametype j = MapInfo_Type_FromString(typestr, false, false); // try and get the real name of the game type
        if(j) { typestr = MapInfo_Type_ToText(j); } // only set it if we actually found it
 
        me.currentServerType = strzone(typestr);
index a18037db63178830a7e85d675a66564cf01a7a47..924924f01dcc72ccccfda2ca3bf2192f88d05018 100644 (file)
@@ -156,7 +156,12 @@ void XonoticMapList_drawListBoxItem(entity me, int i, vector absSize, bool isSel
        }
 
        if(draw_PictureSize(strcat("/maps/", MapInfo_Map_bspname)) == '0 0 0')
-               draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+       {
+               if(!draw_PictureExists(strcat("/levelshots/", MapInfo_Map_bspname)))
+                       draw_Picture(me.columnPreviewOrigin * eX, "nopreview_map", me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+               else
+                       draw_Picture(me.columnPreviewOrigin * eX, strcat("/levelshots/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
+       }
        else
                draw_Picture(me.columnPreviewOrigin * eX, strcat("/maps/", MapInfo_Map_bspname), me.columnPreviewSize * eX + eY, '1 1 1', theAlpha);
 
index a368938c2ddd37595fa7db9cb9ad96517ab25a4d..21a8c92b173ab8f0a53c1958d026a8da1031b8ef 100644 (file)
@@ -33,7 +33,7 @@ float Campaign_Invalid()
        string thismapname, wantedmapname;
        thismapname = GetMapname();
        wantedmapname = campaign_gametype[0];
-       if(MapInfo_CurrentGametype() != MapInfo_Type_FromString(wantedmapname, false))
+       if(MapInfo_CurrentGametype() != MapInfo_Type_FromString(wantedmapname, false, false))
                return CampaignBailout("wrong game type!");
        wantedmapname = campaign_mapname[0];
        if(wantedmapname != thismapname)
@@ -67,7 +67,7 @@ void CampaignPreInit()
 
        if(autocvar_sv_cheats)
        {
-               MapInfo_SwitchGameType(MapInfo_Type_FromString(campaign_gametype[0], false));
+               MapInfo_SwitchGameType(MapInfo_Type_FromString(campaign_gametype[0], false, false));
                CampaignFile_Unload();
                CampaignBailout("JOLLY CHEATS AHAHAHAHAHAHAH))");
                return;
@@ -96,7 +96,7 @@ void CampaignPreInit()
        cvar_settemp("skill", ftos(baseskill));
        cvar_settemp("bot_number", ftos(campaign_bots[0]));
 
-       MapInfo_SwitchGameType(MapInfo_Type_FromString(campaign_gametype[0], false));
+       MapInfo_SwitchGameType(MapInfo_Type_FromString(campaign_gametype[0], false, false));
 
        if(Campaign_Invalid())
                return;
index ca6b268e23708a51b5fdb000e295fa4226512657..235ae9b9a1f2026d70dffd1240a03f86a0af27c6 100644 (file)
@@ -729,7 +729,7 @@ void GameCommand_gametype(int request, int argc)
                        if (argv(1) != "")
                        {
                                string s = argv(1);
-                               Gametype t = MapInfo_Type_FromString(s, false), tsave = MapInfo_CurrentGametype();
+                               Gametype t = MapInfo_Type_FromString(s, false, false), tsave = MapInfo_CurrentGametype();
 
                                if (t)
                                {
index 9242a5b6f4d057aa99e95f356cf80098eb2f6a12..c73f97da961643c4cbe3b791e93dea3b880e73f1 100644 (file)
@@ -48,10 +48,10 @@ entity mapvote_ent;
  */
 Gametype GameTypeVote_Type_FromString(string type_name)
 {
-       Gametype type = MapInfo_Type_FromString(type_name, false);
+       Gametype type = MapInfo_Type_FromString(type_name, false, false);
        if (type == NULL)
                type = MapInfo_Type_FromString(cvar_string(
-                       strcat("sv_vote_gametype_",type_name,"_type")), false);
+                       strcat("sv_vote_gametype_",type_name,"_type")), false, false);
        return type;
 }
 
@@ -59,11 +59,11 @@ int GameTypeVote_AvailabilityStatus(string type_name)
 {
        int flag = GTV_FORBIDDEN;
 
-       Gametype type = MapInfo_Type_FromString(type_name, false);
+       Gametype type = MapInfo_Type_FromString(type_name, false, false);
        if ( type == NULL )
        {
                type = MapInfo_Type_FromString(cvar_string(
-                       strcat("sv_vote_gametype_",type_name,"_type")), false);
+                       strcat("sv_vote_gametype_",type_name,"_type")), false, false);
                flag |= GTV_CUSTOM;
        }
 
index a438e633f61a71f7f47e89bd95bd6c93fe72f58b..2733ce216c82c183875742e4b92c4e11ece2314c 100644 (file)
@@ -887,8 +887,30 @@ spawnfunc(worldspawn)
        MapInfo_Enumerate();
        MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1);
 
-       q3compat = BITSET(q3compat, Q3COMPAT_ARENA, fexists(strcat("scripts/", mapname, ".arena")));
-       q3compat = BITSET(q3compat, Q3COMPAT_DEFI, fexists(strcat("scripts/", mapname, ".defi")));
+       q3compat = BITSET(q3compat, Q3COMPAT_ARENA, fexists(_MapInfo_FindArenaFile(mapname, ".arena")));
+       q3compat = BITSET(q3compat, Q3COMPAT_DEFI, fexists(_MapInfo_FindArenaFile(mapname, ".defi")));
+
+       // quake 3 music support
+       if(world.music || world.noise)
+       {
+               // prefer .music over .noise
+               string chosen_music;
+               string oldstuff;
+               if(world.music)
+                       chosen_music = world.music;
+               else
+                       chosen_music = world.noise;
+               if(
+                       substring(chosen_music, strlen(chosen_music) - 4, 4) == ".wav"
+                       ||
+                       substring(chosen_music, strlen(chosen_music) - 4, 4) == ".ogg"
+               )
+                       oldstuff = strcat(clientstuff, "cd loop \"", chosen_music, "\"\n");
+               else
+                       oldstuff = strcat(clientstuff, "cd loop \"", chosen_music, "\"\n");
+
+               strcpy(clientstuff, oldstuff);
+       }
 
        if(whichpack(strcat("maps/", mapname, ".cfg")) != "")
        {
index 3f6b9b6d22d676abd06947c077560d28e6924307..3bd1a79bd76e7cbc9aee2c5189481ca9f2cd1b1b 100644 (file)
@@ -145,6 +145,10 @@ float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, f
 void CheckRules_World();
 float RedirectionThink();
 
+// quake 3 music compatibility
+.string music;
+.string noise;
+
 void readplayerstartcvars();
 
 void readlevelcvars();
index 05670d56ca19a54a18a3ad38e46664a1b9ca1d45..40207ac8b51be8d32f8df40c3a49d3db6a133f2c 100644 (file)
@@ -162,6 +162,9 @@ set debug_deglobalization_clear 0 "make the new wrappers set globals to NaN afte
 // disabling until it's complete
 set prvm_garbagecollection_enable 0
 
+set g_mapinfo_arena_compat 1 "allow mapinfo data to be pulled directly from .arena and .defi files if they exist, rather than generating .mapinfo files for them"
+set g_mapinfo_arena_generate 0 "allow mapinfo data to be pulled from .arena and .defi files during generation"
+
 // load console command aliases and settings
 exec commands.cfg