]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_freezetag.qc
Restore functionality of g_ca_round_timelimit and add g_freezetag_round_timelimit
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_freezetag.qc
index 1aad9d3c890b0dafb69f492878ad3bfa04638c52..f2e624c56325826affe75d0f4420d4ef43b71c48 100644 (file)
@@ -1,3 +1,4 @@
+float freezetag_teams;
 float freezetag_CheckTeams();
 float freezetag_CheckWinner();
 void freezetag_Initialize()
@@ -5,7 +6,7 @@ void freezetag_Initialize()
        precache_model("models/ice/ice.md3");
        ScoreRules_freezetag();
 
-       round_handler_Spawn(freezetag_CheckTeams, freezetag_CheckWinner, 5, autocvar_g_freezetag_warmup);
+       round_handler_Spawn(freezetag_CheckTeams, freezetag_CheckWinner, 5, autocvar_g_freezetag_warmup, autocvar_g_freezetag_round_timelimit);
 
        addstat(STAT_REDALIVE, AS_INT, redalive_stat);
        addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
@@ -49,24 +50,14 @@ void freezetag_count_alive_players()
                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 1; // we still have active players on two or more teams, nobody won yet
-       return 0;
-}
+#define FREEZETAG_ALIVE_TEAMS() ((redalive > 0) + (bluealive > 0) + (yellowalive > 0) + (pinkalive > 0))
+#define FREEZETAG_ALIVE_TEAMS_OK() (FREEZETAG_ALIVE_TEAMS() == freezetag_teams)
 
 float prev_total_players;
 float freezetag_CheckTeams()
 {
        entity e;
-       if(freezetag_TeamsCanPlay())
+       if(FREEZETAG_ALIVE_TEAMS_OK())
        {
                if(prev_total_players != -1)
                {
@@ -81,6 +72,10 @@ float freezetag_CheckTeams()
                string teams_missing;
                if(!redalive)   teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM1), ", ");
                if(!bluealive)  teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM2), ", ");
+               if(freezetag_teams >= 3)
+               if(!yellowalive)        teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM3), ", ");
+               if(freezetag_teams == 4)
+               if(!pinkalive)  teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM4), ", ");
                teams_missing = substring(teams_missing, 0, strlen(teams_missing)-2);
 
                FOR_EACH_REALCLIENT(e)
@@ -89,31 +84,62 @@ float freezetag_CheckTeams()
        }
        return 0;
 }
-float freezetag_CheckWinner()
-{
-       if(freezetag_TeamsCanPlay())
-               return 0;
 
-       entity e, winner;
-       string teamname;
-       winner = world;
+float freezetag_getWinnerTeam()
+{
+       float winner_team;
+       if(redalive >= 1)
+               winner_team = COLOR_TEAM1;
+       if(bluealive >= 1)
+       {
+               if(winner_team) return 0;
+               winner_team = COLOR_TEAM2;
+       }
+       if(yellowalive >= 1)
+       {
+               if(winner_team) return 0;
+               winner_team = COLOR_TEAM3;
+       }
+       if(pinkalive >= 1)
+       {
+               if(winner_team) return 0;
+               winner_team = COLOR_TEAM4;
+       }
+       if(winner_team)
+               return winner_team;
+       return -1; // no player left
+}
 
-       FOR_EACH_PLAYER(e)
+float freezetag_CheckWinner()
+{
+       entity e;
+       if(round_handler_GetTimeLeft() <= 0)
        {
-               if(e.freezetag_frozen == 0 && e.health >= 1) // here's one player from the winning team... good
-               {
-                       winner = e;
-                       break; // break, we found the winner
-               }
+               FOR_EACH_REALCLIENT(e)
+                       centerprint(e, "Round over, there's no winner");
+               bprint("Round over, there's no winner.\n");
+               return 1;
        }
 
-       if(winner != world) // just in case a winner wasn't found
+       if(FREEZETAG_ALIVE_TEAMS() > 1)
+               return 0;
+
+       float winner_team;
+       string teamname;
+       winner_team = freezetag_getWinnerTeam();
+       if(winner_team > 0)
        {
-               teamname = ColoredTeamName(winner.team);
+               teamname = ColoredTeamName(winner_team);
                FOR_EACH_REALCLIENT(e)
                        centerprint(e, strcat(teamname, "^5 wins the round, all other teams were frozen."));
                bprint(teamname, "^5 wins the round since all the other teams were frozen.\n");
-               TeamScore_AddToTeam(winner.team, ST_SCORE, +1);
+               TeamScore_AddToTeam(winner_team, ST_SCORE, +1);
+       }
+       else if(winner_team == -1)
+       {
+               FOR_EACH_REALCLIENT(e)
+                       centerprint(e, "^5Round tied! All teams were frozen.");
+               bprint("^5Round tied! All teams were frozen.\n");
        }
 
        return 1;
@@ -328,28 +354,21 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerDies)
                return 1; // let the player die so that he can respawn whenever he wants
        }
 
