Merge branch 'master' into terencehill/menu_quit_game
authorterencehill <piuntn@gmail.com>
Mon, 28 Mar 2022 15:14:35 +0000 (17:14 +0200)
committerterencehill <piuntn@gmail.com>
Mon, 28 Mar 2022 15:14:35 +0000 (17:14 +0200)
32 files changed:
binds-xonotic.cfg
commands.cfg
qcsrc/client/main.qc
qcsrc/common/campaign_setup.qc
qcsrc/menu/command/menu_cmd.qc
qcsrc/menu/menu.qc
qcsrc/menu/xonotic/_mod.inc
qcsrc/menu/xonotic/_mod.qh
qcsrc/menu/xonotic/commandbutton.qc
qcsrc/menu/xonotic/dialog_disconnect.qc [deleted file]
qcsrc/menu/xonotic/dialog_disconnect.qh [deleted file]
qcsrc/menu/xonotic/dialog_gamemenu.qc [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_gamemenu.qh [new file with mode: 0644]
qcsrc/menu/xonotic/dialog_multiplayer_create.qc
qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc
qcsrc/menu/xonotic/dialog_multiplayer_join.qc
qcsrc/menu/xonotic/dialog_multiplayer_join.qh
qcsrc/menu/xonotic/dialog_multiplayer_profile.qh
qcsrc/menu/xonotic/dialog_quit.qc
qcsrc/menu/xonotic/dialog_quit.qh
qcsrc/menu/xonotic/dialog_settings_input.qh
qcsrc/menu/xonotic/dialog_singleplayer.qc
qcsrc/menu/xonotic/keybinder.qc
qcsrc/menu/xonotic/leavematchbutton.qc [new file with mode: 0644]
qcsrc/menu/xonotic/leavematchbutton.qh [new file with mode: 0644]
qcsrc/menu/xonotic/mainwindow.qc
qcsrc/menu/xonotic/mainwindow.qh
qcsrc/menu/xonotic/maplist.qc
qcsrc/menu/xonotic/serverlist.qc
qcsrc/menu/xonotic/serverlist.qh
qcsrc/menu/xonotic/util.qc
qcsrc/menu/xonotic/util.qh

index fc469c2c96acfed3333c5ba35e61b08a26ae4321..a90704c870164c570bfecef52adaa3fc3bd6cd6e 100644 (file)
@@ -61,7 +61,6 @@ bind i +show_info
 bind PAUSE pause
 bind F9 "cl_cmd hud minigame"
 bind F10 menu_showquitdialog
-bind F11 menu_showdisconnectdialog
 bind F12 screenshot
 bind F4 ready
 
index c84d748e6c763fa6b8ab2952823f780df00b0183..1e26673d42055b639a03f40bbc12d9358e842c07 100644 (file)
@@ -117,7 +117,7 @@ alias menu_showhudexit "menu_cmd directmenu HUDExit"
 alias menu_showhudoptions "menu_cmd directpanelhudmenu ${* ?}"
 alias menu_showsandboxtools "menu_cmd directmenu SandboxTools"
 alias menu_showquitdialog "menu_cmd directmenu Quit"
-alias menu_showdisconnectdialog "menu_cmd directmenu Disconnect"
+alias menu_showgamemenudialog "menu_cmd directmenu GameMenu"
 alias menu_showmonstertools "menu_cmd directmenu MonsterTools"
 
 // command executed before loading a map by the menu
index afebfd77ef0d35c5a257ef943211f037b82e69f2..16227a0cba9071dfb31632f5376b21df07dd43eb 100644 (file)
@@ -471,6 +471,32 @@ float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary)
        if(override)
                return true;
 
+       if(bInputType == 3 || bInputType == 2)
+               return false;
+
+       // at this point bInputType can only be 0 or 1 (key pressed or released)
+       bool key_pressed = (bInputType == 0);
+
+       if(key_pressed) {
+               if(nPrimary == K_ALT) hudShiftState |= S_ALT;
+               if(nPrimary == K_CTRL) hudShiftState |= S_CTRL;
+               if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
+       }
+       else {
+               if(nPrimary == K_ALT) hudShiftState -= (hudShiftState & S_ALT);
+               if(nPrimary == K_CTRL) hudShiftState -= (hudShiftState & S_CTRL);
+               if(nPrimary == K_SHIFT) hudShiftState -= (hudShiftState & S_SHIFT);
+       }
+
+       if (nPrimary == K_ESCAPE && !(hudShiftState & S_SHIFT) && key_pressed)
+       {
+               if (cvar("_menu_gamemenu_dialog_available"))
+               {
+                       localcmd("\nmenu_showgamemenudialog\n");
+                       return true;
+               }
+       }
+
        return false;
 }
 
index 8be208980a3061d1b595d04ccb40c25235538f37..2b174a68de0a0422cb81bc9d3efc30b8c73acc49 100644 (file)
@@ -18,4 +18,7 @@ void CampaignSetup(int n)
                localcmd("\n");
        localcmd("disconnect\nmaxplayers 16\n");
        MapInfo_LoadMap(campaign_mapname[n], 1);
