]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Refactor round handling in freezetag because I couldn't find any way to fix some...
authorterencehill <piuntn@gmail.com>
Thu, 6 Dec 2012 15:51:47 +0000 (16:51 +0100)
committerterencehill <piuntn@gmail.com>
Mon, 10 Dec 2012 23:53:02 +0000 (00:53 +0100)
What's changed:
Countdown doesn't start anymore after warmup stage or if g_start_delay is 0 at the beginning of the game when there aren't enough players
Countdown to round start is now stopped if there aren't enough players
Weapons can't be used anymore when the round ends (it avoids to add accuracy stats)

qcsrc/server/arena.qc
qcsrc/server/cl_weapons.qc
qcsrc/server/mutators/gamemode_freezetag.qc
qcsrc/server/progs.src
qcsrc/server/round_handler.qc [new file with mode: 0644]
qcsrc/server/round_handler.qh [new file with mode: 0644]

index a4968af8031574a614df744f0c0231c716cc114f..e2d73cc44287778c6f66e2de08803c13481a5346 100644 (file)
@@ -394,12 +394,6 @@ void Spawnqueue_Check()
                        next_round = 0;
                        reset_map(TRUE);
                }
-       } else if(g_freezetag) {
-               if((next_round && next_round < time))
-               {
-                       next_round = 0;
-                       reset_map(TRUE);
-               }
        } else { // arena
                //extend next_round if it isn't set yet and only 1 player is spawned
                if(!next_round)
@@ -436,7 +430,7 @@ void Spawnqueue_Check()
 
 void Arena_Main()
 {
-       if(!(g_ca || g_freezetag || g_arena))
+       if(!(g_ca || g_arena))
                return;
 
        if(g_ca)
index 236c0923fdc330834469234bc9eb2285a1f6bb26..0b12297c7852f8f08741c2a57094be4013989906 100644 (file)
@@ -374,7 +374,10 @@ void W_WeaponFrame()
        if (frametime)
                self.weapon_frametime = frametime;
 
-       if(((arena_roundbased || g_ca || g_freezetag) && time < warmup) || ((time < game_starttime) && !autocvar_sv_ready_restart_after_countdown))
+       if(((arena_roundbased || g_ca) && time < warmup) || ((time < game_starttime) && !autocvar_sv_ready_restart_after_countdown))
+               return;
+
+       if(round_handler_IsActive() && !round_handler_IsRoundStarted())
                return;
 
        if(self.freezetag_frozen == 1)
index ca453c5c0145fe3023927620dda8221835884733..e9ff6153ffd84bd8c33354957e5af6badd168a89 100644 (file)
@@ -1,9 +1,12 @@
+float freezetag_TeamsCanPlay();
+float freezetag_CheckWinner();
 void freezetag_Initialize()
 {
        precache_model("models/ice/ice.md3");
-       warmup = max(time, game_starttime) + autocvar_g_freezetag_warmup;
        ScoreRules_freezetag();
 
+       round_handler_Spawn(freezetag_TeamsCanPlay, freezetag_CheckWinner, 5, autocvar_g_freezetag_warmup);
+
        addstat(STAT_REDALIVE, AS_INT, redalive_stat);
        addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
        addstat(STAT_YELLOWALIVE, AS_INT, yellowalive_stat);
@@ -13,21 +16,56 @@ void freezetag_Initialize()
        addstat(STAT_REVIVE_PROGRESS, AS_FLOAT, freezetag_revive_progress);
 }
 
-void freezetag_CheckWinner()
+void freezetag_count_alive_players()
 {
-       if(time <= game_starttime || inWarmupStage)
-               return;
-
-       if(next_round || (time > warmup - autocvar_g_freezetag_warmup && time < warmup))
-               return; // already waiting for next round to start
+       entity e;
+       total_players = redalive = bluealive = yellowalive = pinkalive = 0;
+       FOR_EACH_PLAYER(e) {
+               if(e.team == COLOR_TEAM1 && e.health >= 1)
+               {
+                       ++total_players;
+                       if (!e.freezetag_frozen) ++redalive;
+               }
+               else if(e.team == COLOR_TEAM2 && e.health >= 1)
+               {
+                       ++total_players;
+                       if (!e.freezetag_frozen) ++bluealive;
+               }
+               else if(e.team == COLOR_TEAM3 && e.health >= 1)
+               {
+                       ++total_players;
+                       if (!e.freezetag_frozen) ++yellowalive;
+               }
+               else if(e.team == COLOR_TEAM4 && e.health >= 1)
+               {
+                       ++total_players;
+                       if (!e.freezetag_frozen) ++pinkalive;
+               }
+       }
+       FOR_EACH_REALCLIENT(e) {
+               e.redalive_stat = redalive;
+               e.bluealive_stat = bluealive;
+               e.yellowalive_stat = yellowalive;
+               e.pinkalive_stat = pinkalive;
+       }
+}
 
+float freezetag_TeamsCanPlay()
+{
        if((redalive >= 1 && bluealive >= 1)
                || (redalive >= 1 && yellowalive >= 1)
                || (redalive >= 1 && pinkalive >= 1)
                || (bluealive >= 1 && yellowalive >= 1)
                || (bluealive >= 1 && pinkalive >= 1)
                || (yellowalive >= 1 && pinkalive >= 1))
-               return; // we still have active players on two or more teams, nobody won yet
+               return 1; // we still have active players on two or more teams, nobody won yet
+       return 0;
+}
+
+float freezetag_CheckWinner()
+{
+       if(freezetag_TeamsCanPlay())
+               return 0;
 
        entity e, winner;
        string teamname;
@@ -59,7 +97,7 @@ void freezetag_CheckWinner()
                TeamScore_AddToTeam(winner.team, ST_SCORE, +1);
        }
 
-       next_round = time + 5;
+       return 1;
 }
 
 // this is needed to allow the player to turn his view around (fixangle can't
@@ -71,40 +109,6 @@ void freezetag_Ice_Think()
        self.nextthink = time;
 }
 
