]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/mutators/gamemode_ca.qc
Merge branch 'master' into divVerent/4team_ctf
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / gamemode_ca.qc
index 291166fe7bf06c47cb662666386b7d5e4e85a2b0..d5ded0f546780a6b7ff1201c267e19637c0e4245 100644 (file)
@@ -9,22 +9,22 @@ void CA_count_alive_players()
        entity e;
        total_players = redalive = bluealive = yellowalive = pinkalive = 0;
        FOR_EACH_PLAYER(e) {
-               if(e.team == COLOR_TEAM1)
+               if(e.team == NUM_TEAM_1)
                {
                        ++total_players;
                        if (e.health >= 1) ++redalive;
                }
-               else if(e.team == COLOR_TEAM2)
+               else if(e.team == NUM_TEAM_2)
                {
                        ++total_players;
                        if (e.health >= 1) ++bluealive;
                }
-               else if(e.team == COLOR_TEAM3)
+               else if(e.team == NUM_TEAM_3)
                {
                        ++total_players;
                        if (e.health >= 1) ++yellowalive;
                }
-               else if(e.team == COLOR_TEAM4)
+               else if(e.team == NUM_TEAM_4)
                {
                        ++total_players;
                        if (e.health >= 1) ++pinkalive;
@@ -42,21 +42,21 @@ float CA_GetWinnerTeam()
 {
        float winner_team = 0;
        if(redalive >= 1)
-               winner_team = COLOR_TEAM1;
+               winner_team = NUM_TEAM_1;
        if(bluealive >= 1)
        {
                if(winner_team) return 0;
-               winner_team = COLOR_TEAM2;
+               winner_team = NUM_TEAM_2;
        }
        if(yellowalive >= 1)
        {
                if(winner_team) return 0;
-               winner_team = COLOR_TEAM3;
+               winner_team = NUM_TEAM_3;
        }
        if(pinkalive >= 1)
        {
                if(winner_team) return 0;
-               winner_team = COLOR_TEAM4;
+               winner_team = NUM_TEAM_4;
        }
        if(winner_team)
                return winner_team;
@@ -67,13 +67,12 @@ float CA_GetWinnerTeam()
 #define CA_ALIVE_TEAMS_OK() (CA_ALIVE_TEAMS() == ca_teams)
 float CA_CheckWinner()
 {
-       entity e;
-       if(round_handler_GetTimeLeft() <= 0)
+       if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0)
        {
-               FOR_EACH_REALCLIENT(e)
-                       centerprint(e, "Round over, there's no winner");
-               bprint("Round over, there's no winner.\n");
-               allowed_to_spawn = TRUE;
+               Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_OVER);
+               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_OVER);
+               allowed_to_spawn = FALSE;
+               round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
                return 1;
        }
 
@@ -81,25 +80,21 @@ float CA_CheckWinner()
        if(CA_ALIVE_TEAMS() > 1)
                return 0;
 
-       float winner_team;
-       string teamname;
-       winner_team = CA_GetWinnerTeam();
+       float winner_team = CA_GetWinnerTeam();
        if(winner_team > 0)
        {
-               teamname = ColoredTeamName(winner_team);
-               FOR_EACH_REALCLIENT(e)
-                       centerprint(e, strcat(teamname, " wins the round"));
-               bprint(teamname, " wins the round.\n");
-               TeamScore_AddToTeam(winner_team, ST_SCORE, +1);
+               Send_Notification(NOTIF_ALL, world, MSG_CENTER, APP_TEAM_NUM_4(winner_team, CENTER_ROUND_TEAM_WIN_));
+               Send_Notification(NOTIF_ALL, world, MSG_INFO, APP_TEAM_NUM_4(winner_team, INFO_ROUND_TEAM_WIN_));
+               TeamScore_AddToTeam(winner_team, ST_CA_ROUNDS, +1);
        }
        else if(winner_team == -1)
        {
-               FOR_EACH_REALCLIENT(e)
-                       centerprint(e, "Round tied");
-               bprint("Round tied.\n");
+               Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_ROUND_TIED);
+               Send_Notification(NOTIF_ALL, world, MSG_INFO, INFO_ROUND_TIED);
        }
 
-       allowed_to_spawn = TRUE;
+       allowed_to_spawn = FALSE;
+       round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
        return 1;
 }
 
