From: bones_was_here Date: Sat, 5 Apr 2025 11:12:10 +0000 (+1000) Subject: sv_spectate: add less harsh mode "2", improve notifications X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=9f2f3f1754e183286db97f512420e52b2a38dceb;p=xonotic%2Fxonotic-data.pk3dir.git sv_spectate: add less harsh mode "2", improve notifications More friendly than mode "0": direct spectating is disabled during the match but observing is still allowed so nobody gets kicked. Updates two existing sv_spectate notifications to use MULTI macros. --- diff --git a/notifications.cfg b/notifications.cfg index 98db7e9eba..5cce58ad1a 100644 --- a/notifications.cfg +++ b/notifications.cfg @@ -283,6 +283,8 @@ seta notification_INFO_ROUND_PLAYER_WIN "1" "\"0\" = off, \"1\" = print to conso seta notification_INFO_ROUND_TEAM_WIN "1" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" seta notification_INFO_ROUND_TIED "1" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" seta notification_INFO_SCORES "1" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" +seta notification_INFO_SPECTATE_NOTALLOWED "1" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" +seta notification_INFO_SPECTATE_SPEC_NOTALLOWED "1" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" seta notification_INFO_SPECTATE_WARNING "1" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" seta notification_INFO_SUPERSPEC_MISSING_UID "2" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" seta notification_INFO_SUPERWEAPON_PICKUP "1" "\"0\" = off, \"1\" = print to console, \"2\" = print to console and chatbox (if notification_allow_chatboxprint is enabled)" @@ -552,6 +554,7 @@ seta notification_CENTER_SEQUENCE_COMPLETED "1" "\"0\" = off, \"1\" = centerprin seta notification_CENTER_SEQUENCE_COUNTER "1" "\"0\" = off, \"1\" = centerprint" seta notification_CENTER_SEQUENCE_COUNTER_FEWMORE "1" "\"0\" = off, \"1\" = centerprint" seta notification_CENTER_SPECTATE_NOTALLOWED "1" "\"0\" = off, \"1\" = centerprint" +seta notification_CENTER_SPECTATE_SPEC_NOTALLOWED "1" "\"0\" = off, \"1\" = centerprint" seta notification_CENTER_SPECTATE_WARNING "1" "\"0\" = off, \"1\" = centerprint" seta notification_CENTER_SUPERWEAPON_BROKEN "1" "\"0\" = off, \"1\" = centerprint" seta notification_CENTER_SUPERWEAPON_LOST "1" "\"0\" = off, \"1\" = centerprint" @@ -676,6 +679,9 @@ seta notification_ITEM_WEAPON_PRIMORSEC "1" "enable this multiple notification" seta notification_ITEM_WEAPON_UNAVAILABLE "1" "enable this multiple notification" seta notification_MULTI_COINTOSS "1" "enable this multiple notification" seta notification_MULTI_INSTAGIB_FINDAMMO "1" "enable this multiple notification" +seta notification_SPECTATE_NOTALLOWED "1" "enable this multiple notification" +seta notification_SPECTATE_SPEC_NOTALLOWED "1" "enable this multiple notification" +seta notification_SPECTATE_WARNING "1" "enable this multiple notification" seta notification_WEAPON_ACCORDEON_MURDER "1" "enable this multiple notification" seta notification_WEAPON_ACCORDEON_SUICIDE "1" "enable this multiple notification" seta notification_WEAPON_ARC_MURDER "1" "enable this multiple notification" diff --git a/qcsrc/common/notifications/all.inc b/qcsrc/common/notifications/all.inc index 1e475b1689..74713c9bf8 100644 --- a/qcsrc/common/notifications/all.inc +++ b/qcsrc/common/notifications/all.inc @@ -450,6 +450,8 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input != MULTITEAM_INFO(SCORES, N_CONSOLE, 0, 0, "", "", "", _("^TC^TT ^BGteam scores!"), "", NAME) MSG_INFO_NOTIF(SPECTATE_WARNING, N_CONSOLE, 0, 1, "f1secs", "", "", _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!"), "") + MSG_INFO_NOTIF(SPECTATE_NOTALLOWED, N_CONSOLE, 0, 0, "", "", "", _("^F2Spectating isn't allowed at this time!"), "") + MSG_INFO_NOTIF(SPECTATE_SPEC_NOTALLOWED, N_CONSOLE, 0, 0, "", "", "", _("^F2Spectating specific players isn't allowed at this time!"), "") MSG_INFO_NOTIF(SUPERWEAPON_PICKUP, N_CONSOLE, 1, 0, "s1", "s1", "superweapons", _("^BG%s^K1 picked up a Superweapon"), "") @@ -799,6 +801,7 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input != MSG_CENTER_NOTIF(SPECTATE_WARNING, N_ENABLE, 0, 1, "f1secs", CPID_PREVENT_JOIN, "0 0", _("^F2You have to become a player within the next %s, otherwise you will be kicked, because spectating isn't allowed at this time!"), "") // same string as INFO_SPECTATE_WARNING MSG_CENTER_NOTIF(SPECTATE_NOTALLOWED, N_ENABLE, 0, 0, "", CPID_Null, "0 0", _("^F2Spectating isn't allowed at this time!"), "") + MSG_CENTER_NOTIF(SPECTATE_SPEC_NOTALLOWED, N_ENABLE, 0, 0, "", CPID_Null, "0 0", _("^F2Spectating specific players isn't allowed at this time!"), "") MSG_CENTER_NOTIF(SUPERWEAPON_BROKEN, N_ENABLE, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Superweapons have broken down"), "") MSG_CENTER_NOTIF(SUPERWEAPON_LOST, N_ENABLE, 0, 0, "", CPID_POWERUP, "0 0", _("^F2Superweapons have been lost"), "") @@ -948,6 +951,10 @@ string multiteam_info_sprintf(string input, string teamname) { return ((input != MSG_MULTI_NOTIF(MULTI_COINTOSS, N_ENABLE, NULL, INFO_COINTOSS, CENTER_COINTOSS) MSG_MULTI_NOTIF(MULTI_INSTAGIB_FINDAMMO, N_ENABLE, ANNCE_NUM_10, NULL, CENTER_INSTAGIB_FINDAMMO_FIRST) + MSG_MULTI_NOTIF(SPECTATE_WARNING, N_ENABLE, NULL, INFO_SPECTATE_WARNING, CENTER_SPECTATE_WARNING) + MSG_MULTI_NOTIF(SPECTATE_NOTALLOWED, N_ENABLE, NULL, INFO_SPECTATE_NOTALLOWED, CENTER_SPECTATE_NOTALLOWED) + MSG_MULTI_NOTIF(SPECTATE_SPEC_NOTALLOWED, N_ENABLE, NULL, INFO_SPECTATE_SPEC_NOTALLOWED, CENTER_SPECTATE_SPEC_NOTALLOWED) + MSG_MULTI_NOTIF(WEAPON_ACCORDEON_MURDER, N_ENABLE, NULL, INFO_WEAPON_ACCORDEON_MURDER, NULL) MSG_MULTI_NOTIF(WEAPON_ACCORDEON_SUICIDE, N_ENABLE, NULL, INFO_WEAPON_ACCORDEON_SUICIDE, CENTER_DEATH_SELF_GENERIC) MSG_MULTI_NOTIF(WEAPON_ARC_MURDER, N_ENABLE, NULL, INFO_WEAPON_ARC_MURDER, NULL) diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 5367d48fe4..8e2408736f 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -2493,7 +2493,9 @@ void ObserverOrSpectatorThink(entity this) || (!is_spec && ((PHYS_INPUT_BUTTON_ATCK(this) && !CS(this).version_mismatch) || this.would_spectate))) { this.flags &= ~FL_JUMPRELEASED; - if(SpectateNext(this)) + if (autocvar_sv_spectate == 2 && !warmup_stage && !this.vote_master) + Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_SPECTATE_SPEC_NOTALLOWED); + else if(SpectateNext(this)) TRANSMUTE(Spectator, this); else if (is_spec) { @@ -2825,6 +2827,7 @@ void PlayerFrame (entity this) anticheat_prethink(this); // Check if spectating is allowed + // cvar hook/callback TODO: make this event-driven if (!autocvar_sv_spectate && IS_REAL_CLIENT(this) && (IS_SPEC(this) || IS_OBSERVER(this)) && !INGAME(this)) { @@ -2833,8 +2836,7 @@ void PlayerFrame (entity this) { // sv_spectate was disabled recently (or the server was stalled far too long) CS(this).spectatortime = time; // reset the grace period - Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime); - Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime); + Send_Notification(NOTIF_ONE_ONLY, this, MSG_MULTI, SPECTATE_WARNING, autocvar_g_maxplayers_spectator_blocktime); } else if (time > cutoff) if (dropclient_schedule(this)) diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 5c22952edc..d2f8c40557 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -762,6 +762,8 @@ void ClientCommand_spectate(entity caller, int request) PutClientInServer(caller); } } + else if (autocvar_sv_spectate == 2 && !warmup_stage && !caller.vote_master) + Send_Notification(NOTIF_ONE_ONLY, caller, MSG_INFO, INFO_SPECTATE_SPEC_NOTALLOWED); else { entity client = GetFilteredEntity(argv(1)); @@ -786,7 +788,7 @@ void ClientCommand_spectate(entity caller, int request) if (autocvar_sv_spectate) ClientKill_TeamChange(caller, -2); // observe else - Send_Notification(NOTIF_ONE_ONLY, caller, MSG_CENTER, CENTER_SPECTATE_NOTALLOWED); + Send_Notification(NOTIF_ONE_ONLY, caller, MSG_MULTI, SPECTATE_NOTALLOWED); } return; // never fall through to usage } diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc index e2df71b7ff..a169517556 100644 --- a/qcsrc/server/command/vote.qc +++ b/qcsrc/server/command/vote.qc @@ -489,6 +489,21 @@ void ReadyRestart_force(bool is_fake_round_start) FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), { CS(it).allowed_timeouts = autocvar_sv_timeout_number; }); } + if (autocvar_sv_spectate == 2 && !warmup_stage) + { + FOREACH_CLIENT(IS_SPEC(it), + { + if (it.vote_master) + ClientData_Touch(it.enemy); + else + { + Send_Notification(NOTIF_ONE_ONLY, it, MSG_MULTI, SPECTATE_SPEC_NOTALLOWED); + TRANSMUTE(Observer, it); + PutClientInServer(it); + } + }); + } + if (!sv_ready_restart_after_countdown || warmup_stage) reset_map(is_fake_round_start); diff --git a/xonotic-server.cfg b/xonotic-server.cfg index 38976ea130..aa22a9cad8 100644 --- a/xonotic-server.cfg +++ b/xonotic-server.cfg @@ -97,7 +97,7 @@ set sv_precacheplayermodels 1 "preload all the player models at game start, to a set sv_spectator_speed_multiplier 1.5 "base movement speed factor of spectators, all movement settings scale off this" set sv_spectator_speed_multiplier_min 1 "minimum movement speed factor for spectators as determined by scrolling" set sv_spectator_speed_multiplier_max 5 "maximum movement speed factor for spectators as determined by scrolling" -set sv_spectate 1 "\"1\" = clients are allowed to spectate or observe the game, \"0\" = clients spawn as players immediately or are kicked after g_maxplayers_spectator_blocktime if that's not possible (NOTE: incompatible with spec-based features such as sv_maxidle_playertospectator and g_balance_teams_queue)" +set sv_spectate 1 "\"1\" = clients are allowed to spectate or observe the game, \"2\" = clients are restricted to observing only during the match (spectating is allowed during warmup), \"0\" = clients spawn as players immediately or are kicked after g_maxplayers_spectator_blocktime if that's not possible (NOTE: \"0\" is incompatible with features based on spectating or observing, such as sv_maxidle_playertospectator and g_balance_teams_queue)" set sv_defaultcharacter 0 "master switch, if \"1\" the further configuration for replacing all player models, skins and colors is taken from the sv_defaultplayermodel, sv_defaultplayerskin, and sv_defaultplayercolors variables" set sv_defaultcharacterskin 0 "if \"1\", the further configuration for replacing all skins is taken from the sv_defaultplayerskin variables" set sv_defaultplayermodel "models/player/erebus.iqm" "default model selection, only works if sv_defaultcharacter is \"1\"; you may append a : suffix to model names; you can specify multiple, separated by space, and a random one will be chosen"