From: terencehill Date: Sat, 14 Sep 2024 21:53:05 +0000 (+0200) Subject: Ask player if they want to forfeit on F3 press while playing. Allow F3 to switch... X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=3485e1b10d776b7aa561b6ceb2226887bf1c6fd3;p=xonotic%2Fxonotic-data.pk3dir.git Ask player if they want to forfeit on F3 press while playing. Allow F3 to switch from spectator to observer too The F3 key now consistently works while playing and while spectating another player --- diff --git a/commands.cfg b/commands.cfg index ae8719a0f..748f2aecd 100644 --- a/commands.cfg +++ b/commands.cfg @@ -129,6 +129,7 @@ alias menu_showhudoptions "menu_cmd directpanelhudmenu ${* ?}" alias menu_showsandboxtools "menu_cmd directmenu SandboxTools" alias menu_showquitdialog "menu_cmd directmenu Quit" alias menu_showgamemenudialog "menu_cmd directmenu GameMenu" +alias menu_showforfeitdialog "menu_cmd directmenu Forfeit" alias menu_showmonstertools "menu_cmd directmenu MonsterTools" // command executed before loading a map by the menu diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc index 5315d1e88..b77e1b052 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc @@ -634,7 +634,7 @@ MUTATOR_HOOKFUNCTION(ca, ClientCommand_Spectate) { // they're going to spec, we can do other checks if (autocvar_sv_spectate && (IS_SPEC(player) || IS_OBSERVER(player))) - Send_Notification(NOTIF_ONE_ONLY, player, MSG_INFO, INFO_CA_LEAVE); + return MUT_SPECCMD_RETURN_FORFEIT; return MUT_SPECCMD_FORCE; } diff --git a/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc b/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc index deaae435c..825276980 100644 --- a/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc +++ b/qcsrc/common/gamemodes/gamemode/survival/sv_survival.qc @@ -483,7 +483,7 @@ MUTATOR_HOOKFUNCTION(surv, ClientCommand_Spectate) { // they're going to spec, we can do other checks if (autocvar_sv_spectate && (IS_SPEC(player) || IS_OBSERVER(player))) - Send_Notification(NOTIF_ONE_ONLY, player, MSG_INFO, INFO_CA_LEAVE); + return MUT_SPECCMD_RETURN_FORFEIT; return MUT_SPECCMD_FORCE; } diff --git a/qcsrc/menu/xonotic/_mod.inc b/qcsrc/menu/xonotic/_mod.inc index 96287299d..8d2c3e8a4 100644 --- a/qcsrc/menu/xonotic/_mod.inc +++ b/qcsrc/menu/xonotic/_mod.inc @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/_mod.qh b/qcsrc/menu/xonotic/_mod.qh index c8941bbd6..a9a94c9c1 100644 --- a/qcsrc/menu/xonotic/_mod.qh +++ b/qcsrc/menu/xonotic/_mod.qh @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/qcsrc/menu/xonotic/dialog_forfeit.qc b/qcsrc/menu/xonotic/dialog_forfeit.qc new file mode 100644 index 000000000..c6e2bca46 --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_forfeit.qc @@ -0,0 +1,18 @@ +#include "dialog_forfeit.qh" + +#include "button.qh" +#include "commandbutton.qh" +#include "textlabel.qh" + +void XonoticForfeitDialog_fill(entity me) +{ + entity e; + me.TR(me); + me.TD(me, 1, 2, makeXonoticTextLabel(0.5, _("Are you sure you want to observe and quit current match?"))); + me.TR(me); + me.TR(me); + me.TD(me, 1, 1, e = makeXonoticCommandButton(_("Yes"), '1 0 0', "spec \"\" FORFEIT", COMMANDBUTTON_CLOSE)); + me.TD(me, 1, 1, e = makeXonoticButton(_("No"), '0 1 0')); + e.onClick = Dialog_Close; + e.onClickEntity = me; +} diff --git a/qcsrc/menu/xonotic/dialog_forfeit.qh b/qcsrc/menu/xonotic/dialog_forfeit.qh new file mode 100644 index 000000000..7e8ecb3b2 --- /dev/null +++ b/qcsrc/menu/xonotic/dialog_forfeit.qh @@ -0,0 +1,12 @@ +#pragma once + +#include "dialog.qh" +CLASS(XonoticForfeitDialog, XonoticRootDialog) + METHOD(XonoticForfeitDialog, fill, void(entity)); + ATTRIB(XonoticForfeitDialog, title, string, _("Forfeit")); + ATTRIB(XonoticForfeitDialog, name, string, "Forfeit"); + ATTRIB(XonoticForfeitDialog, color, vector, SKINCOLOR_DIALOG_QUIT); + ATTRIB(XonoticForfeitDialog, intendedWidth, float, 0.5); + ATTRIB(XonoticForfeitDialog, rows, float, 3); + ATTRIB(XonoticForfeitDialog, columns, float, 2); +ENDCLASS(XonoticForfeitDialog) diff --git a/qcsrc/menu/xonotic/mainwindow.qc b/qcsrc/menu/xonotic/mainwindow.qc index 039d3452f..3eacbed8c 100644 --- a/qcsrc/menu/xonotic/mainwindow.qc +++ b/qcsrc/menu/xonotic/mainwindow.qc @@ -6,6 +6,7 @@ #include "inputbox.qh" #include "dialog_termsofservice.qh" #include "dialog_firstrun.qh" +#include "dialog_forfeit.qh" #include "dialog_hudsetup_exit.qh" #include "dialog_hudpanel_notification.qh" #include "dialog_hudpanel_ammo.qh" @@ -268,6 +269,10 @@ void MainWindow_configureMainWindow(entity me) i.configureDialog(i); me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + i = NEW(XonoticForfeitDialog); + i.configureDialog(i); + me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z); + i = NEW(XonoticMonsterToolsDialog); i.configureDialog(i); me.addItemCentered(me, i, i.intendedWidth * eX + i.intendedHeight * eY, SKINALPHAS_MAINMENU_z * SKINALPHA_DIALOG_SANDBOXTOOLS); diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 25a8c1b67..e527029b5 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -710,10 +710,42 @@ void ClientCommand_spectate(entity caller, int request) return; } + bool caller_wants_to_forfeit = false; + if (argv(2) == "FORFEIT" || warmup_stage) + caller_wants_to_forfeit = true; // player replied that they want to forfeit + + if (IS_PLAYER(caller) && !caller_wants_to_forfeit) + { + // ask player if they want to forfeit + stuffcmd(caller, "menu_showforfeitdialog\n"); + return; + } + + if (IS_SPEC(caller) && (!observe_blocked_if_eliminated || !INGAME(caller))) + { + // turn spectator into observer + caller.would_spectate = false; + TRANSMUTE(Observer, caller); + PutClientInServer(caller); + caller.flags |= FL_CLIENT | FL_NOTARGET; + return; + } + int mutator_returnvalue = MUTATOR_CALLHOOK(ClientCommand_Spectate, caller); if (mutator_returnvalue == MUT_SPECCMD_RETURN) return; + if (mutator_returnvalue == MUT_SPECCMD_RETURN_FORFEIT) + { + if (caller_wants_to_forfeit) + mutator_returnvalue = MUT_SPECCMD_FORCE; + else + { + stuffcmd(caller, "menu_showobservedialog\n"); + return; + } + } + if ((IS_PLAYER(caller) || mutator_returnvalue == MUT_SPECCMD_FORCE || caller.wants_join)) if (autocvar_sv_spectate) ClientKill_TeamChange(caller, -2); // observe @@ -726,8 +758,10 @@ void ClientCommand_spectate(entity caller, int request) default: case CMD_REQUEST_USAGE: { - sprint(caller, "\nUsage:^3 cmd spectate []\n"); + sprint(caller, "\nUsage:^3 cmd spectate [] [FORFEIT]\n"); sprint(caller, " Where can be the player to spectate.\n"); + sprint(caller, " If is \"\" or not specified, caller becomes observer.\n"); + sprint(caller, " If is \"\", FORFEIT makes so that caller forcedly quits current game.\n"); return; } } diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index 34155a4d3..53a09a9e3 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -992,6 +992,7 @@ MUTATOR_HOOKABLE(ClientCommand_Spectate, EV_ClientCommand_Spectate); enum { MUT_SPECCMD_CONTINUE, // return this flag to make the function continue as normal MUT_SPECCMD_RETURN, // return this flag to make the function return (don't spectate) + MUT_SPECCMD_RETURN_FORFEIT, // like MUT_SPECCMD_RETURN and ask player if they want to forfeit MUT_SPECCMD_FORCE // return this flag to force the player to spectate, even if they're not a player };