+       #ifdef MENUQC
+       makeServerSingleplayer();
+       #endif
 }
index b933a9194f4747bf8f5e5c7e61505e5abdb1392f..b56e8e9e4afd4ba69e8047d6afbdc04cd64119d7 100644 (file)
@@ -122,6 +122,24 @@ void GameCommand(string theCommand)
                return;
        }
 
+       if (argv(0) == "nexposee")
+       {
+               m_goto("nexposee");
+               return;
+       }
+
+       if (argv(0) == "servers")
+       {
+               m_goto("servers");
+               return;
+       }
+
+       if (argv(0) == "profile")
+       {
+               m_goto("profile");
+               return;
+       }
+
        if (argv(0) == "skinselect")
        {
                m_goto("skinselector");
@@ -134,6 +152,12 @@ void GameCommand(string theCommand)
                return;
        }
 
+       if (argv(0) == "inputsettings")
+       {
+               m_goto("inputsettings");
+               return;
+       }
+
        if (argv(0) == "videosettings")
        {
                m_goto("videosettings");
index 710dca1e6685be3d57671237bd9a1647148cfa55..4030270d321b727222074e2d7fbe7ec1709446ef 100644 (file)
@@ -673,6 +673,7 @@ void m_tooltip(vector pos)
 }
 
 float autocvar_menu_force_on_disconnection;
