]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/arena.qc
Merge remote branch 'origin/terencehill/powerups_respawntime_fix'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / arena.qc
index c95396332f45106f404c68c2c549dc56b71f6a44..ef81fd92bad7db138edb2fa1e1067d252bae875b 100644 (file)
@@ -8,29 +8,18 @@ float arena_roundbased;
 entity spawnqueue_first;
 entity spawnqueue_last;
 entity champion;
-string champion_name;
 float warmup;
-float ca_players;
-float required_ca_players;
 .float caplayer;
 
 void PutObserverInServer();
 void PutClientInServer();
-void(entity e) ReturnFlag;
-void dom_controlpoint_setup();
-void onslaught_generator_reset();
-void onslaught_controlpoint_reset();
-void func_breakable_reset();
-void assault_objective_reset();
-void target_assault_roundend_reset();
 
 float next_round;
-float stopalivecheck;
 float redalive, bluealive, yellowalive, pinkalive;
 float totalalive;
 .float redalive_stat, bluealive_stat, yellowalive_stat, pinkalive_stat;
-float redspawned, bluespawned, yellowspawned, pinkspawned;
-float totalspawned;
+float red_players, blue_players, yellow_players, pink_players;
+float total_players;
 
 /**
  * Resets the state of all clients, items, flags, runes, keys, weapons, waypoints, ... of the map.
@@ -58,7 +47,7 @@ void reset_map(float dorespawn)
        race_ReadyRestart();
 
        for(self = world; (self = nextent(self)); )
-       if(clienttype(self) == CLIENTTYPE_NOTACLIENT && self.items != IT_STRENGTH && self.items != IT_INVINCIBLE) // don't respawn strength or shield, that will only lead to them spawning very early each match
+       if(clienttype(self) == CLIENTTYPE_NOTACLIENT)
        {
                if(self.reset)
                {
@@ -134,7 +123,7 @@ void reset_map(float dorespawn)
        }
 
        if(g_keyhunt)
-               kh_Controller_SetThink(autocvar_g_balance_keyhunt_delay_round+(game_starttime - time), "", kh_StartRound);
+               kh_Controller_SetThink_NoMsg(autocvar_g_balance_keyhunt_delay_round+(game_starttime - time), kh_StartRound);
 
        if(g_arena)
        if(champion && champion.classname == "player" && player_count > 1)
@@ -198,111 +187,131 @@ void Spawnqueue_Mark(entity e)
  * Blocks the players movement while countdown is active.
  * Unblocks the player once the countdown is over.
  *
- * Called in PlayerPostThink()
+ * Called in StartFrame()
  */
 float roundStartTime_prev; // prevent networkspam
 void Arena_Warmup()
 {
        float f;
-       string msg;
-    entity e;
+       entity e;
 
+       if(gameover)
+       {
+               if(warmup && time < warmup)
+               {
+                       FOR_EACH_REALCLIENT(e)
+                               Send_CSQC_Centerprint_Generic_Expire(e, CPID_ROUND_STARTING);
+                       warmup = 0;
+               }
+               if(champion && g_arena)
+               {
+                       FOR_EACH_REALCLIENT(e)
+                               centerprint(e, strcat("The Champion is ", champion.netname));
+                       champion = world;
+               }
+               return;
+       }
        if((!g_arena && !g_ca && !g_freezetag) || (g_arena && !arena_roundbased) || (time < game_starttime))
                return;
 
        f = ceil(warmup - time);
-       if(f > 0)
-               champion = world; // this is done because a if(champion) will not execute if champion = world
-
-       allowed_to_spawn = 0;
 
        if(inWarmupStage)
                allowed_to_spawn = 1;
-       if(ca_players < required_ca_players)
-               allowed_to_spawn = 1;
+       else if(!g_ca)
+               allowed_to_spawn = 0;
 
-       msg = NEWLINES;
        if(time < warmup && !inWarmupStage)
        {
                if (g_ca)
                        allowed_to_spawn = 1;
                if(champion && g_arena)
-                       msg = strcat("The Champion is ", champion_name, "^7\n");
-                       //centerprint(self, strcat(msg, "The Champion is ", champion.netname, "^7\n"));
+               {
+                       FOR_EACH_REALCLIENT(e)
+                               centerprint(e, strcat("The Champion is ", champion.netname));
+               }
 
                if(f != roundStartTime_prev) {
-                       msg = strcat(msg, "Round will start in ", ftos(f),"\n");
-                       //centerprint(self, strcat("Round will start in ", ftos(f),"\n"));
                        roundStartTime_prev = f;
-                       if(f == 5)
-                               Announce("prepareforbattle");
-                       else if(f == 3)
-                               Announce("3");
-                       else if(f == 2)
-                               Announce("2");
-                       else if(f == 1)
-                               Announce("1");
-
-            FOR_EACH_PLAYER(e)
-                centerprint(e, msg);
+                       if(g_ca && !(red_players && blue_players)) {
+                               FOR_EACH_REALCLIENT(self)
+                                       Send_CSQC_Centerprint_Generic(self, CPID_ROUND_STARTING, "^1Need at least 1 player in each team to play CA", 2, 0);
+                               warmup = time + autocvar_g_ca_warmup;
+                       } else {
+                               if(f == 5)
+                                       Announce("prepareforbattle");
+                               else if(f == 3)
+                                       Announce("3");
+                               else if(f == 2)
+                                       Announce("2");
+                               else if(f == 1)
+                                       Announce("1");
+
+                               FOR_EACH_REALCLIENT(e)
+                                       Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "Round will start in %d", 1, f);
+                       }
                }
 
                if (g_arena) {
-                       if(self.spawned && self.classname == "player")
-                               self.movetype = MOVETYPE_NONE;
-
-                       self.velocity = '0 0 0';
-                       self.avelocity = '0 0 0';
-                       self.movement = '0 0 0';
+                       FOR_EACH_CLIENT(e)
+                       {
+                               if(e.spawned && e.classname == "player")
+                                       e.player_blocked = 1;
+                       }
                }
        }
