strcpy(prev_pl2_name, pl2_name);
// There are new duelers, update title
- float offset = stringwidth(pl2_name, true, hud_fontsize) - stringwidth(pl1_name, true, hud_fontsize) - 1;
- centerprint_SetTitle(sprintf("^BG%s^BG %s %s", pl1_name, _("vs"), pl2_name), offset / 2);
+ centerprint_SetDuelTitle(pl1_name, pl2_name, _("vs"));
}
void Announcer_ClearTitle()
{
float starttime = STAT(GAMESTARTTIME);
float roundstarttime = STAT(ROUNDSTARTTIME);
- if(roundstarttime == -1)
+ bool game_timeout = (STAT(TIMEOUT_LAST) > 0);
+
+ if(roundstarttime == -1 || game_timeout)
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_ROUNDSTOP);
delete(this);
float countdown = (inround ? roundstarttime - time : starttime - time);
float countdown_rounded = floor(0.5 + countdown);
+ if(time >= starttime) centerprint_ClearTitle();
+
if(countdown <= 0) // countdown has finished, starttime is now
{
Local_Notification(MSG_CENTER, CENTER_COUNTDOWN_BEGIN);
if (gametype.m_1v1)
Announcer_Duel();
else
- centerprint_SetTitle(strcat("^BG", MapInfo_Type_ToText(gametype)), 0); // Show game type as title
+ centerprint_SetTitle(strcat("^BG", MapInfo_Type_ToText(gametype))); // Show game type as title
if(time + 5.0 < startTime) // if connecting to server while restart was active don't always play prepareforbattle
- Local_Notification(MSG_ANNCE, ANNCE_PREPARE);
+ if(teamplay)
+ Local_Notification(MSG_ANNCE, ANNCE_PREPARE_TEAM);
+ else
+ Local_Notification(MSG_ANNCE, ANNCE_PREPARE);
}
announcer_countdown.nextthink = startTime - floor(startTime - time + 0.5); //synchronize nextthink to startTime
int centerprint_countdown_num[CENTERPRINT_MAX_MSGS];
bool centerprint_showing;
+float centerprint_medal_expire_time;
+string centerprint_medal_icon;
+float centerprint_medal_times;
+
string centerprint_title;
- float centerprint_title_offset;
+ string centerprint_title_left;
+ string centerprint_title_right;
void centerprint_Add(int new_id, string strMessage, float duration, int countdown_num)
{
}
}
- void centerprint_ClearTitle()
+void centerprint_Medal(string icon, float times)
+{
+ if(!autocvar_hud_panel_centerprint_medals) return;
+
+ //LOG_INFOF("centerprint_Medal: icon: %s times: %d", icon, times);
+ //centerprint_medal_expire_time = time + autocvar_hud_panel_centerprint_time;
+ centerprint_medal_expire_time = time + MSG_MEDAL_TIME;
+ centerprint_medal_times = times;
+ if(centerprint_medal_icon)
+ strunzone(centerprint_medal_icon);
+ centerprint_medal_icon = strzone(strcat("gfx/medal/", icon));
+
+ centerprint_showing = true;
+}
+
+ void centerprint_SetDuelTitle(string left, string right, string div)
{
- strfree(centerprint_title);
- centerprint_title_offset = 0;
+ strcpy(centerprint_title_left, left);
+ strcpy(centerprint_title_right, right);
+ centerprint_SetTitle(sprintf("^BG%s^BG %s %s", left, div, right));
}
- void centerprint_SetTitle(string title, float offset)
+ void centerprint_SetTitle(string title)
{
- if(title != centerprint_title) {
+ if(title != centerprint_title)
strcpy(centerprint_title, CCR(title));
- centerprint_title_offset = offset;
- }
+ }
+
+ void centerprint_ClearTitle()
+ {
+ strfree(centerprint_title);
+ strfree(centerprint_title_left);
+ strfree(centerprint_title_right);
}
float hud_configure_cp_generation_time;
{
if(highlightedPanel == HUD_PANEL(CENTERPRINT))
{
- centerprint_SetTitle(sprintf(_("Title at %s"), seconds_tostring(hud_configure_cp_generation_time)), 0);
+ centerprint_SetTitle(sprintf(_("Title at %s"), seconds_tostring(hud_configure_cp_generation_time)));
float r;
r = random();
bool all_messages_expired = true;
pos = panel_pos;
+
if (autocvar_hud_panel_centerprint_flip)
pos.y += panel_size.y;
align = bound(0, autocvar_hud_panel_centerprint_align, 1);
+
+ // z411 draw medals first
+ if (autocvar_hud_panel_centerprint_medals && time < centerprint_medal_expire_time) {
+ float height = vid_conheight/50 * 4;
+ pos.y -= height;
+
+ if(time < centerprint_medal_expire_time - MSG_MEDAL_FADE_TIME)
+ a = 1;
+ else
+ a = (centerprint_medal_expire_time - time) / MSG_MEDAL_FADE_TIME;
+
+ vector tmp_in = pos;
+
+ vector mysize = draw_getimagesize(centerprint_medal_icon);
+ vector newsize = vec2(height*(mysize.x/mysize.y), height);
+ vector fontsize = '1 1 0' * (newsize.y/2);
+
+ tmp_in.x += (panel_size.x - newsize.x) / 2; // center medal icon
+
+ if(centerprint_medal_times < autocvar_hud_panel_centerprint_medals_max) {
+ tmp_in.x -= ((newsize.x * 1.1) * (centerprint_medal_times - 1) / 2);
+ for(int t = 0; t < centerprint_medal_times; t++) {
+ drawpic(tmp_in, centerprint_medal_icon, newsize, '1 1 1', a, DRAWFLAG_NORMAL);
+ tmp_in.x += newsize.x * 1.1;
+ }
+ } else {
+ drawpic(tmp_in, centerprint_medal_icon, newsize, '1 1 1', a, DRAWFLAG_NORMAL);
+ tmp_in.x += newsize.x + fontsize.x * 0.25; // draw times next to it
+ tmp_in.y += (newsize.y - fontsize.y) / 2;
+ drawstring(tmp_in, ftos(centerprint_medal_times), fontsize, '1 1 1', a, DRAWFLAG_NORMAL);
+ }
+
+ pos.y += height;
+
+ all_messages_expired = false;
+ }
// Show title if available
if(centerprint_title) {
if (autocvar_hud_panel_centerprint_flip)
pos.y -= fontsize.y;
- if (centerprint_title_offset && align == 0.5)
- pos.x += centerprint_title_offset * CENTERPRINT_BASE_SIZE * autocvar_hud_panel_centerprint_fontscale_title;
+ if (centerprint_title_left != "" && align == 0.5) // Center line at the main word (for duels)
+ pos.x += (stringwidth(centerprint_title_right, true, fontsize) - stringwidth(centerprint_title_left, true, fontsize)) / 2;
drawcolorcodedstring(pos, centerprint_title, fontsize, 1, DRAWFLAG_NORMAL);
if (time < centerprint_start_time[j]) continue;
- float fade_in_time = autocvar_hud_panel_centerprint_fade_in;
+ float fade_in_time = 0;
float fade_out_time = autocvar_hud_panel_centerprint_fade_out;
if (centerprint_countdown_num[j] && centerprint_start_time[j]) {
a *= panel_fg_alpha;
// finally set the size based on the alpha
- sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
+ //sz = autocvar_hud_panel_centerprint_fade_minfontsize + a * (1 - autocvar_hud_panel_centerprint_fade_minfontsize);
+ sz = 1; // remove zoom;
drawfontscale = hud_scale * sz;
if (centerprint_countdown_num[j])
bool autocvar_hud_panel_centerprint;
float autocvar_hud_panel_centerprint_align;
-float autocvar_hud_panel_centerprint_fade_in = 0.15;
+//float autocvar_hud_panel_centerprint_fade_in = 0;
float autocvar_hud_panel_centerprint_fade_out = 0.15;
float autocvar_hud_panel_centerprint_fade_subsequent = 1;
float autocvar_hud_panel_centerprint_fade_subsequent_passone = 3;
float autocvar_hud_panel_centerprint_fade_subsequent_passone_minalpha = 0.5;
float autocvar_hud_panel_centerprint_fade_subsequent_passtwo = 10;
float autocvar_hud_panel_centerprint_fade_subsequent_passtwo_minalpha = 0.5;
-float autocvar_hud_panel_centerprint_fade_minfontsize = 1;
+//float autocvar_hud_panel_centerprint_fade_minfontsize = 1;
bool autocvar_hud_panel_centerprint_flip;
float autocvar_hud_panel_centerprint_fontscale = 1;
float autocvar_hud_panel_centerprint_fontscale_bold = 1.4;
bool autocvar_hud_panel_centerprint_dynamichud = true;
float autocvar_hud_panel_centerprint_time;
+bool autocvar_hud_panel_centerprint_medals = true;
+int autocvar_hud_panel_centerprint_medals_max = 5;
+
void centerprint_Add(int new_id, string strMessage, float duration, int countdown_num);
void centerprint_AddStandard(string strMessage);
void centerprint_Kill(int id);
void centerprint_KillAll();
+ void centerprint_SetDuelTitle(string left, string right, string div);
+ void centerprint_SetTitle(string title);
void centerprint_ClearTitle();
- void centerprint_SetTitle(string title, float offset);
+void centerprint_Medal(string icon, int times);
maxclients = i;
}
- ReplicateVars(REPLICATEVARS_SEND_ALL);
-
// needs to be done so early because of the constants they create
static_init();
static_init_late();
registercvar("cl_weapon_switch_fallback_to_impulse", "1");
registercvar("cl_allow_uidranking", "1");
+
+ // z411
+ registercvar("cl_chat_sounds", "1");
if(autocvar_cl_lockview)
cvar_set("cl_lockview", "0");
TrueAim_Init();
+ // this can't be called in CSQC_Init as it'd send cvars too early
+ ReplicateVars_Start();
+
postinit = true;
}
NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
{
make_pure(this);
+ float entnum = ReadByte();
+
int sf = ReadInt24_t();
if (sf == 0) {
for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
int f = 1;
for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
if (sf & f) {
- int b = ReadByte();
- if (b == 0)
- weapon_accuracy[w] = -1;
- else if (b == 255)
- weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
- else
- weapon_accuracy[w] = (b - 1.0) / 100.0;
+ if(entnum > 0) {
+ playerslots[entnum-1].accuracy_frags[w] = ReadByte();
+ playerslots[entnum-1].accuracy_hit[w] = ReadShort();
+ playerslots[entnum-1].accuracy_cnt_hit[w] = ReadShort();
+ playerslots[entnum-1].accuracy_cnt_fired[w] = ReadShort();
+
+ //LOG_INFOF("Duel stats ?/%d", playerslots[entnum-1].accuracy_cnt_fired[w]);
+ } else {
+ int b = ReadByte();
+ if (b == 0)
+ weapon_accuracy[w] = -1;
+ else if (b == 255)
+ weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
+ else
+ weapon_accuracy[w] = (b - 1.0) / 100.0;
+ }
}
f = (f == 0x800000) ? 1 : f * 2;
}
serverflags = ReadByte();
g_trueaim_minrange = ReadCoord();
+
+ strcpy(hostname_full, ReadString());
+ strcpy(motd_permanent, ReadString());
+
+ sv_timer_countdown = ReadByte();
return = true;
if (!postinit) PostInit();
}
+NET_HANDLE(TE_CSQC_TEAMNAMES, bool isNew)
+{
+ teamname_red = strzone(ReadString());
+ teamname_blue = strzone(ReadString());
+ teamname_yellow = strzone(ReadString());
+ teamname_pink = strzone(ReadString());
+
+ return = true;
+}
+
+NET_HANDLE(TE_CSQC_CHATSOUND, bool isNew)
+{
+ string snd = ReadString();
+ snd = strcat("chat/", snd, ".ogg");
+
+ precache_sound(snd);
+ _sound(NULL, CH_INFO, snd, VOL_BASE, ATTN_NONE);
+
+ return = true;
+}
+
float GetSpeedUnitFactor(int speed_unit)
{
switch(speed_unit)
WriteHeader(MSG_BROADCAST, TE_CSQC_TEAMNAGGER);
}
+void send_TeamNames(int channel, entity to) {
+ msg_entity = to;
+
+ WriteHeader(channel, TE_CSQC_TEAMNAMES);
+ WriteString(channel, autocvar_g_teamnames_red);
+ WriteString(channel, autocvar_g_teamnames_blue);
+ WriteString(channel, autocvar_g_teamnames_yellow);
+ WriteString(channel, autocvar_g_teamnames_pink);
+}
+
int CountSpectators(entity player, entity to)
{
if(!player) { return 0; } // not sure how, but best to be safe
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 (autocvar_sv_showspectators) sf |= BIT(4); // show spectators
+ if (autocvar_sv_showspectators == 1 || (autocvar_sv_showspectators && IS_SPEC(to)))
+ sf |= BIT(4); // show spectators
WriteHeader(MSG_ENTITY, ENT_CLIENT_CLIENTDATA);
WriteByte(MSG_ENTITY, sf);
}
else
{
- SetPlayerTeam(this, -1, TEAM_CHANGE_SPECTATOR);
+ SetPlayerTeam(this, -1, TEAM_CHANGE_SPECTATOR); // clears scores too in game modes without teams
this.frags = FRAGS_SPECTATOR;
}
if (CS(this).just_joined)
CS(this).just_joined = false;
+
+ // for RJZ
+ if (autocvar_rjz_count_shards)
+ send_TotalShards(this);
}
int player_getspecies(entity this)
setcolor(player, stof(autocvar_sv_defaultplayercolors));
}
+void ResetPlayerResources(entity this)
+{
+ if (warmup_stage) {
+ SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
+ SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
+ SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
+ SetResource(this, RES_CELLS, warmup_start_ammo_cells);
+ SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
+ SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
+ SetResource(this, RES_HEALTH, warmup_start_health);
+ SetResource(this, RES_ARMOR, warmup_start_armorvalue);
+ STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
+ } else {
+ SetResource(this, RES_SHELLS, start_ammo_shells);
+ SetResource(this, RES_BULLETS, start_ammo_nails);
+ SetResource(this, RES_ROCKETS, start_ammo_rockets);
+ SetResource(this, RES_CELLS, start_ammo_cells);
+ SetResource(this, RES_PLASMA, start_ammo_plasma);
+ SetResource(this, RES_FUEL, start_ammo_fuel);
+ SetResource(this, RES_HEALTH, start_health);
+ SetResource(this, RES_ARMOR, start_armorvalue);
+ STAT(WEAPONS, this) = start_weapons;
+ if (MUTATOR_CALLHOOK(ForbidRandomStartWeapons, this) == false)
+ {
+ GiveRandomWeapons(this, random_start_weapons_count,
+ autocvar_g_random_start_weapons, random_start_ammo);
+ }
+ }
+}
+
void PutPlayerInServer(entity this)
{
if (this.vehicle) vehicles_exit(this.vehicle, VHEF_RELEASE);
this.takedamage = DAMAGE_AIM;
this.effects = EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
- if (warmup_stage) {
- SetResource(this, RES_SHELLS, warmup_start_ammo_shells);
- SetResource(this, RES_BULLETS, warmup_start_ammo_nails);
- SetResource(this, RES_ROCKETS, warmup_start_ammo_rockets);
- SetResource(this, RES_CELLS, warmup_start_ammo_cells);
- SetResource(this, RES_PLASMA, warmup_start_ammo_plasma);
- SetResource(this, RES_FUEL, warmup_start_ammo_fuel);
- SetResource(this, RES_HEALTH, warmup_start_health);
- SetResource(this, RES_ARMOR, warmup_start_armorvalue);
- STAT(WEAPONS, this) = WARMUP_START_WEAPONS;
- } else {
- SetResource(this, RES_SHELLS, start_ammo_shells);
- SetResource(this, RES_BULLETS, start_ammo_nails);
- SetResource(this, RES_ROCKETS, start_ammo_rockets);
- SetResource(this, RES_CELLS, start_ammo_cells);
- SetResource(this, RES_PLASMA, start_ammo_plasma);
- SetResource(this, RES_FUEL, start_ammo_fuel);
- SetResource(this, RES_HEALTH, start_health);
- SetResource(this, RES_ARMOR, start_armorvalue);
- STAT(WEAPONS, this) = start_weapons;
- if (MUTATOR_CALLHOOK(ForbidRandomStartWeapons, this) == false)
- {
- GiveRandomWeapons(this, random_start_weapons_count,
- autocvar_g_random_start_weapons, random_start_ammo);
- }
- }
+ ResetPlayerResources(this);
+
SetSpectatee_status(this, 0);
PS(this).dual_weapons = '0 0 0';
Unfreeze(this, false);
MUTATOR_CALLHOOK(PlayerSpawn, this, spot);
-
{
string s = spot.target;
if(g_assault || g_race) // TODO: make targeting work in assault & race without this hack
} else if (IS_PLAYER(this)) {
PutPlayerInServer(this);
}
-
+ // send team names
+ if(teamplay && IS_REAL_CLIENT(this))
+ send_TeamNames(MSG_ONE, this);
bot_relinkplayerlist();
}
WriteByte(channel, this.cnt * 255.0); // g_balance_damagepush_speedfactor
WriteByte(channel, serverflags);
WriteCoord(channel, autocvar_g_trueaim_minrange);
+
+ // z411 send full hostname
+ WriteString(channel, (autocvar_hostname_full != "" ? autocvar_hostname_full : autocvar_hostname));
+ WriteString(channel, autocvar_sv_motd_permanent);
+
+ // z411 send client countdown type
+ WriteByte(channel, autocvar_sv_timer_countdown);
}
void ClientInit_CheckUpdate(entity this)
else
CS(this).allowed_timeouts = autocvar_sv_timeout_number;
- if (autocvar_sv_eventlog)
+ if (autocvar_sv_eventlog) {
GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? GameLog_ProcessIP(this.netaddress) : "bot"), ":", playername(this.netname, this.team, false)));
+
+ /* z411 for RJZ */
+ if(autocvar_rjz_ranks) GameLogEcho(strcat(":idfp:", ftos(etof(this)), ":", this.crypto_idfp));
+ }
CS(this).just_joined = true; // stop spamming the eventlog with additional lines when the client connects
}
void Join(entity this)
{
+ if (autocvar_g_campaign && !campaign_bots_may_start && !game_stopped && time >= game_starttime)
+ ReadyRestart(true);
+
TRANSMUTE(Player, this);
if(!this.team_selected)
else
Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname);
this.team_selected = false;
+
+ // z411
+ // send constant ready notification
+ if(warmup_stage)
+ Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_MISSING_READY);
}
int GetPlayerLimit()
return false;
}
- if (timeout_status == TIMEOUT_ACTIVE) {
- // don't allow the player to turn around while game is paused
+ if (game_timeout) {
+ // don't allow the player to turn around while game is paused
// FIXME turn this into CSQC stuff
this.v_angle = this.lastV_angle;
this.angles = this.lastV_angle;
this.fixangle = true;
+ return false;
}
if (frametime) player_powerups(this);
|| (!(autocvar_sv_spectate || autocvar_g_campaign || (Player_GetForcedTeamIndex(this) == TEAM_FORCE_SPECTATOR))
&& (!teamplay || autocvar_g_balance_teams)))
{
- campaign_bots_may_start = true;
if(joinAllowed(this))
Join(this);
return;
#include <common/stats.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
+ #include <server/campaign.qh>
#include <server/client.qh>
#include <server/command/banning.qh>
#include <server/command/common.qh>
// add up all the votes from each connected client
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)) ++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)
{
if(warmup_stage)
game_starttime = time; // Warmup: No countdown in warmup
+ else if (autocvar_g_campaign)
+ game_starttime = time + 3;
else
game_starttime = time + RESTART_COUNTDOWN; // Go into match mode
localcmd("\nsv_hook_warmupend\n");
// reset the .ready status of all players (also spectators)
- FOREACH_CLIENT(IS_REAL_CLIENT(it), { it.ready = false; });
+ 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(true, is_fake_round_start);
if (MUTATOR_CALLHOOK(ReadyRestart_Deny) || intermission_running || race_completing) localcmd("restart\n");
else localcmd("\nsv_hook_readyrestart\n");
- if(forceWarmupEnd)
+ if(forceWarmupEnd || autocvar_g_campaign)
warmup_stage = 0; // forcefully end warmup and go to match stage
else
warmup_stage = cvar("g_warmup"); // go into warmup if it's enabled, otherwise restart into match stage
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 "kick":
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 "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;
}
.int m_team_balance_state; ///< Holds the state of the team balance entity.
.entity m_team_balance_team[NUM_TEAMS]; ///< ???
+.string m_team_name; // z411 team name
.float m_team_score; ///< The score of the team.
.int m_num_players; ///< Number of players (both humans and bots) in a team.
.int m_num_bots; ///< Number of bots in a team.
return g_team_entities[Team_TeamToIndex(team_num) - 1];
}
+string Team_GetTeamName(entity team_ent)
+{
+ return team_ent.m_team_name;
+}
+
+void Team_SetTeamName(entity team_ent, string name)
+{
+ team_ent.m_team_name = name;
+}
+
float Team_GetTeamScore(entity team_ent)
{
return team_ent.m_team_score;
team_ent.m_num_players_alive = number;
}
+int Team_GetNumberOfPlayers(entity team_ent)
+{
+ return team_ent.m_num_players;
+}
+
+void Team_SetNumberOfPlayers(entity team_ent, int number)
+{
+ team_ent.m_num_players = number;
+}
+
int Team_GetWinnerAliveTeam()
{
int winner = 0;
if (team_index != old_team_index)
{
KillPlayerForTeamChange(player);
- PlayerScore_Clear(player);
+ PlayerScore_Clear(player); // works only in game modes without teams
CS(player).parm_idlesince = time;
if (!IS_BOT_CLIENT(player))
const float SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS = 1;
+void send_TotalShards(entity to) {
+ // for RJZ
+ // Send total number of picked up shards
+ if(!autocvar_rjz_count_shards) return;
+ if(!IS_REAL_CLIENT(to)) return;
+
+ msg_entity = to;
+ WriteHeader(MSG_ONE, TE_CSQC_TOTALSHARDS);
+ WriteInt24_t(MSG_ONE, total_shards);
+}
+
+void send_TotalShardsAll() {
+ // for RJZ
+ // Send total number of picked up shards
+ if(!autocvar_rjz_count_shards) return;
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && (IS_SPEC(it) || IS_OBSERVER(it)), {
+ send_TotalShards(it);
+ });
+}
+
void SetDefaultAlpha()
{
if (!MUTATOR_CALLHOOK(SetDefaultAlpha))
BADCVAR("g_keyhunt");
BADCVAR("g_keyhunt_teams");
BADCVAR("g_lms");
+ BADCVAR("g_mayhem");
BADCVAR("g_nexball");
BADCVAR("g_onslaught");
BADCVAR("g_race");
BADCVAR("g_tdm");
BADCVAR("g_tdm_on_dm_maps");
BADCVAR("g_tdm_teams");
+ BADCVAR("g_mmm");
+ BADCVAR("g_mmm_not_dm_maps");
+ BADCVAR("g_tmayhem");
+ BADCVAR("g_tmayhem_teams");
BADCVAR("g_vip");
BADCVAR("leadlimit");
BADCVAR("nextmap");
BADCVAR("g_mapinfo_ignore_warnings");
BADCVAR("g_maplist_ignore_sizes");
BADCVAR("g_maplist_sizes_count_bots");
+ //LegendGuard adds BADCVAR(g_*) for MMM 20-02-2021
// long
BADCVAR("hostname");
+ BADCVAR("hostname_full");
BADCVAR("g_maplist");
BADCVAR("g_maplist_mostrecent");
BADCVAR("sv_motd");
+ BADCVAR("sv_motd_permanent");
+
+ BADPREFIX("g_teamnames_");
v = cvar_string(k);
d = cvar_defstring(k);
BADCVAR("g_forced_respawn");
BADCVAR("g_freezetag_point_leadlimit");
BADCVAR("g_freezetag_point_limit");
+ BADCVAR("g_freezetag_revive_respawn");
+ BADCVAR("g_freezetag_round_stop");
+ BADCVAR("g_freezetag_round_respawn");
BADCVAR("g_glowtrails");
BADCVAR("g_hats");
BADCVAR("g_casings");
BADCVAR("g_spawn_alloweffects");
BADCVAR("g_tdm_point_leadlimit");
BADCVAR("g_tdm_point_limit");
+ BADCVAR("g_mayhem_fraglimit");
+ BADCVAR("g_tmayhem_fraglimit");
+ BADCVAR("g_mayhem_visual_score_limit");
+ BADCVAR("g_tmayhem_visual_score_limit");
+ BADCVAR("g_tmayhem_score_leadlimit");
BADCVAR("leadlimit_and_fraglimit");
BADCVAR("leadlimit_override");
+ BADCVAR("g_mayhem_scoringmethod");
+ BADCVAR("g_mayhem_scoringmethod_damage_weight");
+ BADCVAR("g_mayhem_scoringmethod_frag_weight");
+ BADCVAR("g_tmayhem_scoringmethod");
+ BADCVAR("g_tmayhem_scoringmethod_damage_weight");
+ BADCVAR("g_tmayhem_scoringmethod_frag_weight");
BADCVAR("pausable");
BADCVAR("sv_announcer");
BADCVAR("sv_checkforpacketsduringsleep");
BADPREFIX("sv_timeout_");
BADPREFIX("sv_vote_");
BADPREFIX("timelimit_");
+ BADPREFIX("sv_chat_");
+ BADPREFIX("sv_jingle_");
// allowed changes to server admins (please sync this to server.cfg)
// vi commands:
BADCVAR("g_keyhunt_point_limit");
BADCVAR("g_keyhunt_teams_override");
BADCVAR("g_lms_lives_override");
+ BADCVAR("g_mayhem_powerups");
BADCVAR("g_maplist");
BADCVAR("g_maxplayers");
BADCVAR("g_mirrordamage");
BADCVAR("g_start_delay");
BADCVAR("g_superspectate");
BADCVAR("g_tdm_teams_override");
+ BADCVAR("g_tmayhem_teams_override");
+ BADCVAR("g_tmayhem_powerups");
BADCVAR("g_warmup");
BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay");
BADCVAR("hostname");
BADCVAR("sv_motd");
BADCVAR("sv_public");
BADCVAR("sv_showfps");
+ BADCVAR("sv_showspectators");
BADCVAR("sv_status_privacy");
BADCVAR("sv_taunt");
BADCVAR("sv_vote_call");
BADCVAR("g_ca_weaponarena");
BADCVAR("g_freezetag_weaponarena");
BADCVAR("g_lms_weaponarena");
+ BADCVAR("g_mayhem_weaponarena");
+ BADCVAR("g_tmayhem_weaponarena");
BADCVAR("g_ctf_stalemate_time");
#undef BADPRESUFFIX
if(autocvar_g_campaign)
CampaignPreInit();
+ else
+ PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
Map_MarkAsRecent(mapname);
- PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
-
InitGameplayMode();
static_init_late();
static_init_precache();
WinningConditionHelper(this); // set worldstatus
+ round_handler_Activate(!warmup_stage);
+
+ // for RJZ
+ if (autocvar_rjz_count_shards && warmup_stage) {
+ total_shards = -2;
+ send_TotalShardsAll();
+ }
+
world_initialized = 1;
__spawnfunc_spawn_all();
}
*/
//pos = FindIntermission ();
+
+ sound(NULL, CH_INFO, SND_ENDMATCH, VOL_BASE, ATTN_NONE);
VoteReset();
WeaponStats_Shutdown();
Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_Null); // kill all centerprints now
+
+ // send winner notification
+ if(teamplay) {
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, APP_TEAM_NUM(WinningConditionHelper_winnerteam, ANNCE_TEAM_WINS));
+ }
if(autocvar_sv_eventlog)
GameLogEcho(":gameover");
});
target_music_kill();
+
+ // z411
+ if(autocvar_sv_jingle_end) {
+ int jingles_len = 0;
+ string jingles[32];
+ jingles[0] = "";
+
+ FOREACH_WORD(autocvar_sv_jingle_end_list, it,
+ {
+ jingles[jingles_len] = it;
+ jingles_len++;
+ });
+
+ if(jingles_len) {
+ int song_to_play = rint(random() * (jingles_len - 1));
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it),
+ {
+ stuffcmd(it, "cd stop\n");
+ _sound(it, CH_INFO, strcat("jingle/", jingles[song_to_play], ".ogg"), VOL_BASE * autocvar_sv_jingle_end_volume, ATTEN_NORM);
+ });
+ }
+ }
if(autocvar_g_campaign)
CampaignPreIntermission();
//add one more overtime by simply extending the timelimit
cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
+
+ sound(NULL, CH_INFO, SND_OVERTIME, VOL_BASE, ATTN_NONE);
+ if(checkrules_overtimesadded == 1) {
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_OVERTIME);
+ overtime_starttime = time;
+ }
}
float GetWinningCode(float fraglimitreached, float equality)
FOREACH_CLIENT(IS_PLAYER(it) || INGAME(it), { it.winning = 0; });
}
-int fragsleft_last;
+void AnnounceNewLeader()
+{
+ if(teamplay) {
+ if (WinningConditionHelper_equality)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_TEAM_LEADS_TIED);
+ else
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ if(it.team == WinningConditionHelper_winnerteam)
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_LEADS_TEAM);
+ else
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_LEADS_ENEMY);
+ });
+ Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(WinningConditionHelper_winnerteam, ANNCE_TEAM_LEADS));
+ } else {
+ if (WinningConditionHelper_equality)
+ {
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_equality_one, MSG_ANNCE, ANNCE_LEAD_TIED);
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_equality_two, MSG_ANNCE, ANNCE_LEAD_TIED);
+ }
+ else
+ {
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_winner, MSG_ANNCE, ANNCE_LEAD_GAINED);
+ Send_Notification(NOTIF_ONE, WinningConditionHelper_second, MSG_ANNCE, ANNCE_LEAD_LOST);
+ }
+ }
+}
+
+void AnnounceScores(float tm)
+{
+ WinningConditionHelper(NULL);
+ if (Score_NewLeader()) {
+ AnnounceNewLeader();
+ } else {
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ if(it.team == tm)
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_SCORES_TEAM);
+ else
+ Send_Notification(NOTIF_ONE_ONLY, it, MSG_ANNCE, ANNCE_TEAM_SCORES_ENEMY);
+ });
+ Send_Notification(NOTIF_ALL_SPEC, NULL, MSG_ANNCE, APP_TEAM_NUM(tm, ANNCE_TEAM_SCORES));
+ }
+}
+
float WinningCondition_Scores(float limit, float leadlimit)
{
// TODO make everything use THIS winning condition (except LMS)
if(MUTATOR_CALLHOOK(Scores_CountFragsRemaining))
{
- float fragsleft;
if (checkrules_suddendeathend && time >= checkrules_suddendeathend)
{
fragsleft = 1;
fragsleft_last = fragsleft;
}
}
-
+
+ // z411 - lead announcer
+ if(MUTATOR_CALLHOOK(Scores_AnnounceLeads)) {
+ if (Score_NewLeader())
+ AnnounceNewLeader();
+ }
+
bool fraglimit_reached = (limit && WinningConditionHelper_topscore >= limit);
bool leadlimit_reached = (leadlimit && WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
// again, but this shouldn't hurt
return;
}
+
+ // z411 don't check rules if we're in a timeout
+ if (game_timeout) return;
float timelimit = autocvar_timelimit * 60;
float fraglimit = autocvar_fraglimit;
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_RACE_FINISHLAP);
else
Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_FRAG);
+ checkrules_overtimesadded = 1;
+ sound(NULL, CH_INFO, SND_OVERTIME, VOL_BASE, ATTN_NONE);
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_OVERTIME);
}
}
else
{
if(cvar("sv_allow_fullbright"))
serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
+ if(cvar("sv_forbid_pickuptimer"))
+ serverflags |= SERVERFLAG_FORBID_PICKUPTIMER;
sv_ready_restart_after_countdown = cvar("sv_ready_restart_after_countdown");
MUTATOR_CALLHOOK(ReadLevelCvars);
- if (!warmup_stage)
+ if (!warmup_stage && !autocvar_g_campaign)
game_starttime = time + cvar("g_start_delay");
FOREACH(Weapons, it != WEP_Null, { it.wr_init(it); });
bool autocvar_sv_freezenonclients;
void Physics_Frame()
{
- if(autocvar_sv_freezenonclients)
+ if(autocvar_sv_freezenonclients || game_timeout)
return;
IL_EACH(g_moveables, true,