+bool autocvar_g_campaign;
 void m_draw(float width, float height)
 {
        if (autocvar_menu_force_on_disconnection > 0)
@@ -680,6 +681,14 @@ void m_draw(float width, float height)
                static float connected_time;
                if (clientstate() == CS_DISCONNECTED)
                {
+                       if (autocvar_g_campaign)
+                       {
+                               // 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();
+                       }
                        if (connected_time && time - connected_time > autocvar_menu_force_on_disconnection)
                        {
                                m_toggle(true);
@@ -960,12 +969,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
        {
index cd3b9cb471dd71a963b5d460b69b0903f76e9ff6..103b2ea675f7c79e1dfca814f3f652ebbdb0b74e 100644 (file)
@@ -19,8 +19,8 @@
 #include <menu/xonotic/demolist.qc>
 #include <menu/xonotic/dialog.qc>
 #include <menu/xonotic/dialog_credits.qc>
-#include <menu/xonotic/dialog_disconnect.qc>
 #include <menu/xonotic/dialog_firstrun.qc>
+#include <menu/xonotic/dialog_gamemenu.qc>
 #include <menu/xonotic/dialog_hudpanel_ammo.qc>
 #include <menu/xonotic/dialog_hudpanel_centerprint.qc>
 #include <menu/xonotic/dialog_hudpanel_chat.qc>
 #include <menu/xonotic/playerlist.qc>
 #include <menu/xonotic/playermodel.qc>
 #include <menu/xonotic/playlist.qc>
+#include <menu/xonotic/leavematchbutton.qc>
 #include <menu/xonotic/radiobutton.qc>
 #include <menu/xonotic/rootdialog.qc>
 #include <menu/xonotic/screenshotimage.qc>
index a1e9e31e1c7a465e4e421fa11eaf5e853327f2ac..2e0cf762bf7deee45b442ec4522b9b5cea268073 100644 (file)
@@ -19,8 +19,8 @@
 #include <menu/xonotic/demolist.qh>
 #include <menu/xonotic/dialog.qh>
 #include <menu/xonotic/dialog_credits.qh>
-#include <menu/xonotic/dialog_disconnect.qh>
 #include <menu/xonotic/dialog_firstrun.qh>
+#include <menu/xonotic/dialog_gamemenu.qh>
 #include <menu/xonotic/dialog_hudpanel_ammo.qh>
 #include <menu/xonotic/dialog_hudpanel_centerprint.qh>
 #include <menu/xonotic/dialog_hudpanel_chat.qh>
 #include <menu/xonotic/playerlist.qh>
 #include <menu/xonotic/playermodel.qh>
 #include <menu/xonotic/playlist.qh>
+#include <menu/xonotic/leavematchbutton.qh>
 #include <menu/xonotic/radiobutton.qh>
 #include <menu/xonotic/rootdialog.qh>
 #include <menu/xonotic/screenshotimage.qh>
index fa15bdbbd7938da53d8f5db17f80ff80fa2995b9..ec03633eb136dc3cc9b4def9d3218034bd824d9d 100644 (file)
@@ -1,4 +1,5 @@
 #include "commandbutton.qh"
+#include "dialog.qh"
 
 entity makeXonoticCommandButton_T(string theText, vector theColor, string theCommand, int theFlags, string theTooltip)
 {
@@ -20,7 +21,7 @@ void XonoticCommandButton_Click(entity me, entity other)
        //if(me.flags & COMMANDBUTTON_REVERT)
        //      loadAllCvars(me.parent);
        if(me.flags & COMMANDBUTTON_CLOSE)
-               m_goto(string_null);
+               me.parent.close(me.parent);
 }
 
 void XonoticCommandButton_configureXonoticCommandButton(entity me, string theText, vector theColor, string theCommand, int theFlags, string theTooltip)
diff --git a/qcsrc/menu/xonotic/dialog_disconnect.qc b/qcsrc/menu/xonotic/dialog_disconnect.qc
deleted file mode 100644 (file)
index 83e1ca0..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-#include "dialog_disconnect.qh"
-
-#include "textlabel.qh"
-#include "button.qh"
-
-void Disconnect_Click(entity btn, entity me)
-{
-       localcmd("disconnect\n");
-       Dialog_Close(btn, me);
-}
-
-void XonoticDisconnectDialog_fill(entity me)
-{
-       entity e;
-       me.TR(me);
-               me.TD(me, 1, 2, makeXonoticTextLabel(0.5, _("Are you sure to disconnect from server?")));
-       me.TR(me);
-       me.TR(me);
-               me.TD(me, 1, 1, e = makeXonoticButton_T(_("Yes"), '1 0 0', _("I would disconnect from server...")));
-                       e.onClick = Disconnect_Click;
-                       e.onClickEntity = me;
-               me.TD(me, 1, 1, e = makeXonoticButton_T(_("No"), '0 1 0', _("I would play more!")));
-                       e.onClick = Dialog_Close;
-                       e.onClickEntity = me;
-}
diff --git a/qcsrc/menu/xonotic/dialog_disconnect.qh b/qcsrc/menu/xonotic/dialog_disconnect.qh
deleted file mode 100644 (file)
index 5e397cd..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-
-#include "dialog.qh"
-CLASS(XonoticDisconnectDialog, XonoticDialog)
-       METHOD(XonoticDisconnectDialog, fill, void(entity));
-       ATTRIB(XonoticDisconnectDialog, title, string, _("Disconnect"));
-       ATTRIB(XonoticDisconnectDialog, tooltip, string, _("Disconnect from the server you are connected to"));
-       ATTRIB(XonoticDisconnectDialog, color, vector, SKINCOLOR_DIALOG_QUIT);
-       ATTRIB(XonoticDisconnectDialog, intendedWidth, float, 0.5);
-       ATTRIB(XonoticDisconnectDialog, rows, float, 3);
-       ATTRIB(XonoticDisconnectDialog, colums, float, 2);
-       ATTRIB(XonoticDisconnectDialog, name, string, "Disconnect");
-ENDCLASS(XonoticDisconnectDialog)
diff --git a/qcsrc/menu/xonotic/dialog_gamemenu.qc b/qcsrc/menu/xonotic/dialog_gamemenu.qc
new file mode 100644 (file)
index 0000000..2613454
--- /dev/null
@@ -0,0 +1,45 @@
+#include "dialog_gamemenu.qh"
+
+#include "textlabel.qh"
+#include "commandbutton.qh"
+#include "leavematchbutton.qh"
+#include "button.qh"
+
+void XonoticGameMenuDialog_destroy(entity me)
+{
+       cvar_set("_menu_gamemenu_dialog_available", "0");
+}
+
+void XonoticGameMenuDialog_fill(entity me)
+{
+       registercvar("_menu_gamemenu_dialog_available", "0", 0);
+       cvar_set("_menu_gamemenu_dialog_available", "1");
+
+       entity e;
+       me.TR(me);
+               me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Main menu"), '0 0 0', "menu_cmd nexposee", 0));
+       me.TR(me);
+               me.TDempty(me, 0.1);
+               me.TD(me, 1, 0.8, e = makeXonoticCommandButton(_("Servers"), '0 0 0', "menu_cmd servers", 0));
+       me.TR(me);
+               me.TDempty(me, 0.1);
+               me.TD(me, 1, 0.8, e = makeXonoticCommandButton(_("Profile"), '0 0 0', "menu_cmd profile", 0));
+       me.TR(me);
+               me.TDempty(me, 0.1);
+               me.TD(me, 1, 0.8, e = makeXonoticCommandButton(_("Settings"), '0 0 0', "menu_cmd videosettings", 0));
+       me.TR(me);
+               me.TDempty(me, 0.1);
+               me.TD(me, 1, 0.8, e = makeXonoticCommandButton(_("Keys"), '0 0 0', "menu_cmd inputsettings", 0));
+       me.TR(me);
+               me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Quick menu"), '0 0 0', "quickmenu", COMMANDBUTTON_CLOSE));
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Join!"), '0 0 0', "join", COMMANDBUTTON_CLOSE));
+       me.TR(me);
+               me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Spectate"), '0 0 0', "spec", COMMANDBUTTON_CLOSE));
+       me.TR(me);
+       me.TR(me);
+               me.TD(me, 1, 1, e = makeXonoticLeaveMatchButton('0 0 0', COMMANDBUTTON_CLOSE));
+       me.TR(me);
+               me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Quit Xonotic"), '1 0 0', "echo ]quit; quit", 0));
+}
diff --git a/qcsrc/menu/xonotic/dialog_gamemenu.qh b/qcsrc/menu/xonotic/dialog_gamemenu.qh
new file mode 100644 (file)
index 0000000..b0d12ea
--- /dev/null
@@ -0,0 +1,14 @@
+#pragma once
+
+#include "rootdialog.qh"
+CLASS(XonoticGameMenuDialog, XonoticRootDialog)
+       METHOD(XonoticGameMenuDialog, destroy, void(entity));
+       METHOD(XonoticGameMenuDialog, fill, void(entity));
+       ATTRIB(XonoticGameMenuDialog, title, string, _("Game menu"));
+       ATTRIB(XonoticGameMenuDialog, color, vector, SKINCOLOR_DIALOG_QUIT);
+       ATTRIB(XonoticGameMenuDialog, intendedWidth, float, 0.3);
+       ATTRIB(XonoticGameMenuDialog, rows, float, 12);
+       ATTRIB(XonoticGameMenuDialog, columns, float, 1);
+       ATTRIB(XonoticGameMenuDialog, name, string, "GameMenu");
+       ATTRIB(XonoticGameMenuDialog, requiresConnection, bool, true);
+ENDCLASS(XonoticGameMenuDialog)
index ba09c311e4bf0e3fbf99a69898bf91b7fb70e638..a343c546c28827ded6d7f5888db2e2d535f3a6eb 100644 (file)
@@ -13,6 +13,8 @@
 #include "slider.qh"
 #include "mainwindow.qh"
 #include "button.qh"
+#include "commandbutton.qh"
+#include "leavematchbutton.qh"
 #include "inputbox.qh"
 
 void GameType_ConfigureSliders(entity me, string pLabel, float pMin, float pMax, float pStep, string pCvar, string tCvar, string pTooltip)
@@ -119,11 +121,13 @@ void XonoticServerCreateTab_fill(entity me)
                        _("The maximum amount of players or bots that can be connected to your server at once")));
        me.TR(me);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Number of bots:")));
+                       setDependent(e, "g_campaign", 0, 0);
                me.TD(me, 1, 2, e = makeXonoticSlider_T(0, 9, 1, "bot_number",
                        _("Amount of bots on your server")));
+                       setDependent(e, "g_campaign", 0, 0);
        me.TR(me);
                me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Bot skill:")));
-                       setDependent(e, "bot_number", 0, -1);
+                       setDependentAND(e, "bot_number", 0, -1, "g_campaign", 0, 0);
                me.TD(me, 1, 2, e = makeXonoticTextSlider_T("skill",
                        _("Specify how experienced the bots will be")));
                        e.addValue(e, _("Botlike"), "0");
@@ -138,13 +142,14 @@ void XonoticServerCreateTab_fill(entity me)
                        e.addValue(e, _("Unhuman"), "9");
                        e.addValue(e, _("Godlike"), "10");
                        e.configureXonoticTextSliderValues(e);
-                       setDependent(e, "bot_number", 0, -1);
+                       setDependentAND(e, "bot_number", 0, -1, "g_campaign", 0, 0);
 
        me.gotoRC(me, me.rows - 3.8, 0);
                me.TD(me, 1, 3, e0 = makeXonoticTextLabel(0.5, string_null));
                        e0.textEntity = main.mutatorsDialog;
                        e0.allowCut = 1;
                        //e0.allowWrap = 1;
+                       setDependent(e0, "g_campaign", 0, 0);
 
        // mapListBox is in the right column but the ref is needed for mutators dialog here
        me.mapListBox = makeXonoticMapList();
@@ -157,6 +162,7 @@ void XonoticServerCreateTab_fill(entity me)
                        e.onClick = DialogOpenButton_Click;
                        e.onClickEntity = main.mutatorsDialog;
                        main.mutatorsDialog.refilterEntity = me.mapListBox;
+                       setDependent(e, "g_campaign", 0, 0);
 
        // The right half begins here
 
@@ -200,10 +206,11 @@ void XonoticServerCreateTab_fill(entity me)
                        e.onClick = MapList_Remove_All;
                        e.onClickEntity = me.mapListBox;
 
-       // The big button at the bottom
-
+       // bottom row
        me.gotoRC(me, me.rows - 1, 0);
-               me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Multiplayer!"), '0 0 0'));
+               me.TDempty(me, me.columns * 1/12);
+               me.TD(me, 1, me.columns * 5/12, e = makeXonoticLeaveMatchButton('0 0 0', 0));
+               me.TD(me, 1, me.columns * 5/12, e = makeXonoticButton(_("Start multiplayer!"), '0 0 0'));
                        e.onClick = MapList_LoadMap;
                        e.onClickEntity = me.mapListBox;
                        me.mapListBox.startButton = e;
index 87ffadf3831d8015641eb7b3b9e50e7d8e95ecc7..c9db70116f0f171729d6e3115aa20f06233bc2de 100644 (file)
@@ -88,4 +88,5 @@ void XonoticMapInfoDialog_fill(entity me)
                me.TD(me, 1, me.columns - 5.5, me.startButton = e = makeXonoticButton(ZCTX(_("MAP^Play")), '0 0 0'));
                        me.startButton.onClick = MapList_LoadMap;
                        me.startButton.onClickEntity = NULL; // filled later
+                       setDependent(e, "g_campaign", 0, 0);
 }
