From 299930256ea2658df60dd629d8bfcbc2467676c9 Mon Sep 17 00:00:00 2001 From: div0 Date: Fri, 6 Feb 2009 07:27:30 +0000 Subject: [PATCH] [ 2555894 ] Ready restart countdown clientside git-svn-id: svn://svn.icculus.org/nexuiz/trunk@5770 f962a42d-fe04-0410-a3ab-8c8b0445ebaa --- data/qcsrc/client/View.qc | 26 ++++++++++ data/qcsrc/client/main.qh | 4 ++ data/qcsrc/client/miscfunctions.qc | 24 +++++++++ data/qcsrc/client/sbar.qc | 9 ++++ data/qcsrc/common/constants.qh | 3 ++ data/qcsrc/server/clientcommands.qc | 75 +++++++---------------------- data/qcsrc/server/defs.qh | 6 +-- data/qcsrc/server/miscfunctions.qc | 9 ---- data/qcsrc/server/teamplay.qc | 11 ++--- 9 files changed, 90 insertions(+), 77 deletions(-) diff --git a/data/qcsrc/client/View.qc b/data/qcsrc/client/View.qc index 94a7dc613..ed250fe6e 100644 --- a/data/qcsrc/client/View.qc +++ b/data/qcsrc/client/View.qc @@ -70,6 +70,30 @@ void Porto_Draw() } } +/** + * Checks whether the server initiated a map restart (stat_game_starttime changed) + * + * TODO: Use a better solution where a common shared entitiy is used that contains + * timelimit, fraglimit and game_starttime! Requires engine changes (remove STAT_TIMELIMIT + * and STAT_FRAGLIMIT to be auto-sent) + */ +void CheckForGamestartChange() { + float startTime; + startTime = getstatf(STAT_GAMESTARTTIME); + if (previous_game_starttime != startTime) { + if ((time + 5.0) < startTime) { + //if connecting to server while restart was active don't always play prepareforbattle + sound(self, CHAN_VOICE, "announcer/robotic/prepareforbattle.wav", VOL_BASEVOICE, ATTN_NONE); + } + if (time < startTime) { + restartAnnouncer = spawn(); + restartAnnouncer.think = restartAnnouncer_Think; + restartAnnouncer.nextthink = startTime - floor(startTime - time); //synchronize nextthink to startTime + } + } + previous_game_starttime = startTime; +} + float DPCONTENTS_SOLID = 1; // hit a bmodel, not a bounding box float DPCONTENTS_BODY = 32; // hit a bounding box, not a bmodel void Porto_Init() @@ -247,6 +271,8 @@ void CSQC_UpdateView(float w, float h) // might even be better to add the gametype to TE_CSQC_INIT...? if(!postinit) PostInit(); + + CheckForGamestartChange(); fov = cvar("fov"); if(button_zoom || fov <= 59.5) diff --git a/data/qcsrc/client/main.qh b/data/qcsrc/client/main.qh index 28ac634be..c9a3b4b9b 100644 --- a/data/qcsrc/client/main.qh +++ b/data/qcsrc/client/main.qh @@ -136,6 +136,10 @@ float ready_waiting_for_me; float vote_waiting; float vote_waiting_for_me; +float previous_game_starttime; +entity restartAnnouncer; //a temporary entity which will play the countdown sounds 3, 2, 1 for the client +void restartAnnouncer_Think(); + float current_zoomfraction; float cs_project_is_b0rked; diff --git a/data/qcsrc/client/miscfunctions.qc b/data/qcsrc/client/miscfunctions.qc index 86a640b6b..f648de2bc 100644 --- a/data/qcsrc/client/miscfunctions.qc +++ b/data/qcsrc/client/miscfunctions.qc @@ -3,6 +3,30 @@ var float(string text, float handleColors) stringwidth; entity players; entity teams; +void restartAnnouncer_Think() { + float countdown_rounded, countdown; + countdown = getstatf(STAT_GAMESTARTTIME) - time; + countdown_rounded = floor(0.5 + countdown); + if(countdown <= 0) { + if (!spectatee_status) //do cprint only for players + cprint(NEWLINES, "^1Begin!"); + + sound(self, CHAN_VOICE, "announcer/robotic/begin.wav", VOL_BASEVOICE, ATTN_NONE); + remove(self); + return; + } + else { + if (!spectatee_status) //do cprint only for players + cprint(NEWLINES, "^1Game starts in ", ftos(countdown_rounded), " seconds"); + + if(countdown_rounded <= 3 && countdown_rounded >= 1) { + sound(self, CHAN_VOICE, strcat("announcer/robotic/", ftos(countdown_rounded), ".wav"), VOL_BASEVOICE, ATTN_NONE); + } + + self.nextthink = getstatf(STAT_GAMESTARTTIME) - (countdown - 1); + } +} + void AuditLists() { entity e; diff --git a/data/qcsrc/client/sbar.qc b/data/qcsrc/client/sbar.qc index b0bab9e7c..4196d33ac 100644 --- a/data/qcsrc/client/sbar.qc +++ b/data/qcsrc/client/sbar.qc @@ -1590,6 +1590,15 @@ void Sbar_Draw (void) else s = strcat("^1Press ^3", getcommandkey("jump", "+jump"), "^1 to join"); o = Sbar_DrawNoteLine(o, s); + + //show restart countdown: + if (time < getstatf(STAT_GAMESTARTTIME)) { + float countdown; + //we need to ceil, otherwise the countdown would be off by .5 when using round() + countdown = ceil(getstatf(STAT_GAMESTARTTIME) - time); + s = strcat("^1Game starts in ^3", ftos(countdown), "^1 seconds"); + o = Sbar_DrawNoteLine(o, s); + } } if(warmup_stage) { diff --git a/data/qcsrc/common/constants.qh b/data/qcsrc/common/constants.qh index d9a06299d..716c6329f 100644 --- a/data/qcsrc/common/constants.qh +++ b/data/qcsrc/common/constants.qh @@ -399,3 +399,6 @@ float HITTYPE_RESERVED = 0x1000; // unused yet #define FRAGS_PLAYER 0 #define FRAGS_SPECTATOR -666 #define FRAGS_PLAYER_NONSOLID -616 + +//misc. stuff +#define NEWLINES "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" diff --git a/data/qcsrc/server/clientcommands.qc b/data/qcsrc/server/clientcommands.qc index 5176f2485..86eaeeb1f 100644 --- a/data/qcsrc/server/clientcommands.qc +++ b/data/qcsrc/server/clientcommands.qc @@ -218,8 +218,7 @@ void SV_ParseClientCommand(string s) { if(timeoutStatus) { return sprint(self, "^1You cannot reset the game while a timeout is active!\n"); } - - //if(!restartAnnouncer) + { if(!readyrestart_happened || cvar("sv_ready_restart_repeatable")) { @@ -381,13 +380,15 @@ void ReadyRestartForce() lockteams = 1; bprint("^1The teams are now locked.\n"); } - + //initiate the restart-countdown-announcer entity - restartAnnouncer = spawn(); - restartAnnouncer.think = restartAnnouncer_Think; - restartAnnouncer.nextthink = time; - restartAnnouncer.spawnflags = !!cvar("sv_ready_restart_after_countdown"); - + if(cvar("sv_ready_restart_after_countdown")) + { + restartTimer = spawn(); + restartTimer.think = restartTimer_Think; + restartTimer.nextthink = game_starttime; + } + //after a restart every players number of allowed timeouts gets reset, too if(cvar("sv_timeout")) { @@ -395,13 +396,10 @@ void ReadyRestartForce() e.allowedTimeouts = cvar("sv_timeout_number"); } - //play the prepareforbattle sound to everyone - play2all("announcer/robotic/prepareforbattle.wav"); - //reset map immediately if this cvar is not set if (!cvar("sv_ready_restart_after_countdown")) reset_map(TRUE); - + if(cvar("sv_eventlog")) GameLogEcho(":restart"); } @@ -427,7 +425,7 @@ void ReadyRestart() * restart_countdown variable is set to allow other functions like PlayerPostThink * to detect that the countdown is now active. If the cvar sv_ready_restart_after_countdown * is not set the map will be resetted. - * + * * Function is called after the server receives a 'ready' sign from a player. */ void ReadyCount() @@ -454,53 +452,14 @@ void ReadyCount() } /** - * Shows the restart countdown for all players. - * Plays the countdown sounds for the seconds 3, 2 1, begin for everyone. * Restarts the map after the countdown is over (and cvar sv_ready_restart_after_countdown - * is set to 1). + * is set) */ -void restartAnnouncer_Think() { - local entity plr; - local string s; - float f, c; - c = game_starttime - time; - f = floor(0.5 + c); - if(c <= 0) { //show the "Begin" message - if(self.spawnflags & 1) // if sv_ready_restart_after_countdown is set - { - if (!g_assault) { - //don't clear scores for assault mode, which uses ReadyRestartForce (and thus - //restartAnnouncer_Think) to start a new round - Score_ClearAll(); - } - restart_mapalreadyrestarted = 1; - reset_map(TRUE); - } - - FOR_EACH_REALCLIENT(plr) { - if(plr.classname == "player") { - s = strcat(NEWLINES, "^1Begin!"); - centerprint(plr, s); - } - } - play2all("announcer/robotic/begin.wav"); - - remove(self); - return; - } - else { - FOR_EACH_REALCLIENT(plr) { - if(plr.classname == "player") { - s = strcat(NEWLINES, "^1Game starts in ", ftos(f), " seconds"); - centerprint(plr, s); - } - } - - if(f <= 3) { - play2all(strcat("announcer/robotic/", ftos(f), ".wav")); - } - self.nextthink = game_starttime - (f - 1); - } +void restartTimer_Think() { + restart_mapalreadyrestarted = 1; + reset_map(TRUE); + remove(self); + return; } /** diff --git a/data/qcsrc/server/defs.qh b/data/qcsrc/server/defs.qh index ad2170977..46f143045 100644 --- a/data/qcsrc/server/defs.qh +++ b/data/qcsrc/server/defs.qh @@ -59,8 +59,6 @@ float team1_score, team2_score, team3_score, team4_score; float maxclients; -#define NEWLINES "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" - // Fields .void(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force) event_damage; @@ -259,8 +257,8 @@ float alreadychangedlevel; .float ready; #define RESTART_COUNTDOWN 10 float restart_mapalreadyrestarted; //bool, indicates whether reset_map() was already executed -entity restartAnnouncer; //a temporary entity which will play the countdown sounds 3, 2, 1 for all clients, will also reset the map after the countdown -void restartAnnouncer_Think(); +entity restartTimer; +void restartTimer_Think(); float blockSpectators; //if set, new or existing spectators or observers will be removed unless they become a player within g_maxplayers_spectator_blocktime seconds .float spectatortime; //point in time since the client is spectating or observing void checkSpectatorBlock(); diff --git a/data/qcsrc/server/miscfunctions.qc b/data/qcsrc/server/miscfunctions.qc index ffba52711..26f5d367a 100644 --- a/data/qcsrc/server/miscfunctions.qc +++ b/data/qcsrc/server/miscfunctions.qc @@ -1069,16 +1069,7 @@ void readlevelcvars(void) g_weapon_stay = 1; if not(inWarmupStage) - { game_starttime = cvar("g_start_delay"); - if(game_starttime) - { - restartAnnouncer = spawn(); - restartAnnouncer.think = restartAnnouncer_Think; - restartAnnouncer.nextthink = time + 0.1; - restartAnnouncer.spawnflags = 0; - } - } readplayerstartcvars(); } diff --git a/data/qcsrc/server/teamplay.qc b/data/qcsrc/server/teamplay.qc index 1f3a1d781..873e93f20 100644 --- a/data/qcsrc/server/teamplay.qc +++ b/data/qcsrc/server/teamplay.qc @@ -387,14 +387,16 @@ void PrintWelcomeMessage(entity pl) return; } +//TODO GreEn`mArine: make the timeout-messages clientside as well (just like the ready restart countdown)! if(!self.BUTTON_INFO) { // TODO get rid of this too local string specString; specString = NEWLINES; - if(time < game_starttime) //also show the countdown when being a spectator - specString = strcat(specString, "\n\n^1Game starts in ", ftos(ceil(game_starttime - time)), " seconds^7"); - else if (timeoutStatus != 0) + //if(time < game_starttime) //also show the countdown when being a spectator + // specString = strcat(specString, "\n\n^1Game starts in ", ftos(ceil(game_starttime - time)), " seconds^7"); + //else + if (timeoutStatus != 0) specString = strcat(specString, "\n\n", getTimeoutText(1)); else { @@ -460,9 +462,6 @@ void PrintWelcomeMessage(entity pl) if(modifications != "") s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n"); - if(time < game_starttime) - s = strcat(s, "\n^1Game starts in ", ftos(restartAnnouncer.cnt + 1), " seconds^7"); - if(timeoutStatus != 0) s = strcat(s, "\n\n", getTimeoutText(1)); -- 2.39.2