-
        else if(f > -1 && f != roundStartTime_prev)
        {
                roundStartTime_prev = f;
-               Announce("begin");
-               centerprint(self, "^1Begin!\n");
-
                if(g_ca) {
-                       ca_players = 0;
-
-            FOR_EACH_PLAYER(e)
-                               ca_players += 1;
+                       if(red_players && blue_players)
+                               allowed_to_spawn = 0;
+                       else
+                               reset_map(TRUE);
+               } else {
+                       Announce("begin");
+                       FOR_EACH_REALCLIENT(e)
+                               Send_CSQC_Centerprint_Generic(e, CPID_ROUND_STARTING, "^1Begin!", 1, 0);
                }
 
-        if(self.classname == "player" && self.health > 0 && self.movetype == MOVETYPE_NONE)
-            self.movetype = MOVETYPE_WALK;
+               if(g_arena) {
+                       FOR_EACH_CLIENT(e)
+                       {
+                               if(e.player_blocked)
+                                       e.player_blocked = 0;
+                       }
+               }
        }
+
+       // clear champion to avoid centerprinting again the champion msg
+       if (champion)
+               champion = world;
 }
 
-void count_spawned_players()
+void count_players()
 {
-       // TODO fix "*spawned" name, it should rather be "*players" or so
-       // not doing this now to prevent merge hell with Tag
-       // fix after merging with Tag
-
        // count amount of players in each team
-       totalspawned = redspawned = bluespawned = yellowspawned = pinkspawned = 0;
+       total_players = red_players = blue_players = yellow_players = pink_players = 0;
        FOR_EACH_PLAYER(self) {
                if (self.team == COLOR_TEAM1)
                {
-                       redspawned += 1;
-                       totalspawned += 1;
+                       red_players += 1;
+                       total_players += 1;
                }
                else if (self.team == COLOR_TEAM2)
                {
-                       bluespawned += 1;
-                       totalspawned += 1;
+                       blue_players += 1;
+                       total_players += 1;
                }
                else if (self.team == COLOR_TEAM3)
                {
-                       yellowspawned += 1;
-                       totalspawned += 1;
+                       yellow_players += 1;
+                       total_players += 1;
                }
                else if (self.team == COLOR_TEAM4)
                {
-                       pinkspawned += 1;
-                       totalspawned += 1;
+                       pink_players += 1;
+                       total_players += 1;
                }
        }
 }
