]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/menu/menu.qc
Nades code: don't use booleans as array indexes for m_projectile, optimize spawn_held...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / menu / menu.qc
index 891235def666700cc2a0865d8809d9512a1b43ac..8bff8c4c67eec298b31f2ea589872a23575e6069 100644 (file)
 #include "xonotic/serverlist.qh"
 #include "xonotic/slider_resolution.qh"
 
-.string cvarName;
+.string controlledCvar;
 
 #include "xonotic/util.qh"
 
-#include "../common/items/_mod.qh"
+#include <common/checkextension.qh>
+#include <common/items/_mod.qh>
 #include <common/weapons/_all.qh>
-#include "../common/mapinfo.qh"
-#include "../common/mutators/base.qh"
+#include <common/mapinfo.qh>
+#include <common/mutators/base.qh>
 
 int mouseButtonsPressed;
 vector menuMousePos;
@@ -30,9 +31,13 @@ float menuAlpha;
 float menuLogoAlpha;
 float prevMenuAlpha;
 bool menuInitialized;
-bool menuNotTheFirstFrame;
 int menuMouseMode;
 
+// Used for having effects only execute once in main menu, not for every reload
+// 0: never been in main menu before. 1: coming back to main menu. 2: in main menu.
+int menuNotTheFirstFrame;
+bool autocvar_menu_no_music_nor_welcome;
+
 float conwidth_s, conheight_s;
 float vidwidth_s, vidheight_s, vidpixelheight_s;
 float realconwidth, realconheight;
@@ -69,9 +74,11 @@ void m_init()
        cvar_set("_menu_prvm_language", prvm_language);
 
 #ifdef WATERMARK
-               LOG_INFOF("^4MQC Build information: ^1%s", WATERMARK);
+               LOG_TRACEF("^4MQC Build information: ^1%s", WATERMARK);
 #endif
 
+       CheckEngineExtensions();
+
        // list all game dirs (TEST)
        if (cvar("developer") > 0)
        {
@@ -83,6 +90,9 @@ void m_init()
                }
        }
 
+       registercvar("_menu_cmd_closemenu_available", "0", 0);
+       cvar_set("_menu_cmd_closemenu_available", "1");
+
        // needs to be done so early because of the constants they create
        static_init();
        static_init_late();
@@ -119,7 +129,8 @@ void UpdateConWidthHeight(float w, float h, float p)
 {
        if (w != vidwidth_s || h != vidheight_s || p != vidpixelheight_s)
        {
-               if (updateConwidths(w, h, p)) localcmd(sprintf("\nexec %s\n", cvar_string("menu_font_cfg")));
+               if (updateConwidths(w, h, p) && menuNotTheFirstFrame)
+                       localcmd(sprintf("\nexec %s\n", cvar_string("menu_font_cfg")));
                vidwidth_s = w;
                vidheight_s = h;
                vidpixelheight_s = p;
@@ -221,6 +232,8 @@ void m_init_delayed()
        }
 
        if (Menu_Active) m_display();  // delayed menu display
+
+       cvar_set("_menu_initialized", "2");
 }
 
 void m_keyup(float key, float ascii)
@@ -481,7 +494,7 @@ entity m_findtooltipitem(entity root, vector pos)
                {
                        it = it.itemFromPoint(it, pos);
                        if (it.tooltip) best = it;
-                       else if (menu_tooltips == 2 && (it.cvarName || it.onClickCommand)) best = it;
+                       else if (menu_tooltips == 2 && (it.controlledCvar || it.onClickCommand)) best = it;
                        it = NULL;
                }
                else if (it.instanceOfModalController)
@@ -494,7 +507,7 @@ entity m_findtooltipitem(entity root, vector pos)
                }
                if (!it) break;
                if (it.tooltip) best = it;
-               else if (menu_tooltips == 2 && (it.cvarName || it.onClickCommand)) best = it;
+               else if (menu_tooltips == 2 && (it.controlledCvar || it.onClickCommand)) best = it;
                pos = globalToBox(pos, it.Container_origin, it.Container_size);
        }
 
@@ -505,11 +518,14 @@ string gettooltip()
        if (menu_tooltips == 2)
        {
                string s;
-               if (menuTooltipItem.cvarName)
+               if (menuTooltipItem.controlledCvar)
                {
-                       if (getCvarsMulti(menuTooltipItem)) s =
-                                   strcat("[", menuTooltipItem.cvarName, " ", getCvarsMulti(menuTooltipItem), "]");
-                       else s = strcat("[", menuTooltipItem.cvarName, "]");
+                       string cvar_list = getCvarsMulti(menuTooltipItem);
+                       if (cvar_list)
+                               cvar_list = strcat(menuTooltipItem.controlledCvar, " ", cvar_list);
+                       else
+                               cvar_list = menuTooltipItem.controlledCvar;
+                       s = strcat("[", cvar_list, " \"", cvar_string(menuTooltipItem.controlledCvar), "\"]");
                }
                else if (menuTooltipItem.onClickCommand)
                {
@@ -669,23 +685,41 @@ void m_tooltip(vector pos)
        }
 }
 
