]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_world.qc
Merge branch 'terencehill/minplayers_per_team' into 'master'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_world.qc
index b063981ee282d7840ed7e2d246abd97d4a4e50a9..cf4128ddd2f675b998d0ba76116518237be6a9c2 100644 (file)
 #include "g_hook.qh"
 #include "ipban.qh"
 #include "mapvoting.qh"
-#include "mutators/_mod.qh"
+#include <server/mutators/_mod.qh>
 #include "race.qh"
 #include "scores.qh"
+#include "scores_rules.qh"
 #include "teamplay.qh"
 #include "weapons/weaponstats.qh"
 #include "../common/constants.qh"
 #include <common/net_linked.qh>
 #include "../common/deathtypes/all.qh"
+#include "../common/gamemodes/sv_rules.qh"
 #include "../common/mapinfo.qh"
 #include "../common/monsters/_mod.qh"
 #include "../common/monsters/sv_monsters.qh"
@@ -91,9 +93,6 @@ const float SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS = 1;
 string redirection_target;
 float world_initialized;
 
-string GetGametype();
-void ShuffleMaplist();
-
 void SetDefaultAlpha()
 {
        if (!MUTATOR_CALLHOOK(SetDefaultAlpha))
@@ -266,6 +265,7 @@ void cvar_changes_init()
                BADCVAR("g_dm");
                BADCVAR("g_domination");
                BADCVAR("g_domination_default_teams");
+               BADCVAR("g_duel");
                BADCVAR("g_freezetag");
                BADCVAR("g_freezetag_teams");
                BADCVAR("g_invasion_teams");
@@ -358,10 +358,12 @@ void cvar_changes_init()
                BADCVAR("sv_stepheight");
                BADCVAR("sv_timeout");
                BADCVAR("sv_weapons_modeloverride");
+               BADCVAR("w_prop_interval");
                BADPREFIX("crypto_");
                BADPREFIX("gameversion_");
                BADPREFIX("g_chat_");
                BADPREFIX("g_ctf_captimerecord_");
+               BADPREFIX("g_hats_");
                BADPREFIX("g_maplist_");
                BADPREFIX("g_mod_");
                BADPREFIX("g_respawn_");
@@ -429,6 +431,7 @@ void cvar_changes_init()
                BADCVAR("log_file");
                BADCVAR("maxplayers");
                BADCVAR("minplayers");
+               BADCVAR("minplayers_per_team");
                BADCVAR("net_address");
                BADCVAR("port");
                BADCVAR("rcon_password");
@@ -613,10 +616,12 @@ void InitGameplayMode()
                world.fog = string_null;
        }
        if(MapInfo_Map_fog != "")
+       {
                if(MapInfo_Map_fog == "none")
                        world.fog = string_null;
                else
                        world.fog = strzone(MapInfo_Map_fog);
+       }
        clientstuff = strzone(MapInfo_Map_clientstuff);
 
        MapInfo_ClearTemps();
@@ -631,10 +636,6 @@ void InitGameplayMode()
 
 void Map_MarkAsRecent(string m);
 float world_already_spawned;
-void Nagger_Init();
-void ClientInit_Spawn();
-void WeaponStats_Init();
-void WeaponStats_Shutdown();
 spawnfunc(worldspawn)
 {
        server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
@@ -924,7 +925,7 @@ spawnfunc(worldspawn)
                        s = cons(s, pkg);
                }
                // add automatically managed files to the list
-               #define X(match) MACRO_BEGIN \
+               #define X(match) MACRO_BEGIN \
                        int fd = search_begin(match, true, false); \
                        if (fd >= 0) \
                        { \
@@ -934,7 +935,7 @@ spawnfunc(worldspawn)
                                } \
                                search_end(fd); \
                        } \
-               MACRO_END
+               MACRO_END
                X("*-serverpackage.txt");
                X("*.serverpackage");
                #undef X
