Refined default values for mouse `sensitivity` (halved from 6 to 3) and `mastervolume` (9.0 to 7.0).
See merge request xonotic/xonotic-data.pk3dir!1192
-Sat 03 Jun 2023 07:22:57 AM CEST
+Sun 11 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 ""
+msgstr "Quotiens venatus est (Superstites)"
#: qcsrc/client/hud/panel/scoreboard.qc:144
msgid "SCO^hunts"
-msgstr ""
+msgstr "venatus"
#: qcsrc/client/hud/panel/scoreboard.qc:145
msgid "Number of keys carrier kills"
#: qcsrc/client/hud/panel/scoreboard.qc:164
msgid "Number of rounds played"
-msgstr ""
+msgstr "Quot temporibus lusit"
#: qcsrc/client/hud/panel/scoreboard.qc:164
msgid "SCO^rounds played"
-msgstr ""
+msgstr "quot lusit"
#: qcsrc/client/hud/panel/scoreboard.qc:165
msgid "SCO^score"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "Number of survivals"
-msgstr ""
+msgstr "Quotiens superstes fuit"
#: qcsrc/client/hud/panel/scoreboard.qc:168
msgid "SCO^survivals"
-msgstr ""
+msgstr "superstes"
#: qcsrc/client/hud/panel/scoreboard.qc:169
msgid "Number of domination points taken (Domination)"
#: qcsrc/common/gamemodes/gamemode/survival/cl_survival.qc:16
msgid "Hunter"
-msgstr ""
+msgstr "Venator"
#: qcsrc/common/gamemodes/gamemode/survival/cl_survival.qc:22
msgid "Survivor"
-msgstr ""
+msgstr "Superstes"
#: qcsrc/common/gamemodes/gamemode/survival/survival.qh:12
msgid "Identify and eliminate all the hunters before all your allies are gone"
msgstr ""
+"Supertites et venatores discerne, posteriores occide, ne omnes collegae tui "
+"moriantur"
#: qcsrc/common/gamemodes/gamemode/survival/survival.qh:12
msgid "Survival"
-msgstr ""
+msgstr "Supertites"
#: qcsrc/common/gamemodes/gamemode/tdm/tdm.qh:9
msgid "Help your team score the most frags against the enemy team"
#: qcsrc/common/gamemodes/gamemode/tka/tka.qh:13
msgid "Keep the ball in your team's possession to get points for kills"
-msgstr ""
+msgstr "Age ut manus tua pilam teneat, ut rationi addetur cum interficies"
#: qcsrc/common/gamemodes/gamemode/tka/tka.qh:13
msgid "Team Keepaway"
-msgstr ""
+msgstr "Manuum Abhibitio"
#: qcsrc/common/gamemodes/gamemode/tmayhem/tmayhem.qh:10
msgid ""
#: qcsrc/common/notifications/all.inc:234
msgid "^F4NOTE: ^BGChat is currently disabled on this server"
-msgstr ""
+msgstr "^F4NOTA: ^BGLocutorium hoc moderatro nunc vetatur"
#: qcsrc/common/notifications/all.inc:235
msgid "^F4NOTE: ^BGSpectator chat is not sent to players during the match"
#: qcsrc/common/notifications/all.inc:236
msgid "^F4NOTE: ^BGPrivate chat is currently disabled on this server"
-msgstr ""
+msgstr "^F4NOTA: ^BGLocutorium privatum hoc moderatro nunc vetatur"
#: qcsrc/common/notifications/all.inc:237
msgid "^F4NOTE: ^BGSpectator chat is currently disabled on this server"
-msgstr ""
+msgstr "^F4NOTA: ^BGSpectatorum locutorium hoc moderatro nunc vetatur"
#: qcsrc/common/notifications/all.inc:238
msgid "^F4NOTE: ^BGTeam chat is currently disabled on this server"
-msgstr ""
+msgstr "^F4NOTA: ^BGManus locutorium hoc moderatro nunc vetatur"
#: qcsrc/common/notifications/all.inc:240
#, c-format
#: qcsrc/common/notifications/all.inc:429
#, c-format
msgid "^BG%s^F3 was forced to spectate for excessive teamkilling"
-msgstr ""
+msgstr "^BG%s^F3 spectare debet quia manus collegas nimis interficiebat"
#: qcsrc/common/notifications/all.inc:430
#, c-format
#: qcsrc/common/notifications/all.inc:450
#: qcsrc/common/notifications/all.inc:789
msgid "^K1Hunters^BG win the round"
-msgstr ""
+msgstr "^K1Venatores^BG tempore vincunt"
#: qcsrc/common/notifications/all.inc:451
#: qcsrc/common/notifications/all.inc:791
msgid "^F1Survivors^BG win the round"
-msgstr ""
+msgstr "^F1Superstites^BG tempore vincunt"
#: qcsrc/common/notifications/all.inc:453
msgid "^BGYou cannot change to a larger team"
#, c-format
msgid ""
"^BG%s^K1 blew themself up with their Overkill Rocket Propelled Chainsaw%s%s"
-msgstr ""
+msgstr "^BG%s^K1 Missilium Pellentium Serra Immoderata sua se rupit%s%s"
#: qcsrc/common/notifications/all.inc:507
#, c-format
#: qcsrc/common/notifications/all.inc:519
#, c-format
msgid "^BG%s^K1 is now thinking with portals%s%s"
-msgstr ""
+msgstr "^BG%s^K1 cum teleportis nunc cogitat%s%s"
#: qcsrc/common/notifications/all.inc:520
#, c-format
"^K1You aren't allowed to play because you are banned in this server, but you "
"can play minigames"
msgstr ""
+"^K1Te ludere vetatur quia hoc moderatro expulsus es, sed ludos parvos ludere "
+"potes"
#: qcsrc/common/notifications/all.inc:720
msgid "^BGYou picked up the ball"
#: qcsrc/common/notifications/all.inc:721
msgid "^BGGet the ball to score points for frags!"
-msgstr ""
+msgstr "^BGPilam cape ut rationi addetur cum interficies!"
#: qcsrc/common/notifications/all.inc:723
msgid ""
msgid ""
"^K1You are forced to spectate and you aren't allowed to play because you are "
"banned in this server"
-msgstr ""
+msgstr "^K1Spectare debes et te ludere vetatur quia hoc moderatro expulsus es"
#: qcsrc/common/notifications/all.inc:778
msgid "^F2The race is over, finish your lap!"
msgid ""
"^BGYou are a ^K1hunter^BG! Eliminate the survivor(s) without raising "
"suspicion!"
-msgstr ""
+msgstr "^BGEs ^K1venator^BG! Superstites occide, age ut ei non suspicentur!"
#: qcsrc/common/notifications/all.inc:790
msgid "^BGYou are a ^F1survivor^BG! Identify and eliminate the hunter(s)!"
-msgstr ""
+msgstr "^BGEs ^F1superstes^BG! Venatores discerne et occide!"
#: qcsrc/common/notifications/all.inc:793
msgid "^K1Changing to ^TC^TT^K1 in ^COUNT"
#: qcsrc/common/notifications/all.inc:809
msgid ""
"^K1You aren't allowed to call a vote because you are banned in this server"
-msgstr ""
+msgstr "^K1Te suffragia diribere vetatur quia hoc moderatro expulsus es"
#: qcsrc/common/notifications/all.inc:810
msgid "^K1You aren't allowed to vote because you are banned in this server"
-msgstr ""
+msgstr "^K1Suffragio privaris quia hoc moderatro expulsus es"
#: qcsrc/common/notifications/all.qh:420 qcsrc/common/notifications/all.qh:421
#, c-format
#: qcsrc/menu/xonotic/credits.qc:180
msgid "Chinese (Hong Kong)"
-msgstr ""
+msgstr "Sinica (Hong Cong)"
#: qcsrc/menu/xonotic/credits.qc:193
msgid "Chinese (Taiwan)"
#: qcsrc/menu/xonotic/credits.qc:275
msgid "Indonesian"
-msgstr ""
+msgstr "Indonesica"
#: qcsrc/menu/xonotic/credits.qc:280
msgid "Irish"
#: qcsrc/menu/xonotic/credits.qc:307
msgid "Latin"
-msgstr ""
+msgstr "Latina"
#: qcsrc/menu/xonotic/credits.qc:310
msgid "Polish"
#: 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"
fr "French" "Français" 100%
ga "Irish" "Irish" 29%
it "Italian" "Italiano" 100%
-la "Latin" "Lingua Latina" 62%
+la "Latin" "Lingua Latina" 63%
hu "Hungarian" "Magyar" 43%
nl "Dutch" "Nederlands" 61%
pl "Polish" "Polski" 79%
// 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" \
}
else if(!teamplay)
{
- int f = entcs_GetClientColors(pl.sv_entnum);
+ int f;
+ // NOTE: always adding 1024 allows saving the colormap 0 as a value != 0
+ if (playerslots[pl.sv_entnum].colormap >= 1024)
+ f = playerslots[pl.sv_entnum].colormap - 1024; // override server-side player colors
+ else
+ f = entcs_GetClientColors(pl.sv_entnum);
+
{
sbt_field_icon0 = "gfx/scoreboard/playercolor_base";
sbt_field_icon1 = "gfx/scoreboard/playercolor_shirt";
{ WriteByte(chan, ent.sv_solid); },
{ ent.sv_solid = ReadByte(); })
-// gamemode specific player survival status (independent of score and frags)
-ENTCS_PROP(SURVIVAL_STATUS, true, survival_status, survival_status, ENTCS_SET_NORMAL,
- { WriteShort(chan, ent.survival_status); },
- { ent.survival_status = ReadShort(); })
-
#ifdef SVQC
int ENTCS_PUBLICMASK = 0, ENTCS_PRIVATEMASK = 0;
Send_Notification(NOTIF_ONE_ONLY, player, MSG_INFO, INFO_CA_JOIN_LATE);
}
}
+
+ if (!warmup_stage)
+ eliminatedPlayers.SendFlags |= 1;
}
MUTATOR_HOOKFUNCTION(ca, reset_map_players)
return true;
}
+MUTATOR_HOOKFUNCTION(ft, PutClientInServer)
+{
+ eliminatedPlayers.SendFlags |= 1;
+}
+
MUTATOR_HOOKFUNCTION(ft, reset_map_players)
{
FOREACH_CLIENT(IS_PLAYER(it), {
#include <client/draw.qh>
#include <client/hud/panel/modicons.qh>
+NET_HANDLE(ENT_CLIENT_SURVIVALSTATUSES, bool isnew)
+{
+ make_pure(this);
+ int sf = 0;
+ serialize(byte, 0, sf);
+ if (sf & BIT(1)) // make all players survivors
+ {
+ for (int j = 0; j < maxclients; ++j)
+ if (playerslots[j])
+ playerslots[j].survival_status = SURV_STATUS_PREY;
+ }
+ if (sf & BIT(0)) // reveal hunters (to hunters)
+ {
+ for (int i = 1; i <= maxclients; i += 8)
+ {
+ int f = 0;
+ serialize(byte, 0, f);
+ for (int b = 0; b < 8; ++b)
+ {
+ if (!(f & BIT(b))) continue;
+ int j = i - 1 + b;
+ if (playerslots[j])
+ playerslots[j].survival_status = SURV_STATUS_HUNTER;
+ }
+ }
+ }
+
+ // we could check STAT(GAME_STOPPED) instead of this dedicated flag,
+ // unfortunately STAT(GAME_STOPPED) is still false right when we receive this
+ bool reveal_hunters_to_survivors = (sf & BIT(2)); // when a round ends
+
+ int mystatus = playerslots[player_localnum].survival_status;
+ for (int i = 1; i <= maxclients; ++i)
+ {
+ entity e = playerslots[i - 1];
+ if (!e) continue;
+
+ int plcolor = SURV_COLOR_PREY;
+ if(e.survival_status == SURV_STATUS_HUNTER && (mystatus == SURV_STATUS_HUNTER || reveal_hunters_to_survivors))
+ plcolor = SURV_COLOR_HUNTER;
+
+ e.colormap = 1024 + plcolor; // override scoreboard and player model colors
+ }
+
+ return true;
+}
+
void HUD_Mod_Survival(vector pos, vector mySize)
{
mod_active = 1; // survival should always show the mod HUD
- int mystatus = entcs_receiver(player_localnum).survival_status;
+ int mystatus = playerslots[player_localnum].survival_status;
string player_text = "";
vector player_color = '1 1 1';
//string player_icon = "";
+
+ if(STAT(GAMESTARTTIME) > time || STAT(ROUNDSTARTTIME) > time || entcs_IsSpectating(player_localnum))
+ return;
+
if(mystatus == SURV_STATUS_HUNTER)
{
player_text = _("Hunter");
player_color = '0 1 0';
//player_icon = "player_neutral";
}
- else
- {
- // if the player has no valid status, don't draw anything
- return;
- }
drawstring_aspect(pos, player_text, vec2(mySize.x, mySize.y), player_color, panel_fg_alpha, DRAWFLAG_NORMAL);
}
return false;
entity player = M_ARGV(0, entity);
- entity e = entcs_receiver(player.entnum - 1);
- int surv_status = ((e) ? e.survival_status : 0);
- int mystatus = entcs_receiver(player_localnum).survival_status;
-
- int plcolor = SURV_COLOR_PREY; // default to survivor
- if((mystatus == SURV_STATUS_HUNTER || intermission || STAT(GAME_STOPPED)) && surv_status == SURV_STATUS_HUNTER)
- plcolor = SURV_COLOR_HUNTER;
-
- player.colormap = 1024 + plcolor;
+ entity e = playerslots[player.entnum - 1];
+ if (e && e.colormap)
+ player.colormap = e.colormap;
+ else
+ player.colormap = 1024 + SURV_COLOR_PREY;
return true;
}
#include "survival.qh"
+REGISTER_NET_LINKED(ENT_CLIENT_SURVIVALSTATUSES)
void nades_Clear(entity player);
+entity survivalStatuses;
+void SurvivalStatuses_Init();
+
+void SurvivalStatuses_Send()
+{
+ // SendFlags can be set to anything != 0, SurvivalStatuses_SendEntity won't use its value
+ survivalStatuses.SendFlags = 1;
+ survivalStatuses.nextthink = 0; // clear delayed send
+}
+
+void SurvivalStatuses_Send_Delayed()
+{
+ survivalStatuses.think = SurvivalStatuses_Send;
+ survivalStatuses.nextthink = time + 0.2;
+}
+
+bool SurvivalStatuses_SendEntity(entity this, entity dest, float sendflags)
+{
+ Stream out = MSG_ENTITY;
+ WriteHeader(out, ENT_CLIENT_SURVIVALSTATUSES);
+
+ sendflags |= BIT(1); // make all players survivors
+
+ if (dest.survival_status == SURV_STATUS_HUNTER);
+ sendflags |= BIT(0); // send hunter statuses
+
+ if (round_handler_AwaitingNextRound())
+ sendflags |= (BIT(0) | BIT(2)); // send hunter statuses and reveal hunters to survivors
+
+ serialize(byte, out, sendflags);
+ if (sendflags & BIT(0)) {
+ for (int i = 1; i <= maxclients; i += 8) {
+ int f = 0;
+ entity e = edict_num(i);
+ for (int b = 0; b < 8; ++b, e = nextent(e)) {
+ bool is_hunter = (INGAME(e) && e.survival_status == SURV_STATUS_HUNTER);
+ if (is_hunter)
+ f |= BIT(b);
+ }
+ serialize(byte, out, f);
+ }
+ }
+ return true;
+}
+
+void SurvivalStatuses_Init()
+{
+ if(survivalStatuses)
+ {
+ backtrace("Can't spawn survivalStatuses again!");
+ return;
+ }
+ Net_LinkEntity(survivalStatuses = new_pure(survivalStatuses), false, 0, SurvivalStatuses_SendEntity);
+}
+
void Surv_UpdateScores(bool timed_out)
{
// give players their hard-earned kills now that the round is over
allowed_to_spawn = false;
game_stopped = true;
round_handler_Init(5, autocvar_g_survival_warmup, autocvar_g_survival_round_timelimit);
+ SurvivalStatuses_Send();
return 1;
}
allowed_to_spawn = false;
game_stopped = true;
round_handler_Init(5, autocvar_g_survival_warmup, autocvar_g_survival_round_timelimit);
+ SurvivalStatuses_Send();
FOREACH_CLIENT(true,
{
total_hunters++;
it.survival_status = SURV_STATUS_HUNTER;
});
+ SurvivalStatuses_Send();
FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
{
round_handler_Spawn(Surv_CheckPlayers, Surv_CheckWinner, Surv_RoundStart);
round_handler_Init(5, autocvar_g_survival_warmup, autocvar_g_survival_round_timelimit);
EliminatedPlayers_Init(surv_isEliminated);
+ SurvivalStatuses_Init();
}
M_ARGV(5, bool) = true; // anonymous attacker
}
-MUTATOR_HOOKFUNCTION(surv, PlayerPreThink)
-{
- entity player = M_ARGV(0, entity);
-
- if(IS_PLAYER(player) || INGAME_JOINED(player))
- {
- // update the scoreboard colour display to out the real killer at the end of the round
- // running this every frame to avoid cheats
- int plcolor = SURV_COLOR_PREY;
- if(player.survival_status == SURV_STATUS_HUNTER && game_stopped)
- plcolor = SURV_COLOR_HUNTER;
- setcolor(player, plcolor);
- }
-}
-
MUTATOR_HOOKFUNCTION(surv, PlayerSpawn)
{
entity player = M_ARGV(0, entity);
Send_Notification(NOTIF_ONE_ONLY, player, MSG_INFO, INFO_CA_JOIN_LATE);
}
}
+
+ if (!warmup_stage)
+ eliminatedPlayers.SendFlags |= 1;
+ // send statuses with a small delay to make sure a playerslot exists, otherwise
+ // personal colors for this player won't be overriden
+ // it also reduces network traffic when multiple clients join the server at once (at map start)
+ SurvivalStatuses_Send_Delayed();
}
MUTATOR_HOOKFUNCTION(surv, reset_map_players)
}
});
bot_relinkplayerlist();
+ // this will also clear scheduled SurvivalStatuses_Send set by PutClientInServer
+ SurvivalStatuses_Send();
return true;
}
// killed an ally! punishment is death
if(autocvar_g_survival_punish_teamkill && frag_attacker != frag_target && IS_PLAYER(frag_attacker) && IS_PLAYER(frag_target) && frag_attacker.survival_status == frag_target.survival_status && !ITEM_DAMAGE_NEEDKILL(frag_deathtype))
- if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted()) // don't autokill if the round hasn't
+ if(!warmup_stage && round_handler_IsActive() && round_handler_IsRoundStarted()) // don't autokill if the round hasn't started yet
Damage(frag_attacker, frag_attacker, frag_attacker, 100000, DEATH_MIRRORDAMAGE.m_id, DMG_NOWEP, frag_attacker.origin, '0 0 0');
return true;
}
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
if (ATTACK_FINISHED(actor, weaponentity) > time + actor.(weaponentity).weapon_frametime * 0.5) return false;
entity this = actor.(weaponentity);
// don't fire while changing weapon
- if (this.state != WS_READY) return false;
+ if (!actor.vehicle && this.state != WS_READY) return false;
}
return true;
}
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"