index 01e4381e85196b43d3d3fd79d3af7cb35eacd362..02b6464f6a8018bdcdece83541ca7ba4fcb1685a 100644 (file)
@@ -6,6 +6,7 @@
 #include "inputbox.qh"
 #include "checkbox.qh"
 #include "commandbutton.qh"
+#include "leavematchbutton.qh"
 #include "button.qh"
 
 entity makeXonoticServerListTab()
@@ -88,12 +89,8 @@ void XonoticServerListTab_fill(entity me)
                        e.onClickEntity = slist;
                        slist.infoButton = e;
        me.TR(me);
-               /*
-               me.TD(me, 1, 1, e = makeXonoticCommandButton_T(_("Disconnect"), '0 0 0', "disconnect", 0,
-                       _("Disconnect from the server")));
-                       slist.disconnectButton = e;
-               */
-               me.TD(me, 1, me.columns, e = makeXonoticButton(_("Join!"), '0 0 0'));
+               me.TD(me, 1, me.columns * 0.5, e = makeXonoticLeaveMatchButton('0 0 0', 0));
+               me.TD(me, 1, me.columns * 0.5, e = makeXonoticButton(_("Join!"), '0 0 0'));
                        e.onClick = ServerList_Connect_Click;
                        e.onClickEntity = slist;
                        slist.connectButton = e;