@@ -114,32 +109,25 @@ void CA_RoundStart()
 float prev_total_players;
 float CA_CheckTeams()
 {
-       entity e;
        allowed_to_spawn = TRUE;
        CA_count_alive_players();
        if(CA_ALIVE_TEAMS_OK())
        {
-               if(prev_total_players != -1)
-               {
-                       FOR_EACH_REALCLIENT(e)
-                               Send_CSQC_Centerprint_Generic_Expire(e, CPID_WAITING_PLAYERS);
-               }
+               if(prev_total_players > 0)
+                       Kill_Notification(NOTIF_ALL, world, MSG_CENTER_CPID, CPID_MISSING_TEAMS);
                prev_total_players = -1;
                return 1;
        }
        if(prev_total_players != total_players)
        {
-               string teams_missing = "";
-               if(!redalive)   teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM1), ", ");
-               if(!bluealive)  teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM2), ", ");
+               float p1 = 0, p2 = 0, p3 = 0, p4 = 0;
+               if(!redalive) p1 = NUM_TEAM_1;
+               if(!bluealive) p2 = NUM_TEAM_2;
                if(ca_teams >= 3)
-               if(!yellowalive)        teams_missing = strcat(teams_missing, ColoredTeamName(COLOR_TEAM3), ", ");
-               if(ca_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)
-                       Send_CSQC_Centerprint_Generic(e, CPID_WAITING_PLAYERS, strcat("Waiting for players to join...\n\nNeed active players for: ", teams_missing), -1, 0);
+               if(!yellowalive) p3 = NUM_TEAM_3;
+               if(ca_teams >= 4)
+               if(!pinkalive) p4 = NUM_TEAM_4;
+               Send_Notification(NOTIF_ALL, world, MSG_CENTER, CENTER_MISSING_TEAMS, p1, p2, p3, p4);
                prev_total_players = total_players;
        }
        return 0;
@@ -147,16 +135,22 @@ float CA_CheckTeams()
 
 MUTATOR_HOOKFUNCTION(ca_PlayerSpawn)
 {
-       self.caplayer = TRUE;
+       self.caplayer = 1;
        return 1;
 }
 
 MUTATOR_HOOKFUNCTION(ca_PutClientInServer)
 {
-       if(clienttype(self) == CLIENTTYPE_BOT)
-               self.caplayer = TRUE;
        if(!allowed_to_spawn)
+       {
                self.classname = "observer";
+               if(!self.caplayer)
+               {
+                       self.caplayer = 0.5;
+                       if(IS_REAL_CLIENT(self))
+                               sprint(self, "You will join the game in the next round.\n");
+               }
+       }
        return 1;
 }
 
@@ -167,6 +161,7 @@ MUTATOR_HOOKFUNCTION(ca_reset_map_players)
                if(self.caplayer)
                {
                        self.classname = "player";
+                       self.caplayer = 1;
                        PutClientInServer();
                }
        }
@@ -187,18 +182,14 @@ MUTATOR_HOOKFUNCTION(ca_reset_map_global)
 
 MUTATOR_HOOKFUNCTION(ca_GetTeamCount)
 {
-       ca_teams = autocvar_g_ca_teams_override;
-       if(ca_teams < 2)
-               ca_teams = autocvar_g_ca_teams;
-       ca_teams = bound(2, ca_teams, 4);
        ret_float = ca_teams;
-       return 1;
+       return 0;
 }
 
-MUTATOR_HOOKFUNCTION(ca_PlayerPreThink)
+MUTATOR_HOOKFUNCTION(ca_PlayerDies)
 {
        if(!allowed_to_spawn)
-               self.stat_respawn_time = 0;
+               self.respawn_flags =  RESPAWN_SILENT;
        return 1;
 }
 
@@ -209,6 +200,8 @@ MUTATOR_HOOKFUNCTION(ca_ForbidPlayerScore_Clear)
 
 MUTATOR_HOOKFUNCTION(ca_MakePlayerObserver)
 {
+       if(self.killindicator_teamchange == -2)
+               self.caplayer = 0;
        if(self.caplayer)
                self.frags = FRAGS_LMS_LOSER;
        return 1;
@@ -225,11 +218,82 @@ MUTATOR_HOOKFUNCTION(ca_GiveFragsForKill)
        return 1;
 }
 