@@ -373,60 +382,47 @@ void count_alive_players()
  */
 void Spawnqueue_Check()
 {
-       count_spawned_players();
-       if(g_ca || g_freezetag) // we want to perform this before the return block below (CA)...
+       if(warmup == 0 && g_ca && !inWarmupStage)
        {
-               count_alive_players();
+               if(red_players || blue_players)
+                       reset_map(TRUE);
+               return;
        }
        if(time < warmup + 1 || inWarmupStage || intermission_running)
                return;
 
        if(g_ca) {
-               required_ca_players = max(2, fabs(autocvar_bot_vs_human + 1));
-
-               if(ca_players < required_ca_players && (redspawned && bluespawned)) {
-                       reset_map(TRUE);
-               }
-               else if(ca_players < required_ca_players) {
-                       FOR_EACH_PLAYER(self)
-                               centerprint(self, strcat("^1Need at least 1 player in each team to play CA", "^7\n"));
+               if(allowed_to_spawn) // round is not started yet
                        return;
-               }
-               else if(!next_round) {
-                       if((redspawned && !bluespawned) || (bluespawned && !redspawned)) {
-                               next_round = time + 5;
-                               champion = find(world, classname, "player");
-                               if(champion_name)
-                                       strunzone(champion_name);
-                               champion_name = strzone(champion.netname);
+               if(!next_round) {
+                       if(!(redalive && bluealive)) {
+                               // every player of (at least) one team is dead, round ends here
+                               if(redalive) {
+                                       play2all("ctf/red_capture.wav");
+                                       FOR_EACH_CLIENT(self) centerprint(self, "^1RED ^7team wins the round");
+                                       TeamScore_AddToTeam(COLOR_TEAM1, ST_SCORE, +1);
+                               }
+                               else if(bluealive) {
+                                       play2all("ctf/blue_capture.wav");
+                                       FOR_EACH_CLIENT(self) centerprint(self, "^4BLUE ^7team wins the round");
+                                       TeamScore_AddToTeam(COLOR_TEAM2, ST_SCORE, +1);
+                               }
+                               else
+                                       FOR_EACH_CLIENT(self) centerprint(self, "^7Round tied");
+                               next_round = -1;
                        }
-                       else if((!redspawned && !bluespawned) || time - warmup > autocvar_g_ca_round_timelimit) {
-                               FOR_EACH_CLIENT(self) centerprint(self, strcat("^7Round tied.", "^7\n"));
+                       else if(time - warmup > autocvar_g_ca_round_timelimit) {
+                               FOR_EACH_CLIENT(self) centerprint(self, "^7Round tied");
                                next_round = time + 5;
                        }
-
                }
-               if(!stopalivecheck)
-               {
-                       if(redalive && !bluealive)
-                       {
-                               play2all("ctf/red_capture.wav");
-                               FOR_EACH_CLIENT(self) centerprint(self, "^1 RED ^7team wins the round.\n");
-                               TeamScore_AddToTeam(COLOR_TEAM1, ST_SCORE, +1);
-                               stopalivecheck = TRUE;
-                       }
-                       else if(bluealive && !redalive)
-                       {
-                               play2all("ctf/blue_capture.wav");
-                               FOR_EACH_CLIENT(self) centerprint(self, "^4 BLUE ^7team wins the round.\n");
-                               TeamScore_AddToTeam(COLOR_TEAM2, ST_SCORE, +1);
-                               stopalivecheck = TRUE;
-                       }
+               else if(next_round == -1) {
+                       // wait for killed players to be put as spectators
+                       if(!(red_players && blue_players))
+                               next_round = time + 5;
                }
-
-               if((next_round && next_round < time))
+               else if((next_round > 0 && next_round < time))
                {
-                       stopalivecheck = FALSE;
                        next_round = 0;
                        reset_map(TRUE);
                }