-float autocvar_menu_force_on_disconnection;
+const int MIN_DISCONNECTION_TIME = 1;
+bool autocvar_g_campaign;
 void m_draw(float width, float height)
 {
-       if (autocvar_menu_force_on_disconnection > 0)
+       static float connected_time;
+       if (clientstate() == CS_DISCONNECTED)
        {
-               static float connected_time;
-               if (clientstate() == CS_DISCONNECTED)
+               // avoid a bug where the main menu re-opens when changing maps
+               // potentially exclusive to `map <mapname>` cmd?
+               if (connected_time && time - connected_time > MIN_DISCONNECTION_TIME)
                {
-                       if (connected_time && time - connected_time > autocvar_menu_force_on_disconnection)
+                       if (autocvar_g_campaign)
                        {
-                               m_toggle(true);
-                               connected_time = 0;
+                               // in the case player uses the disconnect command (in the console or with a key)
+                               // reset g_campaign and update menu items to reflect cvar values that may have been restored after quiting the campaign
+                               // see also LEAVEMATCH_CMD
+                               cvar_set("g_campaign", "0");
+                               m_sync();
                        }
+
+                       // reload the menu so that disconnecting players don't
+                       // have to press ESC to open it again
+                       m_toggle(true);
+
+                       localcmd("\nmenu_cmd directmenu Welcome RESET\n");
+                       connected_time = 0;
+
+                       // reset main menu
+                       // FIXME?: find out if anything should be done to reset it more,
+                       // this is just a fix to make main menu music replay nicely
+                       menuNotTheFirstFrame = 1;
                }
-               else
-                       connected_time = time;
        }
+       else
+               connected_time = time;
 
        m_gamestatus();
 
@@ -703,16 +737,24 @@ void m_draw(float width, float height)
                m_init_delayed();
                return;
        }
-       if (!menuNotTheFirstFrame)
+
+       if (menuNotTheFirstFrame == 0) // only fade the menu in once ever
+               menuLogoAlpha = -0.8;  // no idea why, but when I start this at zero, it jumps instead of fading FIXME
+
+       if (menuNotTheFirstFrame <= 1) // only once per menu reload
        {
-               menuNotTheFirstFrame = true;
-               if (Menu_Active && !cvar("menu_video_played"))
-        {
-            localcmd("cd loop $menu_cdtrack; play sound/announcer/default/welcome.wav\n");
-            menuLogoAlpha = -0.8;  // no idea why, but when I start this at zero, it jumps instead of fading FIXME
-        }
-               // ALWAYS set this cvar; if we start but menu is not active, this means we want no background music!
-               localcmd("set menu_video_played 1\n");
+               if (Menu_Active && !autocvar_menu_no_music_nor_welcome)
+               {
+                       localcmd("cd loop $menu_cdtrack\n");
+
+                       // TODO: enable this when we have a welcome sound
+                       // FIXME: change the file used according to the selected announcer
+                       // Only play the welcome announcement once, not on any menu reloads
+                       //if (menuNotTheFirstFrame == 0)
+                       //localcmd("play sound/announcer/default/welcome.wav\n");
+               }
+
+               menuNotTheFirstFrame = 2;
        }
 
        float t = gettime();
@@ -878,6 +920,10 @@ void m_toggle(int mode)
        if (Menu_Active)
        {
                if (mode == 1) return;
+               // when togglemenu is called without arguments (mode is -1)
+               // the menu is closed only when connected
+               if (mode == -1 && !(gamestatus & GAME_CONNECTED)) return;
+               // togglemenu 0 always closes the menu
                m_hide();
        }
        else
@@ -894,6 +940,7 @@ void Shutdown()
                if (it.classname == "vtbl") continue;
                it.destroy(it);
        });
+       cvar_set("_menu_cmd_closemenu_available", "0");
 }
 
 void m_focus_item_chain(entity outermost, entity innermost)
@@ -955,12 +1002,16 @@ void m_goto(string itemname)
                if (gamestatus & (GAME_ISSERVER | GAME_CONNECTED))
                {
                        m_hide();
+                       return;
                }
-               else
-               {
-                       m_activate_window(main.mainNexposee);
-                       m_display();
-               }
+               itemname = "nexposee";
+       }
+
+       if (itemname == "nexposee")
+       {
+               // unlike 'togglemenu 1', this closes modal and root dialogs if opened
+               m_activate_window(main.mainNexposee);
+               m_display();
        }
        else
        {