+MUTATOR_HOOKFUNCTION(ca_SetStartItems)
+{
+       start_health = cvar("g_lms_start_health");
+       start_armorvalue = cvar("g_lms_start_armor");
+
+       start_ammo_shells = cvar("g_lms_start_ammo_shells");
+       start_ammo_nails = cvar("g_lms_start_ammo_nails");
+       start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
+       start_ammo_cells = cvar("g_lms_start_ammo_cells");
+       start_ammo_fuel = cvar("g_lms_start_ammo_fuel");
+       
+       start_items &~= IT_UNLIMITED_AMMO;
+
+       return 0;
+}
+
+MUTATOR_HOOKFUNCTION(ca_PlayerDamage)
+{
+       if(IS_PLAYER(frag_target))
+       if(frag_target.deadflag == DEAD_NO)
+       if(frag_target == frag_attacker || !IsDifferentTeam(frag_target, frag_attacker) || frag_deathtype == DEATH_FALL)
+               frag_damage = 0;
+               
+       frag_mirrordamage = 0;
+               
+       return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(ca_FilterItem)
+{
+       if(autocvar_g_powerups <= 0)
+       if(self.flags & FL_POWERUP)
+               return TRUE;
+               
+       if(autocvar_g_pickup_items <= 0)
+               return TRUE;
+               
+       return FALSE;
+}
+
+MUTATOR_HOOKFUNCTION(ca_PlayerDamage_SplitHealthArmor)
+{
+       float excess = max(0, frag_damage - damage_take - damage_save);
+       
+       if(frag_target != frag_attacker && IS_PLAYER(frag_attacker))
+               PlayerTeamScore_Add(frag_attacker, SP_SCORE, ST_SCORE, (frag_damage - excess) * autocvar_g_ca_damage2score_multiplier);
+               
+       return FALSE;
+}
+
+// scoreboard setup
+void ca_ScoreRules()
+{
+       ScoreRules_basics(2, SFL_SORT_PRIO_PRIMARY, 0, TRUE);
+       ScoreInfo_SetLabel_TeamScore  (ST_CA_ROUNDS,    "rounds",    SFL_SORT_PRIO_PRIMARY);
+       ScoreRules_basics_end();
+}
+
+void ca_DelayedInit() // Do this check with a delay so we can wait for teams to be set up.
+{
+       ca_ScoreRules();
+}
+
 void ca_Initialize()
 {
        allowed_to_spawn = TRUE;
 
-       round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, CA_RoundStart, 5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
+       ca_teams = autocvar_g_ca_teams_override;
+       if(ca_teams < 2)
+               ca_teams = autocvar_g_ca_teams;
+       ca_teams = bound(2, ca_teams, 4);
+       ret_float = ca_teams;
+       ScoreRules_ca(ca_teams);
+
+       round_handler_Spawn(CA_CheckTeams, CA_CheckWinner, CA_RoundStart);
+       round_handler_Init(5, autocvar_g_ca_warmup, autocvar_g_ca_round_timelimit);
 
        addstat(STAT_REDALIVE, AS_INT, redalive_stat);
        addstat(STAT_BLUEALIVE, AS_INT, bluealive_stat);
@@ -246,10 +310,14 @@ MUTATOR_DEFINITION(gamemode_ca)
        MUTATOR_HOOK(reset_map_global, ca_reset_map_global, CBC_ORDER_ANY);
        MUTATOR_HOOK(reset_map_players, ca_reset_map_players, CBC_ORDER_ANY);
        MUTATOR_HOOK(GetTeamCount, ca_GetTeamCount, CBC_ORDER_EXCLUSIVE);
-       MUTATOR_HOOK(PlayerPreThink, ca_PlayerPreThink, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerDies, ca_PlayerDies, CBC_ORDER_ANY);
        MUTATOR_HOOK(ForbidPlayerScore_Clear, ca_ForbidPlayerScore_Clear, CBC_ORDER_ANY);
        MUTATOR_HOOK(ForbidThrowCurrentWeapon, ca_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
        MUTATOR_HOOK(GiveFragsForKill, ca_GiveFragsForKill, CBC_ORDER_FIRST);
+       MUTATOR_HOOK(SetStartItems, ca_SetStartItems, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerDamage_Calculate, ca_PlayerDamage, CBC_ORDER_ANY);
+       MUTATOR_HOOK(FilterItem, ca_FilterItem, CBC_ORDER_ANY);
+       MUTATOR_HOOK(PlayerDamage_SplitHealthArmor, ca_PlayerDamage_SplitHealthArmor, CBC_ORDER_ANY);
 
        MUTATOR_ONADD
        {