From 831e6416cc0a6032d00c96e3ccccab5a7ad472de Mon Sep 17 00:00:00 2001 From: z411 Date: Thu, 15 Oct 2020 20:58:22 -0300 Subject: [PATCH] Proper timeout and no rounds in warmup --- qcsrc/client/hud/panel/scoreboard.qc | 5 ++-- qcsrc/client/hud/panel/timer.qc | 17 ++++++++++--- qcsrc/common/monsters/sv_monsters.qc | 4 +-- .../mutators/mutator/bloodloss/bloodloss.qc | 2 +- .../common/mutators/mutator/buffs/sv_buffs.qc | 12 ++++----- .../mutator/campcheck/sv_campcheck.qc | 2 +- .../mutators/mutator/instagib/sv_instagib.qc | 2 +- qcsrc/common/stats.qh | 17 ++++++++++--- qcsrc/ecs/systems/sv_physics.qc | 2 +- qcsrc/server/command/cmd.qc | 4 +-- qcsrc/server/command/common.qc | 22 +++++++++++++--- qcsrc/server/command/sv_cmd.qc | 25 +++++++++++++++++++ qcsrc/server/command/vote.qc | 1 + qcsrc/server/items/items.qc | 12 +++++---- qcsrc/server/round_handler.qc | 18 +++++++++++-- qcsrc/server/round_handler.qh | 4 ++- qcsrc/server/weapons/weaponsystem.qc | 2 +- qcsrc/server/world.qc | 8 +++++- 18 files changed, 123 insertions(+), 36 deletions(-) diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index 579ff9558..12eb71cd7 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -1663,6 +1663,7 @@ vector MapStats_DrawKeyValue(vector pos, string key, string value) { return pos; } +/* vector Scoreboard_MapStats_Draw(vector pos, vector rgb, vector bg_size) { float stat_secrets_found, stat_secrets_total; float stat_monsters_killed, stat_monsters_total; @@ -1731,7 +1732,7 @@ vector Scoreboard_MapStats_Draw(vector pos, vector rgb, vector bg_size) { panel_size.x += panel_bg_padding * 2; // restore initial width return end_pos; } - +*/ vector Scoreboard_Rankings_Draw(vector pos, string ranktitle, entity pl, vector rgb, vector bg_size) { @@ -2223,7 +2224,7 @@ void Scoreboard_Draw() pos = Scoreboard_Rankings_Draw(pos, ranktitle, playerslots[player_localnum], panel_bg_color, bg_size); } - pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size); + //pos = Scoreboard_MapStats_Draw(pos, panel_bg_color, bg_size); // List spectators for(pl = players.sort_next; pl; pl = pl.sort_next) diff --git a/qcsrc/client/hud/panel/timer.qc b/qcsrc/client/hud/panel/timer.qc index 293247f95..65abb0d27 100644 --- a/qcsrc/client/hud/panel/timer.qc +++ b/qcsrc/client/hud/panel/timer.qc @@ -39,10 +39,13 @@ void HUD_Timer() string timer; string timer_sub = ""; - float timelimit, timeleft, minutesLeft, overtimes; + bool game_timeout; + float timelimit, timeleft, minutesLeft, overtimes, timeout_last; timelimit = STAT(TIMELIMIT); overtimes = STAT(OVERTIMESADDED); + game_timeout = STAT(GAME_TIMEOUT); + timeout_last = STAT(TIMEOUT_LAST); timeleft = max(0, timelimit * 60 + STAT(GAMESTARTTIME) - time); timeleft = ceil(timeleft); @@ -72,12 +75,20 @@ void HUD_Timer() timer = seconds_tostring(max(0, floor(intermission_time - STAT(GAMESTARTTIME)))); timer_sub = "Intermission"; //} else if (autocvar_hud_panel_timer_increment || (!warmup_stage && timelimit == 0) || (warmup_stage && warmup_timeleft <= 0)) { + } else if (game_timeout) { + if(autocvar_hud_panel_timer_increment) + timer = seconds_tostring(max(0, floor(timeout_last - STAT(GAMESTARTTIME)))); + else + timer = seconds_tostring(ceil(max(0, timelimit * 60 + STAT(GAMESTARTTIME) - timeout_last))); + timer_sub = "Timeout"; } else if (autocvar_hud_panel_timer_increment || timelimit == 0) { + // Time elapsed timer if((warmup_stage && warmup_timeleft <= 0) || time < STAT(GAMESTARTTIME)) timer = seconds_tostring(0); else timer = seconds_tostring(floor(time - STAT(GAMESTARTTIME))); } else { + // Time left timer if(warmup_stage) { if(warmup_timeleft <= 0) timer = seconds_tostring(floor(timelimit * 60)); @@ -86,8 +97,8 @@ void HUD_Timer() } else { if (time < STAT(GAMESTARTTIME)) timer = seconds_tostring(floor(timelimit * 60)); - else if (overtimes > 0) - timer = seconds_tostring(floor(time - STAT(OVERTIMESTARTTIME))); + //else if (overtimes > 0) + // timer = seconds_tostring(floor(time - STAT(OVERTIMESTARTTIME))); else timer = seconds_tostring(timeleft); } diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index d5bff8f02..ba1d4941f 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -31,8 +31,8 @@ void monsters_setstatus(entity this) { - STAT(MONSTERS_TOTAL, this) = monsters_total; - STAT(MONSTERS_KILLED, this) = monsters_killed; + //STAT(MONSTERS_TOTAL, this) = monsters_total; + //STAT(MONSTERS_KILLED, this) = monsters_killed; } void monster_dropitem(entity this, entity attacker) diff --git a/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc b/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc index 41ceaa91f..3992d985a 100644 --- a/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc +++ b/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc @@ -14,7 +14,7 @@ MUTATOR_HOOKFUNCTION(bloodloss, PlayerPreThink) { entity player = M_ARGV(0, entity); - if(game_stopped) + if(game_stopped || game_timeout) return; // during intermission, the player's health changes to strange values for the engine, let's not cause damage during this phase! if(IS_PLAYER(player)) diff --git a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc index 30cef339a..1c0327dcf 100644 --- a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc +++ b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc @@ -119,7 +119,7 @@ void buff_SetCooldown(entity this, float cd) void buff_Respawn(entity this) { - if(game_stopped) return; + if(game_stopped || game_timeout) return; vector oldbufforigin = this.origin; this.velocity = '0 0 200'; @@ -154,7 +154,7 @@ void buff_Respawn(entity this) void buff_Touch(entity this, entity toucher) { - if(game_stopped) return; + if(game_stopped || game_timeout) return; if(ITEM_TOUCH_NEEDKILL()) { @@ -269,7 +269,7 @@ void buff_Think(entity this) this.oldbuffs = STAT(BUFFS, this); } - if(!game_stopped) + if(!game_stopped && !game_timeout) if((round_handler_IsActive() && round_handler_IsRoundStarted()) || time >= game_starttime) if(!this.buff_activetime_updated) { @@ -290,7 +290,7 @@ void buff_Think(entity this) } if(this.buff_activetime) - if(!game_stopped) + if(!game_stopped && !game_timeout) if((round_handler_IsActive() && round_handler_IsRoundStarted()) || time >= game_starttime) { this.buff_activetime = max(0, this.buff_activetime - frametime); @@ -667,7 +667,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerUseKey, CBC_ORDER_FIRST) MUTATOR_HOOKFUNCTION(buffs, ForbidThrowCurrentWeapon) { - if(MUTATOR_RETURNVALUE || game_stopped) return; + if(MUTATOR_RETURNVALUE || game_stopped || game_timeout) return; entity player = M_ARGV(0, entity); if(STAT(BUFFS, player) & BUFF_SWAPPER.m_itemid) @@ -827,7 +827,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink) { entity player = M_ARGV(0, entity); - if(game_stopped || IS_DEAD(player) || frametime || !IS_PLAYER(player)) return; + if(game_stopped || game_timeout || IS_DEAD(player) || frametime || !IS_PLAYER(player)) return; if(STAT(BUFFS, player) & BUFF_FLIGHT.m_itemid) { diff --git a/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc b/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc index f53d8c356..a2370a48c 100644 --- a/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc +++ b/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc @@ -38,7 +38,7 @@ MUTATOR_HOOKFUNCTION(campcheck, PlayerPreThink) bool checked = false; if(autocvar_g_campcheck_interval) - if(!game_stopped && !warmup_stage && time >= game_starttime) + if(!game_stopped && !game_timeout && !warmup_stage && time >= game_starttime) if(IS_PLAYER(player) && !IS_DEAD(player) && !STAT(FROZEN, player)) if(autocvar_g_campcheck_typecheck || !PHYS_INPUT_BUTTON_CHAT(player)) if(IS_REAL_CLIENT(player)) // only apply to real clients (bots may "camp" due to missing waypoints in the map, but that's no reason to constantly kill them, clones can't move) diff --git a/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc b/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc index a23fc3697..3e3f7ac84 100644 --- a/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc +++ b/qcsrc/common/mutators/mutator/instagib/sv_instagib.qc @@ -79,7 +79,7 @@ void instagib_ammocheck(entity this) if(!IS_PLAYER(this)) return; // not a player - if(IS_DEAD(this) || game_stopped) + if(IS_DEAD(this) || game_stopped || game_timeout) instagib_stop_countdown(this); else if (GetResource(this, RES_CELLS) > 0 || (this.items & IT_UNLIMITED_AMMO) || (this.flags & FL_GODMODE)) instagib_stop_countdown(this); diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh index 2a614e427..49be5178c 100644 --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@ -67,12 +67,21 @@ float game_stopped; float game_starttime; //point in time when the countdown to game start is over float round_starttime; //point in time when the countdown to round start is over float overtime_starttime; // z411 point in time where first overtime started + float checkrules_overtimesadded; // z411 add +float timeout_last; +float timeout_total_time; +bool game_timeout; + bool autocvar_g_allow_oldvortexbeam; int autocvar_leadlimit; #endif REGISTER_STAT(WEAPONRATEFACTOR, float, W_WeaponRateFactor(this)) REGISTER_STAT(GAME_STOPPED, int, game_stopped) + +REGISTER_STAT(GAME_TIMEOUT, bool, game_timeout) +REGISTER_STAT(TIMEOUT_LAST, float, timeout_last) + REGISTER_STAT(GAMESTARTTIME, float, game_starttime) REGISTER_STAT(STRENGTH_FINISHED, float) REGISTER_STAT(INVINCIBLE_FINISHED, float) @@ -103,14 +112,14 @@ REGISTER_STAT(VEHICLESTAT_AMMO2, int) REGISTER_STAT(VEHICLESTAT_RELOAD2, int) REGISTER_STAT(VEHICLESTAT_W2MODE, int) REGISTER_STAT(NADE_TIMER, float) -REGISTER_STAT(SECRETS_TOTAL, int, secrets_total) -REGISTER_STAT(SECRETS_FOUND, int, secrets_found) +//REGISTER_STAT(SECRETS_TOTAL, int, secrets_total) +//REGISTER_STAT(SECRETS_FOUND, int, secrets_found) REGISTER_STAT(RESPAWN_TIME, float) REGISTER_STAT(ROUNDSTARTTIME, float, round_starttime) REGISTER_STAT(OVERTIMESTARTTIME, float, overtime_starttime) REGISTER_STAT(OVERTIMESADDED, float, checkrules_overtimesadded) -REGISTER_STAT(MONSTERS_TOTAL, int) -REGISTER_STAT(MONSTERS_KILLED, int) +//REGISTER_STAT(MONSTERS_TOTAL, int) +//REGISTER_STAT(MONSTERS_KILLED, int) REGISTER_STAT(BUFFS, int) REGISTER_STAT(NADE_BONUS, float) REGISTER_STAT(NADE_BONUS_TYPE, int) diff --git a/qcsrc/ecs/systems/sv_physics.qc b/qcsrc/ecs/systems/sv_physics.qc index 1d5553d1d..694359cbe 100644 --- a/qcsrc/ecs/systems/sv_physics.qc +++ b/qcsrc/ecs/systems/sv_physics.qc @@ -42,7 +42,7 @@ void sys_phys_pregame_hold(entity this) if (!IS_PLAYER(this)) { return; } // z411 //const bool allowed_to_move = (time >= game_starttime && !game_stopped); - const bool allowed_to_move = (!game_stopped); + const bool allowed_to_move = (!game_stopped && !game_timeout); if (!allowed_to_move) { this.velocity = '0 0 0'; set_movetype(this, MOVETYPE_NONE); diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index b1d568ba1..0ba8ed300 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -285,7 +285,7 @@ void ClientCommand_join(entity caller, int request) { case CMD_REQUEST_COMMAND: { - if (!game_stopped && IS_CLIENT(caller) && !IS_PLAYER(caller)) + if (!game_stopped && !game_timeout && IS_CLIENT(caller) && !IS_PLAYER(caller)) { if (joinAllowed(caller)) Join(caller); @@ -636,7 +636,7 @@ void ClientCommand_spectate(entity caller, int request) { case CMD_REQUEST_COMMAND: { - if (!intermission_running && IS_CLIENT(caller)) + if (!intermission_running && IS_CLIENT(caller) && !game_timeout) { if(argv(1) != "") { diff --git a/qcsrc/server/command/common.qc b/qcsrc/server/command/common.qc index c27c5ac33..94ea014e9 100644 --- a/qcsrc/server/command/common.qc +++ b/qcsrc/server/command/common.qc @@ -212,7 +212,8 @@ void timeout_handler_think(entity this) if (timeout_time == autocvar_sv_timeout_resumetime) // play a warning sound when only seconds are left Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_PREPARE); - this.nextthink = time + TIMEOUT_SLOWMO_VALUE; // think again in one second + //this.nextthink = time + TIMEOUT_SLOWMO_VALUE; // think again in one second + this.nextthink = time + 1; timeout_time -= 1; // decrease the time counter } else if (timeout_time == -1) // infinite timer @@ -224,9 +225,20 @@ void timeout_handler_think(entity this) { Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_TIMEIN); timeout_status = TIMEOUT_INACTIVE; + float total_time = time - timeout_last; // reset the slowmo value back to normal - cvar_set("slowmo", ftos(orig_slowmo)); + // z411 TODO + //cvar_set("slowmo", ftos(orig_slowmo)); + + // Disable timeout and fix times + game_timeout = false; + timeout_total_time += total_time; + game_starttime += total_time; + if(round_handler && round_handler_GetEndTime() > 0) + round_handler.round_endtime += total_time; + + LOG_INFOF("timeout lasted %d secs", total_time); // unlock the view for players so they can move around again FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), { @@ -253,7 +265,11 @@ void timeout_handler_think(entity this) timeout_status = TIMEOUT_ACTIVE; // set the slowmo value to the timeout default slowmo value - cvar_set("slowmo", ftos(TIMEOUT_SLOWMO_VALUE)); + //cvar_set("slowmo", ftos(TIMEOUT_SLOWMO_VALUE)); + game_timeout = true; + timeout_last = time; + + // play timeout sound sound(NULL, CH_INFO, SND_TIMEOUT, VOL_BASE, ATTN_NONE); // reset all the flood variables diff --git a/qcsrc/server/command/sv_cmd.qc b/qcsrc/server/command/sv_cmd.qc index 526775c7c..4fe4c7c45 100644 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@ -235,6 +235,30 @@ void GameCommand_allready(int request) } } +// z411 TODO +void GameCommand_stop(int request, int argc) +{ + switch (request) + { + case CMD_REQUEST_COMMAND: + { + if(argv(1) == "true") + game_stopped = true; + else + game_stopped = false; + return; + } + + default: + case CMD_REQUEST_USAGE: + { + LOG_HELP("Usage:^3 sv_cmd stop"); + LOG_HELP(" No arguments required."); + return; + } + } +} + void GameCommand_allspec(int request, int argc) { switch (request) @@ -1712,6 +1736,7 @@ void GameCommand_(int request) // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;) SERVER_COMMAND(setflag, "Set client flag") { GameCommand_setflag(request, arguments); } SERVER_COMMAND(teamname, "Set team name") { GameCommand_teamname(request, arguments); } +SERVER_COMMAND(stop, "Stop") { GameCommand_stop(request, arguments); } SERVER_COMMAND(adminmsg, "Send an admin message to a client directly") { GameCommand_adminmsg(request, arguments); } SERVER_COMMAND(allready, "Restart the server and reset the players") { GameCommand_allready(request); } diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc index edd898546..8306349cf 100644 --- a/qcsrc/server/command/vote.qc +++ b/qcsrc/server/command/vote.qc @@ -481,6 +481,7 @@ void ReadyRestart_force() FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), { CS(it).allowed_timeouts = autocvar_sv_timeout_number; }); } + round_handler_Activate(true); if (!sv_ready_restart_after_countdown) reset_map(true); if (autocvar_sv_eventlog) GameLogEcho(":restart"); } diff --git a/qcsrc/server/items/items.qc b/qcsrc/server/items/items.qc index 861b21eed..906e89aea 100644 --- a/qcsrc/server/items/items.qc +++ b/qcsrc/server/items/items.qc @@ -280,12 +280,14 @@ void Item_RespawnCountdown(entity this) void Item_RespawnThink(entity this) { - this.nextthink = time; + this.nextthink = time + 1; if(this.origin != this.oldorigin) ItemUpdate(this); - - if(time >= this.wait) + + if(!game_timeout && time - timeout_total_time >= this.wait) Item_Respawn(this); + + //LOG_INFOF("time until respawn %d", (this.wait) - (time - timeout_total_time)); } void Item_ScheduleRespawnIn(entity e, float t) @@ -308,8 +310,8 @@ void Item_ScheduleRespawnIn(entity e, float t) { setthink(e, Item_RespawnThink); e.nextthink = time; - e.scheduledrespawntime = time + t; - e.wait = time + t; + e.scheduledrespawntime = time - timeout_total_time + t; + e.wait = time - timeout_total_time + t; if(Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS)) { diff --git a/qcsrc/server/round_handler.qc b/qcsrc/server/round_handler.qc index 66da6c37c..9eb8963c8 100644 --- a/qcsrc/server/round_handler.qc +++ b/qcsrc/server/round_handler.qc @@ -9,6 +9,8 @@ void round_handler_Think(entity this) { + if (game_timeout) { this.nextthink = time + 1; return; } + if (intermission_running) { round_handler_Reset(0); @@ -96,13 +98,25 @@ void round_handler_Spawn(bool() canRoundStart_func, bool() canRoundEnd_func, voi } entity this = round_handler = new(round_handler); - setthink(this, round_handler_FirstThink); + this.canRoundStart = canRoundStart_func; this.canRoundEnd = canRoundEnd_func; this.roundStart = roundStart_func; this.wait = false; round_handler_Init(5, 5, 180); - this.nextthink = time; + +} + +void round_handler_Activate(bool active) { + if (round_handler) { + entity this = round_handler; + + this.isactive = active; + if(active) { + setthink(this, round_handler_FirstThink); + this.nextthink = time; + } + } } void round_handler_Reset(float next_think) diff --git a/qcsrc/server/round_handler.qh b/qcsrc/server/round_handler.qh index 5979eb5c3..01288ab64 100644 --- a/qcsrc/server/round_handler.qh +++ b/qcsrc/server/round_handler.qh @@ -1,6 +1,7 @@ #pragma once entity round_handler; +.bool isactive; .float delay; // stores delay from round end to countdown start .float count; // stores initial number of the countdown .bool wait; // it's set to true when round ends, to false when countdown starts @@ -15,9 +16,10 @@ entity round_handler; void round_handler_Init(float the_delay, float the_count, float the_round_timelimit); void round_handler_Spawn(bool() canRoundStart_func, bool() canRoundEnd_func, void() roundStart_func); void round_handler_Reset(float next_think); +void round_handler_Activate(bool active); void round_handler_Remove(); -#define round_handler_IsActive() (round_handler != NULL) +#define round_handler_IsActive() (round_handler != NULL && round_handler.isactive) #define round_handler_AwaitingNextRound() (round_handler.wait) #define round_handler_CountdownRunning() (!round_handler.wait && round_handler.cnt) #define round_handler_IsRoundStarted() (!round_handler.wait && !round_handler.cnt) diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index 763881388..b3112fe3b 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -440,7 +440,7 @@ bool weaponLocked(entity player) { if (time < game_starttime && !sv_ready_restart_after_countdown) return true; if (player.player_blocked) return true; - if (game_stopped) return true; + if (game_stopped || game_timeout) return true; if (STAT(FROZEN, player)) return true; if (MUTATOR_CALLHOOK(LockWeapon, player)) return true; return false; diff --git a/qcsrc/server/world.qc b/qcsrc/server/world.qc index 891131b38..309a42123 100644 --- a/qcsrc/server/world.qc +++ b/qcsrc/server/world.qc @@ -1017,9 +1017,12 @@ spawnfunc(worldspawn) modname = strzone(modname); WinningConditionHelper(this); // set worldstatus - + world_initialized = 1; __spawnfunc_spawn_all(); + + if(!warmup_stage) + round_handler_Activate(true); } spawnfunc(light) @@ -1955,6 +1958,9 @@ void CheckRules_World() // 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; -- 2.39.2