#include <server/scores.qh>
#include <server/teamplay.qh>
#include <server/weapons/accuracy.qh>
+#include <server/weapons/selection.qh>
#include <server/world.qh>
// =============================================
Nagger_VoteCountChanged();
// add up all the votes from each connected client
- FOREACH_CLIENT(IS_REAL_CLIENT(it) || autocvar_sv_vote_debug, {
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_CLIENT(it), {
+ // z411
+ if(vote_target_type == VOTE_TARGET_TEAM && it.team != vote_caller.team) continue;
+ if(vote_target_type == VOTE_TARGET_SINGLE && it != vote_target) continue;
+
++vote_player_count;
if (IS_PLAYER(it) || INGAME(it)) ++vote_real_player_count;
switch (it.vote_selection)
if (round_handler_IsActive())
round_handler_Reset(game_starttime);
}
+
+ // for RJZ
+ if (autocvar_rjz_count_shards) {
+ total_shards = 0;
+ send_TotalShardsAll();
+ }
if (shuffleteams_on_reset_map)
{
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);
+ }
});
}
}
if(!is_fake_round_start && !warmup_stage)
localcmd("\nsv_hook_warmupend\n");
- // reset the .ready status of all clients (including spectators and bots)
- FOREACH_CLIENT(true, { it.ready = false; });
+ // reset the .ready status of all players (also spectators)
+ FOREACH_CLIENT(IS_REAL_CLIENT(it), {
+ it.ready = false;
+ Kill_Notification(NOTIF_ONE_ONLY, it, MSG_CENTER, CPID_MISSING_READY);
+ });
readycount = 0;
Nagger_ReadyCounted(); // NOTE: this causes a resend of that entity, and will also turn off warmup state on the client
FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), { CS(it).allowed_timeouts = autocvar_sv_timeout_number; });
}
+ round_handler_Activate(!warmup_stage);
if (!sv_ready_restart_after_countdown || warmup_stage)
reset_map(is_fake_round_start);
void ReadyRestart(bool forceWarmupEnd)
{
- if (MUTATOR_CALLHOOK(ReadyRestart_Deny) || intermission_running || race_completing)
+ if (MUTATOR_CALLHOOK(ReadyRestart_Deny))
{
// NOTE: ReadyRestart support is mandatory in campaign
if (autocvar_g_campaign)
error("ReadyRestart must be supported in campaign mode!");
localcmd("restart\n"); // if ReadyRestart is denied, restart the server
}
- else localcmd("\nsv_hook_readyrestart\n");
+ else if (intermission_running || race_completing) // game is over, ReadyRestart no longer available
+ localcmd("restart\n");
+ else
+ localcmd("\nsv_hook_readyrestart\n");
if(forceWarmupEnd || autocvar_g_campaign)
warmup_stage = 0; // forcefully end warmup and go to match stage
game_starttime = time;
Send_Notification(NOTIF_ALL, NULL, MSG_MULTI, COUNTDOWN_STOP, minplayers);
if (!sv_ready_restart_after_countdown) // if we ran reset_map() at start of countdown
- FOREACH_CLIENT(IS_PLAYER(it), { GiveWarmupResources(it); });
+ FOREACH_CLIENT(IS_PLAYER(it), { ResetPlayerResources(it); });
}
if (warmup_limit > 0)
warmup_limit = -1;
case MUT_VOTEPARSE_UNACCEPTABLE: { return 0; }
}
+ vote_target_type = VOTE_TARGET_ALL;
+
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
{
if (first_command == "kickban")
command_arguments = strcat(ftos(autocvar_g_ban_default_bantime), " ", ftos(autocvar_g_ban_default_masksize), " ~");
- vote_parsed_command = strcat(first_command, " # ", ftos(etof(victim)), " ", command_arguments);
+ if (first_command == "kick") // z411 : Use our kick implementation - kind of hacky...
+ vote_parsed_command = strcat("defer 2 \"sv_cmd kickkick # ", ftos(etof(victim)), " ", command_arguments, "\"");
+ else
+ vote_parsed_command = strcat("defer 2 \"", first_command, " # ", ftos(etof(victim)), " ", command_arguments, "\"");
+
vote_parsed_display = sprintf("^1%s #%d ^7%s^1 %s", first_command, etof(victim), victim.netname, reason);
}
else
{
vote_command = ValidateMap(argv(startpos + 1), caller);
if (!vote_command) return -1;
- vote_parsed_command = strcat("gotomap ", vote_command);
- vote_parsed_display = strzone(strcat("^1", vote_parsed_command));
+ vote_parsed_command = strcat("defer 2 \"gotomap ", vote_command, "\"");
+ vote_parsed_display = strzone(strcat("^1gotomap ", vote_command));
break;
}
+
+ // z411 team calls
+ case "teamname":
+ {
+ if (teamplay && Team_IsValidTeam(caller.team)) {
+ vote_target_type = VOTE_TARGET_TEAM;
+
+ string tmname = strtolower(Static_Team_ColorName(caller.team));
+ string newname = argv(startpos + 1);
+
+ vote_parsed_command = strcat(first_command, " ", tmname, " \"", newname, "\"");
+ vote_parsed_display = strzone(strcat("^3(Team) ^1", first_command, " ^2", newname));
+ } else { print_to(caller, "vcall: Not in a team\n"); return 0; }
+
+ break;
+ }
// TODO: replicate the old behaviour of being able to vote for maps from different modes on multimode servers (possibly support it in gotomap too)
// maybe fallback instead of aborting if map name is invalid?
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));
break;
}
- case "restart":
+ case "gg":
+ case "shuffleteams":
+ case "endmatch":
{
// add a delay so that vote result can be seen and announcer can be heard
// if the vote is accepted
- vote_parsed_command = strcat("defer 1 ", vote_command);
+ vote_parsed_command = strcat("defer 2 ", vote_command);
+ vote_parsed_display = strzone(strcat("^1", vote_command));
+
+ break;
+ }
+
+ case "reset":
+ case "restart": // re-direct all match restarting to resetmatch
+ vote_command = "resetmatch"; // fall-through
+ case "resetmatch":
+ {
+ vote_parsed_command = strcat("defer 2 ", vote_command);
vote_parsed_display = strzone(strcat("^1", vote_command));
break;
return -1;
}
- vote_parsed_command = vote_command;
+ vote_parsed_command = strcat("defer 2 ", vote_command);
vote_parsed_display = strzone(strcat("^1", vote_command));
break;
}