// ** ** //
// ********************************************** //
-// MSG_ANNCE notifications (count = 89):
+// MSG_ANNCE notifications (count = 90):
seta notification_ANNCE_ACHIEVEMENT_AIRSHOT "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_AMAZING "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_ANNCE_ACHIEVEMENT_AWESOME "1" "0 = disabled, 1 = enabled if gentle mode is off, 2 = always enabled"
seta notification_INFO_LMS_NOLIVES "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_MINIGAME_INVITE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_MONSTERS_DISABLED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
+seta notification_INFO_MOVETOSPEC_IDLING "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_NEXBALL_RETURN_HELD "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ONSLAUGHT_CAPTURE "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_ONSLAUGHT_CAPTURE_NONAME "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_WEAPON_VAPORIZER_MURDER "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
seta notification_INFO_WEAPON_VORTEX_MURDER "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
-// MSG_CENTER notifications (count = 240):
+// MSG_CENTER notifications (count = 241):
seta notification_CENTER_ALONE "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ASSAULT_ATTACKING "1" "0 = off, 1 = centerprint"
seta notification_CENTER_ASSAULT_DEFENDING "1" "0 = off, 1 = centerprint"
seta notification_CENTER_MISSING_PLAYERS "1" "0 = off, 1 = centerprint"
seta notification_CENTER_MISSING_TEAMS "1" "0 = off, 1 = centerprint"
seta notification_CENTER_MOTD "1" "0 = off, 1 = centerprint"
+seta notification_CENTER_MOVETOSPEC_IDLING "1" "0 = off, 1 = centerprint"
seta notification_CENTER_NADE_BONUS "1" "0 = off, 1 = centerprint"
seta notification_CENTER_NADE_THROW "1" "0 = off, 1 = centerprint"
seta notification_CENTER_NIX_COUNTDOWN "1" "0 = off, 1 = centerprint"
seta notification_show_sprees_info_newline "1" "Show attacker spree information for MSG_INFO messages on a separate line than the death notification itself"
seta notification_show_sprees_info_specialonly "1" "Don't show attacker spree information in MSG_INFO messages if it isn't an achievement"
-// Notification counts (total = 847): MSG_ANNCE = 89, MSG_INFO = 334, MSG_CENTER = 240, MSG_MULTI = 156, MSG_CHOICE = 28
+// Notification counts (total = 849): MSG_ANNCE = 90, MSG_INFO = 334, MSG_CENTER = 241, MSG_MULTI = 156, MSG_CHOICE = 28
MSG_INFO_NOTIF(QUIT_DISCONNECT, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 disconnected"), "")
MSG_INFO_NOTIF(QUIT_KICK_IDLING, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for idling"), "")
+ MSG_INFO_NOTIF(MOVETOSPEC_IDLING, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 was moved to spectator for idling"), "")
MSG_INFO_NOTIF(QUIT_KICK_SPECTATING, N_CONSOLE, 0, 0, "", "", "", _("^F2You were kicked from the server because you are a spectator and spectators aren't allowed at the moment."), "")
MSG_INFO_NOTIF(QUIT_KICK_TEAMKILL, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 was kicked for excessive teamkilling"), "")
MSG_INFO_NOTIF(QUIT_SPECTATE, N_CHATCON, 1, 0, "s1", "", "", _("^BG%s^F3 is now spectating"), "")
MSG_CENTER_NOTIF(DEATH_TEAMKILL_FRAGGED, N_ENABLE, 1, 0, "s1", CPID_Null, "0 0", _("^K1You were fragged by ^BG%s^K1, a team mate"), _("^K1You were scored against by ^BG%s^K1, a team mate"))
MSG_CENTER_NOTIF(DISCONNECT_IDLING, N_ENABLE, 0, 1, "", CPID_IDLING, "1 f1", _("^K1Stop idling!\n^BGDisconnecting in ^COUNT..."), "")
+ MSG_CENTER_NOTIF(MOVETOSPEC_IDLING, N_ENABLE, 0, 1, "", CPID_IDLING, "1 f1", _("^K1Stop idling!\n^BGMoving to spectator in ^COUNT..."), "")
MSG_CENTER_NOTIF(DOOR_LOCKED_NEED, N_ENABLE, 1, 0, "s1", CPID_Null, "0 0", _("^BGYou need %s^BG!"), "")
MSG_CENTER_NOTIF(DOOR_LOCKED_ALSONEED, N_ENABLE, 1, 0, "s1", CPID_Null, "0 0", _("^BGYou also need %s^BG!"), "")
{
int buttons = PHYS_INPUT_BUTTON_MASK(this);
anticheat_physics(this);
- if (autocvar_sv_maxidle > 0) {
+ if (autocvar_sv_maxidle > 0 || autocvar_sv_maxidle_playertospectator > 0) {
if (buttons != CS(this).buttons_old
|| CS(this).movement != CS(this).movement_old
|| this.v_angle != CS(this).v_angle_old) { CS(this).parm_idlesince = time; }
if (IS_PLAYER(this))
{
+ if (autocvar_sv_maxidle_playertospectator > 0 && CS(this).idlekick_lasttimeleft)
+ {
+ Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_IDLING);
+ CS(this).idlekick_lasttimeleft = 0;
+ CS(this).parm_idlesince = time;
+ }
+
if(GetResource(this, RES_HEALTH) >= 1)
{
// despawn effect
{
Player_Physics(this);
- if (autocvar_sv_maxidle > 0)
+ if (autocvar_sv_maxidle > 0 || (IS_PLAYER(this) && autocvar_sv_maxidle_playertospectator > 0))
if (frametime) // WORKAROUND: only use dropclient in server frames (frametime set). Never use it in cl_movement frames (frametime zero).
if (IS_REAL_CLIENT(this))
if (IS_PLAYER(this) || autocvar_sv_maxidle_spectatorsareidle)
{
int totalClients = 0;
- if(autocvar_sv_maxidle_slots > 0)
+ if(autocvar_sv_maxidle > 0 && autocvar_sv_maxidle_slots > 0)
{
FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_maxidle_slots_countbots,
{
});
}
- if (autocvar_sv_maxidle_slots > 0 && (maxclients - totalClients) > autocvar_sv_maxidle_slots)
+ if (autocvar_sv_maxidle > 0 && autocvar_sv_maxidle_slots > 0 && (maxclients - totalClients) > autocvar_sv_maxidle_slots)
{ /* do nothing */ }
else if (time - CS(this).parm_idlesince < 1) // instead of (time == this.parm_idlesince) to support sv_maxidle <= 10
{
}
else
{
- float timeleft = ceil(autocvar_sv_maxidle - (time - CS(this).parm_idlesince));
- if (timeleft == min(10, autocvar_sv_maxidle - 1)) { // - 1 to support sv_maxidle <= 10
+ float maxidle_time = autocvar_sv_maxidle;
+ if (IS_PLAYER(this) && autocvar_sv_maxidle_playertospectator > 0)
+ maxidle_time = autocvar_sv_maxidle_playertospectator;
+ float timeleft = ceil(maxidle_time - (time - CS(this).parm_idlesince));
+ if (timeleft == min(10, maxidle_time - 1)) { // - 1 to support maxidle_time <= 10
if (!CS(this).idlekick_lasttimeleft)
- Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
+ {
+ if (IS_PLAYER(this) && autocvar_sv_maxidle_playertospectator > 0)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MOVETOSPEC_IDLING, timeleft);
+ else
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_DISCONNECT_IDLING, timeleft);
+ }
}
if (timeleft <= 0) {
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_IDLING, this.netname);
- dropclient(this);
+ if (IS_PLAYER(this) && autocvar_sv_maxidle_playertospectator > 0)
+ {
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_MOVETOSPEC_IDLING, this.netname);
+ if (this.caplayer)
+ this.caplayer = 0;
+ PutObserverInServer(this);
+ CS(this).parm_idlesince = time;
+ }
+ else
+ {
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_QUIT_KICK_IDLING, this.netname);
+ dropclient(this);
+ }
return;
}
else if (timeleft <= 10) {
string autocvar_g_mutatormsg;
float autocvar_sv_foginterval;
float autocvar_sv_maxidle;
+float autocvar_sv_maxidle_playertospectator;
bool autocvar_sv_maxidle_spectatorsareidle;
int autocvar_sv_maxidle_slots;
bool autocvar_sv_maxidle_slots_countbots;
set sv_maxidle_slots 0 "when not 0, only kick idlers when this many or less player slots are available"
set sv_maxidle_slots_countbots 1 "count bots as player slots"
+set sv_maxidle_playertospectator 0 "move players idle for more than this amount of time in seconds to spectators (sv_maxidle timer starts again after sv_maxidle_playertospectator has moved a player to spectators)"
+
sv_allowdownloads_inarchive 1 // for csprogs.dat
sv_allowdownloads 0 // download protocol is evil