set g_ca 0 "Clan Arena: Played in rounds, once you're dead you're out! The team with survivors wins the round"
set g_ca_point_limit -1 "Clan Arena point limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
set g_ca_point_leadlimit -1 "Clan Arena point lead limit overriding the mapinfo specified one (use 0 to play without limit, and -1 to use the mapinfo's limit)"
-set g_ca_spectate_enemies 0 "allow eliminated players to spectate enemy players during Clan Arena games"
+set g_ca_spectate_enemies 0 "allow eliminated players to spectate enemy players during Clan Arena games. -1 blocks freeroam camera. Changes to this cvar take effect from the next round"
set g_ca_warmup 10 "time players get to run around before the round starts"
set g_ca_damage2score 100 "every this amount of damage done give players 1 point"
set g_ca_round_timelimit 180 "round time limit in seconds"
case 1:
if(spectatee_status == -1)
s = sprintf(_("^1Use ^3%s^1 or ^3%s^1 to change the speed"), getcommandkey(_("next weapon"), "weapnext"), getcommandkey(_("previous weapon"), "weapprev"));
- else
+ else if(!observe_blocked)
s = sprintf(_("^1Press ^3%s^1 to observe, ^3%s^1 to change camera mode"), getcommandkey(_("secondary fire"), "+fire2"), getcommandkey(_("drop weapon"), "dropweapon"));
+ else
+ s = sprintf(_("^1Press ^3%s^1 to change camera mode"), getcommandkey(_("drop weapon"), "dropweapon"));
break;
case 2:
s = sprintf(_("^1Press ^3%s^1 for gamemode info"), getcommandkey(_("server info"), "+show_info"));
newspectatee_status = 0;
spectatorbutton_zoom = (f & BIT(2));
+ observe_blocked = (f & BIT(3));
if(f & BIT(4))
{
bool button_zoom;
bool spectatorbutton_zoom;
+bool observe_blocked;
bool button_attack2;
float current_viewzoom;
#include "sv_clanarena.qh"
float autocvar_g_ca_damage2score = 100;
-bool autocvar_g_ca_spectate_enemies;
bool autocvar_g_ca_prevent_stalemate;
float autocvar_g_ca_start_health = 200;
MUTATOR_HOOKFUNCTION(ca, reset_map_players)
{
+ g_ca_spectate_enemies = autocvar_g_ca_spectate_enemies;
+ observe_blocked_if_eliminated = (g_ca_spectate_enemies == -1);
+ // we can avoid sending observe_blocked_if_eliminated to all clients here (with ClientData_Touch)
+ // since it will get sent whenever the client spectates someone anyway
+
FOREACH_CLIENT(true, {
CS(it).killcount = 0;
if (INGAME(it) || IS_BOT_CLIENT(it))
INGAME_STATUS_CLEAR(player);
}
if (INGAME(player))
+ {
player.frags = FRAGS_PLAYER_OUT_OF_GAME;
+ player.would_spectate = observe_blocked_if_eliminated; // if blocked from observing force to spectate now
+ }
if (!warmup_stage)
eliminatedPlayers.SendFlags |= 1;
if (!INGAME(player))
entity client = M_ARGV(0, entity);
entity targ = M_ARGV(1, entity);
- if (!autocvar_g_ca_spectate_enemies && INGAME(client))
+ if (g_ca_spectate_enemies != 1 && INGAME(client))
if (DIFF_TEAM(targ, client))
return true;
}
{
entity client = M_ARGV(0, entity);
- if (!autocvar_g_ca_spectate_enemies && INGAME(client)
+ if (g_ca_spectate_enemies != 1 && INGAME(client)
&& Team_GetNumberOfAlivePlayers(Entity_GetTeam(client)))
{
entity targ = M_ARGV(1, entity);
entity targ = M_ARGV(1, entity);
entity first = M_ARGV(2, entity);
- if (!autocvar_g_ca_spectate_enemies && INGAME(client)
+ if (g_ca_spectate_enemies != 1 && INGAME(client)
&& Team_GetNumberOfAlivePlayers(Entity_GetTeam(client)))
{
do { targ = targ.chain; }
#include <common/mutators/base.qh>
#include <server/elimination.qh>
#include <server/round_handler.qh>
+#include <server/world.qh>
#include <server/command/sv_cmd.qh>
+int autocvar_g_ca_spectate_enemies;
int autocvar_g_ca_point_limit;
int autocvar_g_ca_point_leadlimit;
float autocvar_g_ca_round_timelimit;
int ca_teams;
bool allowed_to_spawn;
+bool g_ca_spectate_enemies; // updated on map reset
const int ST_CA_ROUNDS = 1;
});
allowed_to_spawn = true;
+ g_ca_spectate_enemies = autocvar_g_ca_spectate_enemies;
+ observe_blocked_if_eliminated = (g_ca_spectate_enemies == -1);
round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, CA_RoundStart);
round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
EliminatedPlayers_Init(ca_isEliminated);
if (CS(e).race_completed) sf |= BIT(0); // forced scoreboard
if (CS(to).spectatee_status) sf |= BIT(1); // spectator ent number follows
if (CS(e).zoomstate) sf |= BIT(2); // zoomed
+ if (observe_blocked_if_eliminated && INGAME(to))
+ sf |= BIT(3); // observing blocked
if (autocvar_sv_showspectators == 1 || (autocvar_sv_showspectators && IS_SPEC(to)))
sf |= BIT(4); // show spectators
}
CS(this).impulse = 0;
} else if(PHYS_INPUT_BUTTON_ATCK2(this)) {
- this.would_spectate = false;
- this.flags &= ~FL_JUMPRELEASED;
- TRANSMUTE(Observer, this);
- PutClientInServer(this);
+ if(!observe_blocked_if_eliminated || !INGAME(this)) {
+ this.would_spectate = false;
+ this.flags &= ~FL_JUMPRELEASED;
+ TRANSMUTE(Observer, this);
+ PutClientInServer(this);
+ }
} else if(!SpectateUpdate(this) && !SpectateNext(this)) {
PutObserverInServer(this, false, true);
this.would_spectate = true;
IntrusiveList g_moveables;
STATIC_INIT(g_moveables) { g_moveables = IL_NEW(); }
+
+bool observe_blocked_if_eliminated = false; // forbids eliminated players from observing
sv_showspectators 0
sv_taunt 0
sv_maxidle_playertospectator 0
+g_ca_spectate_enemies -1 // block freeroam camera in CA matches