index a663eb527be116ba9e0b75bf953e6aba47f2dc2c..38744f366de85800ac7693ebd6bf4b4afba93006 100644 (file)
@@ -6,5 +6,7 @@ CLASS(XonoticServerListTab, XonoticTab)
        ATTRIB(XonoticServerListTab, intendedWidth, float, 0.9);
        ATTRIB(XonoticServerListTab, rows, float, 23);
        ATTRIB(XonoticServerListTab, columns, float, 6.5);
+
+       ATTRIB(XonoticServerListTab, name, string, "servers");
 ENDCLASS(XonoticServerListTab)
 entity makeXonoticServerListTab();
index 2285efcafa370cb6a2da6e8a0cc6c895176b96b6..f346aaf66672c0e26de8537a47dee05be6a63bf7 100644 (file)
@@ -9,5 +9,6 @@ CLASS(XonoticProfileTab, XonoticTab)
        ATTRIB(XonoticProfileTab, columns, float, 6.1);  // added extra .2 for center space
        ATTRIB(XonoticProfileTab, playerNameLabel, entity);
        ATTRIB(XonoticProfileTab, playerNameLabelAlpha, float, SKINALPHA_HEADER);
+       ATTRIB(XonoticProfileTab, name, string, "profile");
 ENDCLASS(XonoticProfileTab)
 entity makeXonoticProfileTab();
index 3f5b18712ea8263b277e72a4624a2ae0af65dd21..89bfae806495085842fce9d19fc6d4573e28966f 100644 (file)
@@ -2,19 +2,19 @@
 
 #include "textlabel.qh"
 #include "commandbutton.qh"
+#include "leavematchbutton.qh"
 #include "button.qh"
 
 void XonoticQuitDialog_fill(entity me)
 {
        entity e;
        me.TR(me);
-               me.TD(me, 1, 2, makeXonoticTextLabel(0.5, _("Are you sure you want to quit?")));
+               me.TDempty(me, 0.5);
+               me.TD(me, 1, 1, e = makeXonoticLeaveMatchButton('0 0 0', COMMANDBUTTON_CLOSE));
        me.TR(me);
        me.TR(me);
-               me.TD(me, 1, 1, e = makeXonoticCommandButton_T(_("Yes"), '1 0 0', "echo ]quit; quit", 0,
-                       _("Back to work...")));
-               me.TD(me, 1, 1, e = makeXonoticButton_T(_("No"), '0 1 0',
-                       _("I got some more fragging to do!")));
+               me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Quit Xonotic"), '1 0 0', "echo ]quit; quit", 0));
+               me.TD(me, 1, 1, e = makeXonoticButton(_("Cancel"), '0 1 0'));
                        e.onClick = Dialog_Close;
                        e.onClickEntity = me;
 }
index 6e8c9fea9a9748d7346f6969f4be0ace5b4fe635..ddf89e3a7bb5f2874d3a1a55f0c6099bb89e7bd1 100644 (file)
@@ -3,8 +3,8 @@
 #include "dialog.qh"
 CLASS(XonoticQuitDialog, XonoticDialog)
        METHOD(XonoticQuitDialog, fill, void(entity));