-       switch(frag_deathtype)
+       // Cases DEATH_TEAMCHANGE and DEATH_AUTOTEAMCHANGE are needed to fix a bug whe
+       // you succeed changing team through the menu: you both really die (gibbing) and get frozen
+       if(ITEM_DAMAGE_NEEDKILL(frag_deathtype)
+               || frag_deathtype == DEATH_TEAMCHANGE || frag_deathtype == DEATH_AUTOTEAMCHANGE)
        {
-               case DEATH_HURTTRIGGER:
-               case DEATH_FALL:
-               case DEATH_DROWN:
-               case DEATH_LAVA:
-               case DEATH_SLIME:
-               case DEATH_SWAMP:
-               case DEATH_TEAMCHANGE:
-               case DEATH_AUTOTEAMCHANGE:
+               // let the player die, he will be automatically frozen when he respawns
+               if(!self.freezetag_frozen)
                {
-                       // let the player die, he will be automatically frozen when he respawns
-                       if(!self.freezetag_frozen)
-                       {
-                               freezetag_Add_Score(frag_attacker);
-                               freezetag_count_alive_players();
-                       }
-                       else
-                               freezetag_Unfreeze(world); // remove ice
-                       self.freezetag_frozen_timeout = -2; // freeze on respawn
-                       return 1;
+                       freezetag_Add_Score(frag_attacker);
+                       freezetag_count_alive_players();
                }
+               else
+                       freezetag_Unfreeze(world); // remove ice
+               self.freezetag_frozen_timeout = -2; // freeze on respawn
+               return 1;
        }
 
        if(self.freezetag_frozen)
@@ -390,9 +409,6 @@ MUTATOR_HOOKFUNCTION(freezetag_PlayerSpawn)
 
        freezetag_count_alive_players();
 
-       if(self.freezetag_frozen)
-               return 1;
-
        if(round_handler_IsActive())
        if(round_handler_IsRoundStarted())
        {
@@ -573,6 +589,23 @@ MUTATOR_HOOKFUNCTION(freezetag_BotRoles)
        return TRUE;
 }
 
+MUTATOR_HOOKFUNCTION(freezetag_SpectateCopy)
+{
+       self.freezetag_frozen = other.freezetag_frozen;
+       self.freezetag_revive_progress = other.freezetag_revive_progress;
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(freezetag_GetTeamCount)
+{
+       freezetag_teams = autocvar_g_freezetag_teams_override;
+       if(freezetag_teams < 2)
+               freezetag_teams = autocvar_g_freezetag_teams;
+       freezetag_teams = bound(2, freezetag_teams, 4);
+       ret_float = freezetag_teams;
+       return 0;
+}
+
 MUTATOR_DEFINITION(gamemode_freezetag)
 {
        MUTATOR_HOOK(MakePlayerObserver, freezetag_RemovePlayer, CBC_ORDER_ANY);
@@ -586,6 +619,8 @@ MUTATOR_DEFINITION(gamemode_freezetag)
        MUTATOR_HOOK(PlayerDamage_Calculate, freezetag_PlayerDamage_Calculate, CBC_ORDER_ANY);
        MUTATOR_HOOK(ForbidThrowCurrentWeapon, freezetag_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
        MUTATOR_HOOK(HavocBot_ChooseRule, freezetag_BotRoles, CBC_ORDER_ANY);
+       MUTATOR_HOOK(SpectateCopy, freezetag_SpectateCopy, CBC_ORDER_ANY);
+       MUTATOR_HOOK(GetTeamCount, freezetag_GetTeamCount, CBC_ORDER_EXCLUSIVE);
 
        MUTATOR_ONADD
        {