-Sat 03 Jun 2023 07:22:57 AM CEST
+Fri 09 Jun 2023 07:22:57 AM CEST
alias bans "qc_cmd_sv banlist ${* ?}"
alias muteban "qc_cmd_sv mute ${* ?}"
alias unmuteban "qc_cmd_sv unmute ${* ?}"
+alias chatban "qc_cmd_sv mute ${* ?}"
+alias unchatban "qc_cmd_sv unmute ${* ?}"
alias unvoteban "qc_cmd_sv unvoteban ${* ?}" // Remove an existing vote ban client
// other aliases for muteban, playban and voteban lists
-alias mutebans "g_muteban_list ${* ?}"
+alias mutebans "g_chatban_list ${* ?}"
+alias chatbans "g_chatban_list ${* ?}"
alias playbans "g_playban_list ${* ?}"
alias votebans "g_voteban_list ${* ?}"
#: qcsrc/client/hud/panel/scoreboard.qc:144
msgid "Number of hunts (Survival)"
-msgstr "ç\8c\8eæ\9d\80数(生存模式)"
+msgstr "ç\8b©ç\8c\8e次数(生存模式)"
#: qcsrc/client/hud/panel/scoreboard.qc:144
msgid "SCO^hunts"
-msgstr "ç\8c\8eæ\9d\80"
+msgstr "ç\8b©ç\8c\8e"
#: qcsrc/client/hud/panel/scoreboard.qc:145
msgid "Number of keys carrier kills"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "Number of survivals"
-msgstr "生还数"
+msgstr "ç\94\9fè¿\98次æ\95°"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "SCO^survivals"
#: qcsrc/client/hud/panel/scoreboard.qc:144
msgid "Number of hunts (Survival)"
-msgstr "ç\8dµæ®º數(生存模式)"
+msgstr "ç\8b©ç\8dµæ¬¡數(生存模式)"
#: qcsrc/client/hud/panel/scoreboard.qc:144
msgid "SCO^hunts"
-msgstr "ç\8dµæ®º"
+msgstr "ç\8b©ç\8dµ"
#: qcsrc/client/hud/panel/scoreboard.qc:145
msgid "Number of keys carrier kills"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "Number of survivals"
-msgstr "生還數"
+msgstr "ç\94\9fé\82\84次æ\95¸"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "SCO^survivals"
#: qcsrc/client/hud/panel/scoreboard.qc:144
msgid "Number of hunts (Survival)"
-msgstr "ç\8dµæ®º數(生存模式)"
+msgstr "ç\8b©ç\8dµæ¬¡數(生存模式)"
#: qcsrc/client/hud/panel/scoreboard.qc:144
msgid "SCO^hunts"
-msgstr "ç\8dµæ®º"
+msgstr "ç\8b©ç\8dµ"
#: qcsrc/client/hud/panel/scoreboard.qc:145
msgid "Number of keys carrier kills"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "Number of survivals"
-msgstr "生還數"
+msgstr "ç\94\9fé\82\84次æ\95¸"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "SCO^survivals"
// e.g. -teams,rc,cts,lms/kills ?+rc/kills
#define SCOREBOARD_DEFAULT_COLUMNS \
"ping pl fps name |" \
-" -teams,rc,cts,inv,lms/kills +ft,tdm,tmayhem/kills ?+rc,inv/kills" \
-" -teams,lms/deaths +ft,tdm,tmayhem/deaths" \
+" -teams,rc,cts,surv,inv,lms/kills +ft,tdm,tmayhem/kills ?+rc,inv/kills" \
+" -teams,surv,lms/deaths +ft,tdm,tmayhem/deaths" \
" +tdm/sum" \
-" -teams,lms,rc,cts,inv,ka/suicides +ft,tdm,tmayhem/suicides ?+rc,inv/suicides" \
-" -cts,dm,tdm,ka,ft,mayhem,tmayhem/frags" /* tdm already has this in "score" */ \
+" -teams,lms,rc,cts,surv,inv,ka/suicides +ft,tdm,tmayhem/suicides ?+rc,inv/suicides" \
+" -cts,dm,tdm,surv,ka,ft,mayhem,tmayhem/frags" /* tdm already has this in "score" */ \
" +tdm,ft,dom,ons,as,tmayhem/teamkills"\
-" -rc,cts,nb/dmg -rc,cts,nb/dmgtaken" \
+" -rc,cts,surv,nb/dmg -rc,cts,surv,nb/dmgtaken" \
+" +surv/survivals +surv/hunts" \
" +ctf/pickups +ctf/fckills +ctf/returns +ctf/caps +ons/takes +ons/caps" \
" +lms/lives +lms/rank" \
" +kh/kckills +kh/losses +kh/caps" \
return NULL;
}
-void part_minigame(entity player )
+void part_minigame(entity player)
{
entity minig = CS(player).active_minigame;
return "Invalid player";
if ( inviter == player )
return "You can't invite yourself";
+ if (PlayerInList(player, autocvar_g_playban_list) && autocvar_g_playban_minigames) // playban
+ return "You can't invite a banned player";
if ( CS(player).active_minigame == CS(inviter).active_minigame )
return strcat(player.netname," is already playing");
return;
}
+ if (PlayerInList(caller, autocvar_g_playban_list) && autocvar_g_playban_minigames) // playban
+ {
+ Send_Notification(NOTIF_ONE_ONLY, caller, MSG_CENTER, CENTER_JOIN_PLAYBAN);
+ sprint(caller, "You aren't allowed to play minigames because you are banned from them in this server.\n");
+ return;
+ }
+
if (request == CMD_REQUEST_COMMAND )
{
string minig_cmd = argv(1);
if (!IS_PLAYER(this) || (autocvar_g_campaign && !campaign_bots_may_start))
{
- if (IS_PLAYER(this))
- {
- .entity weaponentity = weaponentities[0];
- if(this.(weaponentity).m_weapon == WEP_Null)
- W_NextWeapon(this, 0, weaponentity);
- }
CS(this).movement = '0 0 0';
this.bot_nextthink = time + 0.5;
return;
if (time < game_starttime)
{
- .entity weaponentity = weaponentities[0];
- if(this.(weaponentity).m_weapon == WEP_Null)
- W_NextWeapon(this, 0, weaponentity);
// block the bot during the countdown to game start
CS(this).movement = '0 0 0';
return;
return false; // empty list or search, just return
// this function allows abbreviated strings!
- FOREACH_WORD(list, it == substring(tofind, 0, strlen(it)),
+ FOREACH_WORD(list, it != "" && it == substring(tofind, 0, strlen(it)),
{
return true;
});
bool PlayerInList(entity player, string list)
{
+ if (list == "")
+ return false;
return boolean(PlayerInIDList(player, list) || PlayerInIPList(player, list));
}
if (PlayerInList(this, autocvar_g_playban_list))
TRANSMUTE(Observer, this);
- if (PlayerInList(this, autocvar_g_muteban_list)) // muteban
+ if (PlayerInList(this, autocvar_g_chatban_list)) // chatban
CS(this).muted = true;
MUTATOR_CALLHOOK(ClientConnect, this);
CS(this).autojoin_checked = true;
TRANSMUTE(Player, this);
PutClientInServer(this);
+
+ .entity weaponentity = weaponentities[0];
+ if(this.(weaponentity).m_weapon == WEP_Null)
+ W_NextWeapon(this, 0, weaponentity);
+
return;
}
#include "banning.qh"
#include <common/command/_mod.qh>
+#include <common/minigames/sv_minigames.qh>
#include <common/state.qh>
#include <common/stats.qh>
#include <common/util.qh>
if (accepted > 0)
{
string theid = "";
- if(!PlayerInIPList(client, autocvar_g_muteban_list))
+ if(!PlayerInIPList(client, autocvar_g_chatban_list))
theid = cons(theid, client.netaddress);
- if(!PlayerInIDList(client, autocvar_g_muteban_list))
+ if(!PlayerInIDList(client, autocvar_g_chatban_list))
theid = cons(theid, client.crypto_idfp);
CS(client).muted = true;
LOG_INFO(strcat("Mute-banning player ", GetCallerName(client), " (", argv(1), ")."));
- cvar_set("g_muteban_list", cons(autocvar_g_muteban_list, theid));
+ cvar_set("g_chatban_list", cons(autocvar_g_chatban_list, theid));
return;
}
{
LOG_HELP("Usage:^3 sv_cmd mute <client>");
LOG_HELP(" <client> is the entity number or name of the player to mute.");
- LOG_HELP("See also: ^2unmute, g_muteban_list^7");
+ LOG_HELP("See also: ^2unmute, g_chatban_list^7");
return;
}
}
LOG_INFO(strcat("Play-banning player ", GetCallerName(client), " (", argv(1), ")."));
PutObserverInServer(client, true, true);
+ if (autocvar_g_playban_minigames)
+ part_minigame(client);
cvar_set("g_playban_list", cons(autocvar_g_playban_list, theid));
return;
if (accepted > 0)
{
string tmp_string = "";
- FOREACH_WORD(autocvar_g_muteban_list, it != client.netaddress,
+ FOREACH_WORD(autocvar_g_chatban_list, it != client.netaddress,
{
if(client.crypto_idfp && it == substring(client.crypto_idfp, 0, strlen(it)))
continue;
tmp_string = cons(tmp_string, it);
});
- cvar_set("g_muteban_list", tmp_string);
+ cvar_set("g_chatban_list", tmp_string);
LOG_INFO(strcat("Unmuting player ", GetCallerName(client), " (", original_arg, ")."));
CS(client).muted = false;
{
LOG_HELP("Usage:^3 sv_cmd unmute <client>");
LOG_HELP(" <client> is the entity number or name of the player to unmute.");
- LOG_HELP("See also: ^2mute, g_muteban_list^7");
+ LOG_HELP("See also: ^2mute, g_chatban_list^7");
return;
}
}
bool autocvar_g_ban_telluser = true;
string autocvar_g_banned_list;
bool autocvar_g_banned_list_idmode;
-string autocvar_g_muteban_list; // "List of banned players from chat"
-string autocvar_g_playban_list; // "List of banned players from playing (forced to spectate)"
-string autocvar_g_voteban_list; // "List of banned players from voting"
+string autocvar_g_chatban_list;
+string autocvar_g_playban_list;
+bool autocvar_g_playban_minigames;
+string autocvar_g_voteban_list;
#define GET_BAN_ARG(v, d) if (argc > reason_arg) { if ((v = stof(argv(reason_arg))) != 0) ++reason_arg; else v = d; } else { v = d; }
#define GET_BAN_REASON(v, d) if (argc > reason_arg) v = substring(command, argv_start_index(reason_arg), strlen(command) - argv_start_index(reason_arg)); else v = d;
else if (destination == "spectator")
{
string pl_name = playername(client.netname, client.team, false);
- if (!IS_SPEC(client) && !IS_OBSERVER(client))
+ if (!(IS_SPEC(client) || IS_OBSERVER(client)) || INGAME(client))
{
PutObserverInServer(client, true, true);
#include <server/scores.qh>
#include <server/teamplay.qh>
#include <server/weapons/accuracy.qh>
+#include <server/weapons/selection.qh>
#include <server/world.qh>
// =============================================
it.avelocity = '0 0 0';
CS(it).movement = '0 0 0';
PutClientInServer(it);
+
+ if(IS_BOT_CLIENT(it))
+ {
+ .entity weaponentity = weaponentities[0];
+ if(it.(weaponentity).m_weapon == WEP_Null)
+ W_NextWeapon(it, 0, weaponentity);
+ }
});
}
}
switch (first_command) // now go through and parse the proper commands to adjust as needed.
{
+ case "movetoauto":
+ case "movetored":
+ case "movetoblue":
+ case "movetoyellow":
+ case "movetopink":
+ case "movetospec":
+ {
+ entity victim = GetIndexedEntity(argc, (startpos + 1));
+ float accepted = VerifyClientEntity(victim, true, false);
+ if (accepted > 0)
+ {
+ vote_parsed_command = vote_command;
+ vote_parsed_display = sprintf("^1%s #%d ^7%s", first_command, etof(victim), victim.netname);
+ }
+ else
+ {
+ print_to(caller, strcat("vcall: ", GetClientErrorString(accepted, argv(startpos + 1)), ".\n"));
+ return 0;
+ }
+
+ break;
+ }
+
case "kick":
case "kickban": // catch all kick/kickban commands
{
break;
}
+ case "fraglimit": // include restrictions on the maximum votable frag limit
+ {
+ float fraglimit_vote = stof(argv(startpos + 1));
+ float fraglimit_min = 0;
+ float fraglimit_max = 999999;
+ if(fraglimit_vote > fraglimit_max || fraglimit_vote < fraglimit_min)
+ {
+ print_to(caller, strcat("Invalid fraglimit vote, accepted values are between ", ftos(fraglimit_min), " and ", ftos(fraglimit_max), "."));
+ return -1;
+ }
+ vote_parsed_command = strcat("fraglimit ", ftos(fraglimit_vote));
+ vote_parsed_display = strzone(strcat("^1", vote_parsed_command));
+
+ break;
+ }
+
case "timelimit": // include restrictions on the maximum votable time limit
{
float timelimit_vote = stof(argv(startpos + 1));
print_to(caller, strcat("Invalid timelimit vote, accepted values are between ", ftos(autocvar_timelimit_min), " and ", ftos(autocvar_timelimit_max), "."));
return -1;
}
- timelimit_vote = bound(autocvar_timelimit_min, timelimit_vote, autocvar_timelimit_max);
vote_parsed_command = strcat("timelimit ", ftos(timelimit_vote));
vote_parsed_display = strzone(strcat("^1", vote_parsed_command));
if (MUTATOR_CALLHOOK(ClientObituary, inflictor, attacker, targ, deathtype, attacker.(weaponentity))) { CS(targ).killcount = 0; return; }
notif_anonymous = M_ARGV(5, bool);
+ // TODO: Replace "???" with a translatable "Anonymous player" string
+ // https://gitlab.com/xonotic/xonotic-data.pk3dir/-/issues/2839
if(notif_anonymous)
- attacker_name = "Anonymous player";
+ attacker_name = "???";
#ifdef NOTIFICATIONS_DEBUG
Debug_Notification(
return true;
}
if (complain)
+ if(IS_REAL_CLIENT(this))
{
// DRESK - 3/16/07
// Report Proper Weapon Status / Modified Weapon Ownership Message
BADCVAR("timeformat");
BADCVAR("timestamps");
BADCVAR("g_require_stats");
- BADCVAR("g_muteban_list");
+ BADCVAR("g_chatban_list");
BADCVAR("g_playban_list");
+ BADCVAR("g_playban_minigames");
BADCVAR("g_voteban_list");
BADPREFIX("developer_");
BADPREFIX("g_ban_");
nopicmip
{
map models/relics/sign_invisible
- blendfunc add
+ blendfunc blend
}
}
nopicmip
{
map models/relics/sign_speed
- blendfunc add
+ blendfunc blend
}
}
set sv_itemstime 1 "enable networking of time left until respawn for items such as mega health/armor and powerups"
// bans
-set g_ban_default_bantime 5400 "90 minutes"
+set g_ban_default_bantime 5400 "default ban time in seconds"
set g_ban_default_masksize 3 "masksize 0 means banning by UID only, 1 means banning by /8 (IPv6: /32) network, 2 means banning by /16 (IPv6: /48) network, 3 means banning by /24 (IPv6: /56) network, 4 means banning by single IP (IPv6: /64 network)"
set g_ban_sync_uri "" "sync using this ban list provider (empty string to disable)"
-set g_ban_sync_interval 5 "sync every 5 minutes"
-set g_ban_sync_trusted_servers "" "request ban lists from these xonotic servers (do not include your own server there, or unbanning may fail)"
+set g_ban_sync_interval 5 "sync interval in minutes"
+set g_ban_sync_trusted_servers "" "request ban lists from these Xonotic servers (do not include your own server there, or unbanning may fail)"
set g_ban_sync_timeout 45 "time out in seconds for the ban sync requests"
-set g_ban_sync_trusted_servers_verify 0 "when set to 1, additional bans sent by the servers are ignored, and only bans for the requested IP are used"
-set g_ban_telluser 1 "notify the banned player about it when they try to join"
-set g_banned_list "" "format: IP remainingtime IP remainingtime ..."
+set g_ban_sync_trusted_servers_verify 0 "ignore additional bans sent by the servers, and use only bans for the requested IP"
+set g_ban_telluser 1 "notify the banned player they are banned when they try to join"
+set g_banned_list "" "list of banned players; player format: IP remainingtime"
set g_banned_list_idmode "1" "when set, the IP banning system always uses the ID over the IP address (so a user in a banned IP range can connect if they have a valid signed ID)"
-set g_muteban_list "" "list of banned players from chat, format: IP playerkey ..."
-set g_playban_list "" "list of banned players from playing (forced to spectate), format: IP playerkey ..."
-set g_voteban_list "" "list of banned players from voting, format: IP playerkey ..."
+set g_chatban_list "" "list of banned players from chat; player format: IP or playerkey"
+set g_playban_list "" "list of banned players from playing (forced to spectate); player format: IP or playerkey"
+set g_playban_minigames 0 "disallow playbanned players (who are forced to spectate) from playing minigames"
+set g_voteban_list "" "list of banned players from voting; player format: IP or playerkey"
// useful vote aliases
set timelimit_increment 5 "number of minutes added to the timer when voting for extendmatchtime"