-       ATTRIB(XonoticQuitDialog, title, string, _("Quit"));
-       ATTRIB(XonoticQuitDialog, tooltip, string, _("Quit the game"));
+       ATTRIB(XonoticQuitDialog, title, string, _("Quit / Leave match"));
+       ATTRIB(XonoticQuitDialog, tooltip, string, _("Quit the game / Leave current match"));
        ATTRIB(XonoticQuitDialog, color, vector, SKINCOLOR_DIALOG_QUIT);
        ATTRIB(XonoticQuitDialog, intendedWidth, float, 0.5);
        ATTRIB(XonoticQuitDialog, rows, float, 3);
index 040908298976dd5784f3b7708ba6af6ae2d9e530..13e56afbb5bf751ce2436e4241d903c4ba0248c3 100644 (file)
@@ -6,5 +6,6 @@ CLASS(XonoticInputSettingsTab, XonoticTab)
        ATTRIB(XonoticInputSettingsTab, intendedWidth, float, 0.9);
        ATTRIB(XonoticInputSettingsTab, rows, float, 15.5);
        ATTRIB(XonoticInputSettingsTab, columns, float, 6.2);  // added extra .2 for center space
+       ATTRIB(XonoticInputSettingsTab, name, string, "inputsettings");
 ENDCLASS(XonoticInputSettingsTab)
 entity makeXonoticInputSettingsTab();
index a223f5807b318dd645f8441628a1b1e30bd50721..57184dc00f0a48103757f5491cbecf80fa26c9fa 100644 (file)
@@ -2,6 +2,8 @@
 
 #include <common/gamemodes/_mod.qh>
 #include "bigbutton.qh"
+#include "commandbutton.qh"
+#include "leavematchbutton.qh"
 #include "radiobutton.qh"
 #include "textlabel.qh"
 #include "campaign.qh"
@@ -120,6 +122,8 @@ void InstantAction_LoadMap(entity btn, entity dummy)
        localcmd("disconnect\n");
        localcmd("g_campaign 0\n");
 
+       makeServerSingleplayer();
+
        MapInfo_LoadMap(s, 1);
 
        // configure bots
@@ -166,8 +170,11 @@ void XonoticSingleplayerDialog_fill(entity me)
                me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "-2", ZCTX(_("CSKL^Easy"))));
                me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "0", ZCTX(_("CSKL^Medium"))));
                me.TD(me, 1, 1, e = makeXonoticRadioButton(1, "g_campaign_skill", "2", ZCTX(_("CSKL^Hard"))));
-               me.TR(me);
-               me.TD(me, 1, me.columns, e = makeXonoticButton(_("Start Singleplayer!"), '0 0 0'));
+       me.TR(me);
+               me.TDempty(me, me.columns * 1/13);
+               me.TD(me, 1, me.columns * 5/13, e = makeXonoticLeaveMatchButton('0 0 0', 0));
+               me.TDempty(me, me.columns * 1/13);
+               me.TD(me, 1, me.columns * 5/13, e = makeXonoticButton(_("Play campaign!"), '0 0 0'));
                        e.onClick = CampaignList_LoadMap;
                        e.onClickEntity = me.campaignBox;
 }
index a0265c4e4b5a9060891073e8a60c4f4a245de223..d1bc88c46a6032d7ef9f80041f38b6972eb7b090 100644 (file)
@@ -106,8 +106,7 @@ void KeyBinds_BuildList()
        KEYBIND_DEF("toggleconsole"                         , _("enter console"));
                string console_shortcut = strcat(translate_key("SHIFT"), "+", translate_key("ESCAPE"));
                KEYBIND_SPECIAL_DEF(console_shortcut, _("enter console"));
-       KEYBIND_DEF("disconnect"                            , _("disconnect"));
-       KEYBIND_DEF("menu_showquitdialog"                   , _("quit"));
+       KEYBIND_DEF("menu_showquitdialog"                   , _("quit / leave match"));
        KEYBIND_EMPTY_LINE();
 
        KEYBIND_HEADER(_("Teamplay"));