-void freezetag_count_alive_players()
-{
-       entity e;
-       total_players = redalive = bluealive = yellowalive = pinkalive = 0;
-       FOR_EACH_PLAYER(e) {
-               if(e.team == COLOR_TEAM1 && e.health >= 1)
-               {
-                       ++total_players;
-                       if (!e.freezetag_frozen) ++redalive;
-               }
-               else if(e.team == COLOR_TEAM2 && e.health >= 1)
-               {
-                       ++total_players;
-                       if (!e.freezetag_frozen) ++bluealive;
-               }
-               else if(e.team == COLOR_TEAM3 && e.health >= 1)
-               {
-                       ++total_players;
-                       if (!e.freezetag_frozen) ++yellowalive;
-               }
-               else if(e.team == COLOR_TEAM4 && e.health >= 1)
-               {
-                       ++total_players;
-                       if (!e.freezetag_frozen) ++pinkalive;
-               }
-       }
-       FOR_EACH_REALCLIENT(e) {
-               e.redalive_stat = redalive;
-               e.bluealive_stat = bluealive;
-               e.yellowalive_stat = yellowalive;
-               e.pinkalive_stat = pinkalive;
-       }
-}
-
 void freezetag_Freeze(entity attacker)
 {
        if(self.freezetag_frozen)
@@ -288,30 +292,25 @@ MUTATOR_HOOKFUNCTION(freezetag_RemovePlayer)
 {
        self.health = 0; // neccessary to update correctly alive stats
        freezetag_Unfreeze(world);
-
        freezetag_count_alive_players();
-
-       if(total_players > 1) // only check for winners if we had more than two players (one of them left, don't let the other player win just because of that)
-               freezetag_CheckWinner();
-
        return 1;
 }
 
 MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
 {
-       // let the player die in these cases
-       if(time <= game_starttime)
-               return 1;
-       if(next_round || (time > warmup - autocvar_g_freezetag_warmup && time < warmup))
-               return 1;
+       if(round_handler_IsActive())
+       if(round_handler_CountdownRunning())
+       {
+               if(self.freezetag_frozen)
+                       freezetag_Unfreeze(world);
+               freezetag_count_alive_players();
+               return 1; // let the player die so that he can respawn whenever he wants
+       }
 
        if(frag_deathtype == DEATH_HURTTRIGGER)
        {
                if(!self.freezetag_frozen)
-               {
                        freezetag_Freeze(world);
-                       freezetag_CheckWinner();
-               }
                PutClientInServer(); // respawn the player
                self.health = 1;
                self.armorvalue = 0;
@@ -340,29 +339,21 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
 
        frag_target.health = 1; // "respawn" the player :P
 
-       freezetag_CheckWinner();
-
        return 1;
 }
 
 MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
 {
+       if(self.freezetag_frozen_timeout == -1) // if PlayerSpawn is called by reset_map_players
+               return 1; // do nothing, round is starting right now
+
        freezetag_count_alive_players();
 
        if(self.freezetag_frozen) // stay frozen if respawning after death (DEATH_HURTTRIGGER)
                return 1;
 
-       if(time <= game_starttime || inWarmupStage || total_players == 1)
-               return 1;
-
-       if(total_players == 2) // only one player active on server, start a new match immediately
-       if(!next_round && warmup && (time < warmup - autocvar_g_freezetag_warmup || time > warmup)) // not awaiting next round
-       {
-               next_round = time;
-               return 1;
-       }
-
-       if(warmup && time > warmup) // spawn too late, freeze player
+       if(round_handler_IsActive())
+       if(round_handler_IsRoundStarted())
        {
                centerprint(self, "^1Round already started, you spawn as frozen.");
                freezetag_Freeze(world);
@@ -371,23 +362,17 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
        return 1;
 }
 
-MUTATOR_HOOKFUNCTION(freezetag_reset_map_global)
-{
-       redalive = bluealive = yellowalive = pinkalive = 0;
-       warmup = max(time, game_starttime);
-       if(autocvar_g_freezetag_warmup > 0)
-               warmup += autocvar_g_freezetag_warmup;
-       return 1;
-}
-
 MUTATOR_HOOKFUNCTION(freezetag_reset_map_players)
 {
        FOR_EACH_PLAYER(self)
        {
                if (self.freezetag_frozen)
                        freezetag_Unfreeze(world);
+               self.freezetag_frozen_timeout = -1;
                PutClientInServer();
+               self.freezetag_frozen_timeout = 0;
        }
+       freezetag_count_alive_players();
        return 1;
 }
 
@@ -402,9 +387,6 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
        float n;
        vector revive_extra_size;
 
-       if(gameover)
-               return 1;
-
        if(self.freezetag_frozen)
        {
                // keep health = 1
@@ -418,8 +400,10 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerPreThink)
                        return 1;
                }
        }
-       if(next_round || (time > warmup - autocvar_g_freezetag_warmup && time < warmup))
-               return 1; // already waiting for next round to start
+
+       if(round_handler_IsActive())
+       if(!round_handler_IsRoundStarted())
+               return 1;
 
        revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
 
@@ -551,7 +535,6 @@ MUTATOR_DEFINITION(gamemode_freezetag)
        MUTATOR_HOOK(ClientDisconnect, freezetag_RemovePlayer, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerDies, freezetag_PlayerDies, CBC_ORDER_ANY);
        MUTATOR_HOOK(PlayerSpawn, freezetag_PlayerSpawn, CBC_ORDER_ANY);
-       MUTATOR_HOOK(reset_map_global, freezetag_reset_map_global, CBC_ORDER_ANY);
        MUTATOR_HOOK(reset_map_players, freezetag_reset_map_players, CBC_ORDER_ANY);
        MUTATOR_HOOK(GiveFragsForKill, freezetag_GiveFragsForKill, CBC_ORDER_FIRST);
        MUTATOR_HOOK(PlayerPreThink, freezetag_PlayerPreThink, CBC_ORDER_FIRST);
index 028519372f025ae24aa923d472ba0a6593de86b7..23e872df2f85650267148ec6150e3ff3a7f57aab 100644 (file)
@@ -78,6 +78,8 @@ antilag.qh
 
 playerdemo.qh
 
+round_handler.qh
+
 // singleplayer stuff
 item_key.qh
 secret.qh
@@ -204,6 +206,8 @@ anticheat.qc
 cheats.qc
 playerstats.qc
 
+round_handler.qc
+
 ../common/explosion_equation.qc
 
 mutators/base.qc
diff --git a/qcsrc/server/round_handler.qc b/qcsrc/server/round_handler.qc
new file mode 100644 (file)
index 0000000..882538d
--- /dev/null
@@ -0,0 +1,127 @@
+void round_handler_Think()
+{
+       entity e;
+       float f;
+
+       if(inWarmupStage || time < game_starttime)
+       {
+               self.nextthink = time + 1;
+               return;
+       }
+
+       if(gameover)
+       {
+               round_handler_Stop();
+               round_handler_Remove();
+               return;
+       }
+
+       if(self.wait)
+       {
+               reset_map(TRUE);
+               self.wait = FALSE;
+               self.cnt = self.count + 1; // init countdown
+       }
+
+       if(self.cnt > 0) // countdown running
+       {
+               if(self.canRoundStart())
+               {
+                       f = self.cnt - 1;
+                       if(f == 5) Announce("prepareforbattle");
+                       else if(f == 3) Announce("3");
+                       else if(f == 2) Announce("2");
+                       else if(f == 1) Announce("1");
+                       else if(f == 0)
+                       {
+                               Announce("begin");
+                               FOR_EACH_REALCLIENT(e)
+                                       Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "^1Begin!", 1, 0);
+                               self.cnt = 0;
+                               self.nextthink = time;
+                               return;
+                       }
+
+                       FOR_EACH_REALCLIENT(e)
+                               Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "Round will start in %d", 1, f);
+                       self.cnt = self.cnt - 1;
+               }
+               else
+               {
+                       round_handler_Stop();
+               }
+               self.nextthink = time + 1; // canRoundStart every second
+       }
+       else
+       {
+               if(self.canRoundEnd())
+               {
+                       // schedule a new round
+                       self.wait = TRUE;
+                       self.nextthink = time + self.delay;
+               }
+               else
+               {
+                       self.nextthink = time; // canRoundEnd every frame
+               }
+       }
+}
+
+void round_handler_Spawn(float() canRoundStart_func, float() canRoundEnd_func, float the_delay, float the_count)
+{
+       if(round_handler)
+       {
+               backtrace("Can't spawn round_handler again!");
+               return;
+       }
+       round_handler = spawn();
+       round_handler.classname = "round_handler";
+
+       round_handler.think = round_handler_Think;
+       round_handler.canRoundStart = canRoundStart_func;
+       round_handler.canRoundEnd = canRoundEnd_func;
+       round_handler.delay = (the_delay > 0) ? the_delay : 0;
+       round_handler.count = fabs(floor(the_count));
+       round_handler.wait = FALSE;
+       round_handler.cnt = round_handler.count + 1;
+       round_handler.nextthink = time;
+}
+
+float round_handler_IsActive()
+{
+       return (round_handler && !inWarmupStage && time > game_starttime);
+}
+
+float round_handler_AwaitingNextRound()
+{
+       return (round_handler.wait);
+}
+
+float round_handler_CountdownRunning()
+{
+       return (!round_handler.wait && round_handler.cnt);
+}
+
+float round_handler_IsRoundStarted()
+{
+       return (!round_handler.wait && !round_handler.cnt);
+}
+
+void round_handler_Stop()
+{
+       entity e;
+       if(round_handler.count)
+       if(round_handler.cnt < round_handler.count + 1)
+       {
+               FOR_EACH_REALCLIENT(e)
+                       Send_CSQC_Centerprint_Generic_Expire(e, CPID_ROUND_STARTING);
+               round_handler.cnt = round_handler.count + 1;
+       }
+       round_handler.nextthink = 0;
+}
+
+void round_handler_Remove()
+{
+       remove(round_handler);
+}
+
diff --git a/qcsrc/server/round_handler.qh b/qcsrc/server/round_handler.qh
new file mode 100644 (file)
index 0000000..7388b1a
--- /dev/null
@@ -0,0 +1,17 @@
+entity round_handler;
+.float delay; // stores delay from round end to countdown start
+.float count; // stores initial number of the countdown
+.float wait; // it's set to TRUE when round ends, to FALSE when countdown starts
+.float cnt;    // its initial value is .count + 1, then decreased while counting down
+                       // reaches 0 when the round starts
+.float() canRoundStart;
+.float() canRoundEnd;
+
+void round_handler_Spawn(float() canRoundStart_func, float() canRoundEnd_func, float the_delay, float the_count);
+float round_handler_IsActive();
+float round_handler_AwaitingNextRound();
+float round_handler_CountdownRunning();
+float round_handler_IsRoundStarted();
+void round_handler_Stop();
+void round_handler_Remove();
+