@@ -1006,8 +1007,11 @@ float GetMaplistPosition()
 
 bool MapHasRightSize(string map)
 {
-       if(currentbots || autocvar_bot_number || player_count < autocvar_minplayers)
-       if(autocvar_g_maplist_check_waypoints)
+       int minplayers = max(0, floor(autocvar_minplayers));
+       if (teamplay)
+               minplayers = max(0, floor(autocvar_minplayers_per_team) * AvailableTeams());
+       if (autocvar_g_maplist_check_waypoints
+               && (currentbots || autocvar_bot_number || player_count < minplayers))
        {
                string checkwp_msg = strcat("checkwp ", map);
                if(!fexists(strcat("maps/", map, ".waypoints")))
@@ -1108,7 +1112,7 @@ void Map_Goto(float reinit)
 // return codes of map selectors:
 //   -1 = temporary failure (that is, try some method that is guaranteed to succeed)
 //   -2 = permanent failure
-float() MaplistMethod_Iterate = // usual method
+float MaplistMethod_Iterate() // usual method
 {
        float pass, i;
 
@@ -1127,7 +1131,7 @@ float() MaplistMethod_Iterate = // usual method
        return -1;
 }
 
-float() MaplistMethod_Repeat = // fallback method
+float MaplistMethod_Repeat() // fallback method
 {
        LOG_TRACE("Trying MaplistMethod_Repeat");
 
@@ -1136,7 +1140,7 @@ float() MaplistMethod_Repeat = // fallback method
        return -2;
 }
 
-float() MaplistMethod_Random = // random map selection
+float MaplistMethod_Random() // random map selection
 {
        float i, imax;
 
@@ -1154,7 +1158,7 @@ float() MaplistMethod_Random = // random map selection
        return -1;
 }
 
-float(float exponent) MaplistMethod_Shuffle = // more clever shuffling
+float MaplistMethod_Shuffle(float exponent) // more clever shuffling
 // the exponent sets a bias on the map selection:
 // the higher the exponent, the less likely "shortly repeated" same maps are
 {
@@ -1523,7 +1527,7 @@ void FixIntermissionClient(entity e)
        if(!e.autoscreenshot) // initial call
        {
                e.autoscreenshot = time + 0.8;  // used for autoscreenshot
-               e.health = -2342;
+               SetResourceExplicit(e, RES_HEALTH, -2342);
                // first intermission phase; voting phase has positive health (used to decide whether to send SVC_FINALE or not)
                for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
@@ -1614,7 +1618,9 @@ float InitiateSuddenDeath()
        // - for this timelimit_overtime needs to be >0 of course
        // - also check the winning condition calculated in the previous frame and only add normal overtime
        //   again, if at the point at which timelimit would be extended again, still no winner was found
-       if (!autocvar_g_campaign && (checkrules_overtimesadded >= 0) && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0) && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
+       if (!autocvar_g_campaign && checkrules_overtimesadded >= 0
+               && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0)
+               && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
        {
                return 1; // need to call InitiateOvertime later
        }
@@ -1637,33 +1643,36 @@ void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
 {
        ++checkrules_overtimesadded;
        //add one more overtime by simply extending the timelimit
-       float tl;
-       tl = autocvar_timelimit;
-       tl += autocvar_timelimit_overtime;
-       cvar_set("timelimit", ftos(tl));
-
+       cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
        Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
 }
 
 float GetWinningCode(float fraglimitreached, float equality)
 {
        if(autocvar_g_campaign == 1)
+       {
                if(fraglimitreached)
                        return WINNING_YES;
                else
                        return WINNING_NO;
-
+       }
        else
+       {
                if(equality)
+               {
                        if(fraglimitreached)
                                return WINNING_STARTSUDDENDEATHOVERTIME;
                        else
                                return WINNING_NEVER;
+               }
                else
+               {
                        if(fraglimitreached)
                                return WINNING_YES;
                        else
                                return WINNING_NO;
+               }
+       }
 }
 
 // set the .winning flag for exactly those players with a given field value
@@ -1733,19 +1742,20 @@ float WinningCondition_Scores(float limit, float leadlimit)
                        leaderfrags = WinningConditionHelper_topscore;
 
                        if (limit)
-                       if (leaderfrags == limit - 1)
-                               Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
-                       else if (leaderfrags == limit - 2)
-                               Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
-                       else if (leaderfrags == limit - 3)
-                               Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
+                       {
+                               if (leaderfrags == limit - 1)
+                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
+                               else if (leaderfrags == limit - 2)
+                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
+                               else if (leaderfrags == limit - 3)
+                                       Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
+                       }
                }
        }
 
        limitreached = false;
-       if(limit)
-               if(WinningConditionHelper_topscore >= limit)
-                       limitreached = true;
+       if (limit && WinningConditionHelper_topscore >= limit)
+               limitreached = true;
        if(leadlimit)
        {
                float leadlimitreached;
@@ -1780,7 +1790,7 @@ float WinningCondition_RanOutOfSpawns()
        {
                Team_SetTeamScore(Team_GetTeamFromIndex(i), 0);
        }
-       
+
        FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
        {
                if (Team_IsValidTeam(it.team))
@@ -2170,7 +2180,6 @@ float RedirectionThink()
        return true;
 }
 
-void TargetMusic_RestoreGame();
 void RestoreGame()
 {
        // Loaded from a save game