diff --git a/qcsrc/menu/xonotic/leavematchbutton.qc b/qcsrc/menu/xonotic/leavematchbutton.qc
new file mode 100644 (file)
index 0000000..e58cbc5
--- /dev/null
@@ -0,0 +1,53 @@
+#include "leavematchbutton.qh"
+
+// resets g_campaign and updates menu items to reflect cvar values that may have been restored after leaving the campaign
+// the delay is for allowing listening to the button sound (if enabled), since the disconnect command stops all sounds
+// menu_sync is also useful when leaving Instant Action mode
+// see also m_draw
+const string LEAVEMATCH_CMD = "defer 0.4 disconnect; defer 0.4 wait; defer 0.4 \"g_campaign 0\"; defer 0.4 menu_sync\n";
+
+string leaveMatchButton_getText(entity me)
+{
+       if (me.disabled)
+               return _("Leave current match");
+       else if(cvar("g_campaign"))
+               return _("Leave campaign");
+       else if (isServerSingleplayer())
+               return _("Leave singleplayer");
+       else
+               return _("Leave multiplayer");
+}
+
+string leaveMatchButton_getTooltip(entity me)
+{
+       if (me.disabled)
+               return "-";
+       else if(cvar("g_campaign"))
+               return _("Leave current campaign level");
+       else if (isServerSingleplayer())
+               return _("Leave current singleplayer match");
+       else
+               return _("Leave current multiplayer match / Disconnect from the server");
+}
+
+entity makeXonoticLeaveMatchButton(vector theColor, int theFlags)
+{
+       entity me;
+       me = NEW(XonoticLeaveMatchButton);
+       me.configureXonoticLeaveMatchButton(me, theColor, theFlags);
+       return me;
+}
+
+void XonoticLeaveMatchButton_draw(entity me)
+{
+       SUPER(XonoticCommandButton).draw(me);
+       me.disabled = !(gamestatus & (GAME_ISSERVER | GAME_CONNECTED));
+       me.setText(me, leaveMatchButton_getText(me));
+       setZonedTooltip(me, leaveMatchButton_getTooltip(me), string_null);
+}
+
+void XonoticLeaveMatchButton_configureXonoticLeaveMatchButton(entity me, vector theColor, int theFlags)
+{
+       me.configureXonoticCommandButton(me, string_null, theColor, LEAVEMATCH_CMD, theFlags, string_null);
+       me.draw = XonoticLeaveMatchButton_draw;
+}
diff --git a/qcsrc/menu/xonotic/leavematchbutton.qh b/qcsrc/menu/xonotic/leavematchbutton.qh
new file mode 100644 (file)
index 0000000..e1e13cb
--- /dev/null
@@ -0,0 +1,9 @@
+#pragma once
+
+#include "commandbutton.qh"
+CLASS(XonoticLeaveMatchButton, XonoticCommandButton)
+       METHOD(XonoticLeaveMatchButton, draw, void(entity));
+       METHOD(XonoticLeaveMatchButton, configureXonoticLeaveMatchButton, void(entity, vector, int));
+ENDCLASS(XonoticLeaveMatchButton)
+
+entity makeXonoticLeaveMatchButton(vector theColor, int theFlags);
index 8377c561e41d4a030f2b39b5f4403869b772de1b..e215e5080bd883bd26086268cf32aa9473b97a19 100644 (file)
@@ -43,6 +43,7 @@
 #include "dialog_multiplayer_create_mutators.qh"
 #include "dialog_sandboxtools.qh"
 #include "dialog_monstertools.qh"
+#include "dialog_gamemenu.qh"
 #include "dialog_welcome.qh"
 #include "dialog_teamselect.qh"
 #include "dialog_uid2name.qh"
 #include "dialog_credits.qh"
 #include "dialog_quit.qh"
 
-#include "dialog_disconnect.qh"
-
-
-
 void MainWindow_draw(entity me)
 {
        SUPER(MainWindow).draw(me);
@@ -71,33 +68,6 @@ void MainWindow_draw(entity me)
                
                me.firstDraw = false;
        }
-
-       //-------------------------------------
-       // Part of Disconnect Dialog button:
-       // In case of this function is recalling every time, need to use condition of visibility 
-       
-       if (me.disconnectDialogVisibility && !(gamestatus & (GAME_ISSERVER | GAME_CONNECTED))) 
-       {
-               // If gamestate is not "ingame" (and it is a first "frame" of drawing (or dialog is visible)), 
-               // disconnect button is unnecessary, remove it
-               me.removeItem(me.mainNexposee, me.disconnectDialog);
-               me.disconnectDialogVisibility = 0;
-
-       } else if(!me.disconnectDialogVisibility && (gamestatus & (GAME_ISSERVER | GAME_CONNECTED))) {
-               
-               // If gamestate is "ingame" (and dialog is not visible), 
-               // make disconnect button visible
-               entity n, i;
-               n = me.mainNexposee;
-               i = me.disconnectDialog;
-               n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-               n.setNexposee(n, i, '0.5 1.2 0.0', SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
-               me.disconnectDialogVisibility = 1;
-       }
-
-       // I haven't found the best solution for making button visible. 
-       // Alpha channel is the worst thing, because dialog with alpha is also clickable
-       //-------------------------------------
 }
 
 void DemoButton_Click(entity me, entity other)
@@ -281,6 +251,10 @@ void MainWindow_configureMainWindow(entity me)
 
 
        // miscellaneous dialogs
+       i = NEW(XonoticGameMenuDialog);
+       i.configureDialog(i);
+       me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
+
        i = NEW(XonoticTeamSelectDialog);
        i.configureDialog(i);
        me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
@@ -330,14 +304,6 @@ void MainWindow_configureMainWindow(entity me)
                n.setNexposee(n, i, SKINPOSITION_DIALOG_CREDITS, SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
                n.pullNexposee(n, i, eY * (SKINHEIGHT_TITLE * SKINFONTSIZE_TITLE / conheight));
 
-               //Disconnect dialog at center of screen (between credits and quit)
-               i = NEW(XonoticDisconnectDialog);
-               i.configureDialog(i);
-               n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
-               n.setNexposee(n, i, '0.5 1.2 0.0', SKINALPHAS_MAINMENU_x, SKINALPHAS_MAINMENU_y);
-               n.pullNexposee(n, i, eY * (SKINHEIGHT_TITLE * SKINFONTSIZE_TITLE / conheight));
-               me.disconnectDialog = i;
-       
                i = NEW(XonoticQuitDialog);
                i.configureDialog(i);
                n.addItemCentered(n, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z);
@@ -348,5 +314,4 @@ void MainWindow_configureMainWindow(entity me)
        me.moveItemAfter(me, n, NULL);
 
        me.initializeDialog(me, n);
-       me.disconnectDialogVisibility = 1;
 }
index 82e126a9f0f41025c7cf7c7ae725d0d51020abe4..24adc370173b077a014941f16cca2aad7677eb09 100644 (file)
@@ -25,6 +25,4 @@ CLASS(MainWindow, ModalController)
        ATTRIB(MainWindow, demostartconfirmDialog, entity);
        ATTRIB(MainWindow, demotimeconfirmDialog, entity);
        ATTRIB(MainWindow, resetDialog, entity);
-       ATTRIB(MainWindow, disconnectDialog, entity);
-       ATTRIB(MainWindow, disconnectDialogVisibility, float, 1);
 ENDCLASS(MainWindow)
index a18037db63178830a7e85d675a66564cf01a7a47..72421150852367bb1379ccc6427cbef05cec4a37 100644 (file)
@@ -79,7 +79,8 @@ void XonoticMapList_g_maplistCacheToggle(entity me, float i)
 void XonoticMapList_draw(entity me)
 {
        if(me.startButton)
-               me.startButton.disabled = ((me.selectedItem < 0) || (me.selectedItem >= me.nItems));
+               me.startButton.disabled = ((me.selectedItem < 0) || (me.selectedItem >= me.nItems)
+                       || (gamestatus & (GAME_ISSERVER | GAME_CONNECTED) && cvar("g_campaign")));
        SUPER(XonoticMapList).draw(me);
 }
 
index 7d5d21e30df9c2653f448cced6b08c18d141fb43..e07081e542fc7f11b980c18cf25b0bc0f54c1a41 100644 (file)
@@ -541,7 +541,6 @@ void XonoticServerList_draw(entity me)
        }
 
        me.connectButton.disabled = (me.ipAddressBox.text == "");
-       //me.disconnectButton.disabled = (!(gamestatus & (GAME_ISSERVER | GAME_CONNECTED)));
        me.infoButton.disabled = !owned;
        me.favoriteButton.disabled = (me.ipAddressBox.text == "");
 
index 150e220715c21a4b776178947056543df0559527..019e11abe42164bfc809958ddd30f9c54da5f768 100644 (file)
@@ -53,7 +53,6 @@ CLASS(XonoticServerList, XonoticListBox)
        ATTRIB(XonoticServerList, sortButton4, entity);
        ATTRIB(XonoticServerList, sortButton5, entity);
        ATTRIB(XonoticServerList, connectButton, entity);
-       //ATTRIB(XonoticServerList, disconnectButton, entity);
        ATTRIB(XonoticServerList, infoButton, entity);
        ATTRIB(XonoticServerList, currentSortOrder, float, 0);
        ATTRIB(XonoticServerList, currentSortField, float, -1);
index f7c5b3f41d732e634ee7eb02974ed32408e1a48d..63eb27abf7b4ffba689280b1f4c83f4faa8357f5 100644 (file)
@@ -829,6 +829,18 @@ void dialog_hudpanel_main_settings(entity me, string panelname)
                                e.configureXonoticTextSliderValues(e);
 }
 
+bool isServerSingleplayer()
+{
+       return (cvar_string("net_address") == "127.0.0.1" && cvar_string("net_address_ipv6") == "::1");
+}
+
+void makeServerSingleplayer()
+{
+       // it doesn't allow clients to connect from different machines
+       localcmd("defer 0.1 \"sv_cmd settemp net_address 127.0.0.1\"\n");
+       localcmd("defer 0.1 \"sv_cmd settemp net_address_ipv6 ::1\"\n");
+}
+
 float getFadedAlpha(float currentAlpha, float startAlpha, float targetAlpha)
 {
        if(startAlpha < targetAlpha)
index 9e90c77764d020715c4b6bc94ad71deeee6f19aa..bb5de1b5141e6769068fd473d3b9b63e8ead67d5 100644 (file)
@@ -39,6 +39,9 @@ int GameType_GetTotalCount();
 void dialog_hudpanel_main_checkbox(entity me, string panelname);
 void dialog_hudpanel_main_settings(entity me, string panelname);
 
+bool isServerSingleplayer();
+void makeServerSingleplayer();
+
 float getFadedAlpha(float currentAlpha, float startAlpha, float targetAlpha);
 
 string _Nex_ExtResponseSystem_BannedServers;