]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/g_world.qc
Merge branch 'master' into Lyberta/TeamplayOverhaul
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / g_world.qc
index 2eda8584ef5d82eeb9f346cb131aa9a049a58488..7cbbb95d59fa20b848b0ee8a1cfa53d1db4433e1 100644 (file)
@@ -145,12 +145,8 @@ void cvar_changes_init()
        string k, v, d;
        float n, i, adding, pureadding;
 
-       if(cvar_changes)
-               strunzone(cvar_changes);
-       cvar_changes = string_null;
-       if(cvar_purechanges)
-               strunzone(cvar_purechanges);
-       cvar_purechanges = string_null;
+       strfree(cvar_changes);
+       strfree(cvar_purechanges);
        cvar_purechanges_count = 0;
 
        h = buf_create();
@@ -253,6 +249,7 @@ void cvar_changes_init()
                // these can contain player IDs, so better hide
                BADPREFIX("g_forced_team_");
                BADCVAR("sv_muteban_list");
+               BADCVAR("sv_voteban_list");
                BADCVAR("sv_allow_customplayermodels_idlist");
                BADCVAR("sv_allow_customplayermodels_speciallist");
 
@@ -613,6 +610,57 @@ STATIC_INIT_EARLY(maxclients)
        }
 }
 
+void default_delayedinit(entity this)
+{
+       if(!scores_initialized)
+               ScoreRules_generic();
+}
+
+void InitGameplayMode()
+{
+       VoteReset();
+
+       // find out good world mins/maxs bounds, either the static bounds found by looking for solid, or the mapinfo specified bounds
+       get_mi_min_max(1);
+       // assign reflectively to avoid "assignment to world" warning
+       int done = 0; for (int i = 0, n = numentityfields(); i < n; ++i) {
+           string k = entityfieldname(i); vector v = (k == "mins") ? mi_min : (k == "maxs") ? mi_max : '0 0 0';
+           if (v) {
+            putentityfieldstring(i, world, sprintf("%v", v));
+            if (++done == 2) break;
+        }
+       }
+       // currently, NetRadiant's limit is 131072 qu for each side
+       // distance from one corner of a 131072qu cube to the opposite corner is approx. 227023 qu
+       // set the distance according to map size but don't go over the limit to avoid issues with float precision
+       // in case somebody makes extremely large maps
+       max_shot_distance = min(230000, vlen(world.maxs - world.mins));
+
+       MapInfo_LoadMapSettings(mapname);
+       GameRules_teams(false);
+
+       if (!cvar_value_issafe(world.fog))
+       {
+               LOG_INFO("The current map contains a potentially harmful fog setting, ignored");
+               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();
+
+       gamemode_name = MapInfo_Type_ToText(MapInfo_LoadedGametype);
+
+       cache_mutatormsg = strzone("");
+       cache_lastmutatormsg = strzone("");
+
+       InitializeEntity(NULL, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK);
+}
+
 void Map_MarkAsRecent(string m);
 float world_already_spawned;
 void Nagger_Init();
@@ -990,45 +1038,43 @@ float GetMaplistPosition()
        return idx;
 }
 
-float MapHasRightSize(string map)
+bool MapHasRightSize(string map)
 {
-       float fh;
        if(currentbots || autocvar_bot_number || player_count < autocvar_minplayers)
        if(autocvar_g_maplist_check_waypoints)
        {
-               LOG_TRACE("checkwp "); LOG_TRACE(map);
+               string checkwp_msg = strcat("checkwp ", map);
                if(!fexists(strcat("maps/", map, ".waypoints")))
                {
-                       LOG_TRACE(": no waypoints");
+                       LOG_TRACE(checkwp_msg, ": no waypoints");
                        return false;
                }
-               LOG_TRACE(": has waypoints");
+               LOG_TRACE(checkwp_msg, ": has waypoints");
        }
 
        // open map size restriction file
-       LOG_TRACE("opensize "); LOG_TRACE(map);
-       fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
+       string opensize_msg = strcat("opensize ", map);
+       float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
        if(fh >= 0)
        {
-               float mapmin, mapmax;
-               LOG_TRACE(": ok, ");
-               mapmin = stof(fgets(fh));
-               mapmax = stof(fgets(fh));
+               opensize_msg = strcat(opensize_msg, ": ok, ");
+               int mapmin = stoi(fgets(fh));
+               int mapmax = stoi(fgets(fh));
                fclose(fh);
                if(player_count < mapmin)
                {
-                       LOG_TRACE("not enough");
+                       LOG_TRACE(opensize_msg, "not enough");
                        return false;
                }
-               if(player_count > mapmax)
+               if(mapmax && player_count > mapmax)
                {
-                       LOG_TRACE("too many");
+                       LOG_TRACE(opensize_msg, "too many");
                        return false;
                }
-               LOG_TRACE("right size");
+               LOG_TRACE(opensize_msg, "right size");
                return true;
        }
-       LOG_TRACE(": not found");
+       LOG_TRACE(opensize_msg, ": not found");
        return true;
 }
 
@@ -1201,9 +1247,7 @@ void Maplist_Init()
                error("empty maplist, cannot select a new map");
        Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
 
-       if(Map_Current_Name)
-               strunzone(Map_Current_Name);
-       Map_Current_Name = strzone(argv(Map_Current)); // will be automatically freed on exit thanks to DP
+       strcpy(Map_Current_Name, argv(Map_Current)); // will be automatically freed on exit thanks to DP
        // this may or may not be correct, but who cares, in the worst case a map
        // isn't chosen in the first pass that should have been
 }
@@ -1692,10 +1736,11 @@ float WinningCondition_Scores(float limit, float leadlimit)
 
        if(teamplay)
        {
-               team1_score = TeamScore_GetCompareValue(NUM_TEAM_1);
-               team2_score = TeamScore_GetCompareValue(NUM_TEAM_2);
-               team3_score = TeamScore_GetCompareValue(NUM_TEAM_3);
-               team4_score = TeamScore_GetCompareValue(NUM_TEAM_4);
+               for (int i = 1; i < 5; ++i)
+               {
+                       Team_SetTeamScore(Team_GetTeamFromIndex(i),
+                               TeamScore_GetCompareValue(Team_IndexToTeam(i)));
+               }
        }
 
        ClearWinners();
@@ -1765,30 +1810,32 @@ float WinningCondition_RanOutOfSpawns()
        if(!some_spawn_has_been_used)
                return WINNING_NO;
 
-       team1_score = team2_score = team3_score = team4_score = 0;
-
-       FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), {
-               switch(it.team)
+       for (int i = 1; i < 5; ++i)
+       {
+               Team_SetTeamScore(Team_GetTeamFromIndex(i), 0);
+       }
+       
+       FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
+       {
+               if (Team_IsValidTeam(it.team))
                {
-                       case NUM_TEAM_1: team1_score = 1; break;
-                       case NUM_TEAM_2: team2_score = 1; break;
-                       case NUM_TEAM_3: team3_score = 1; break;
-                       case NUM_TEAM_4: team4_score = 1; break;
+                       Team_SetTeamScore(Team_GetTeam(it.team), 1);
                }
        });
 
        IL_EACH(g_spawnpoints, true,
        {
-               switch(it.team)
+               if (Team_IsValidTeam(it.team))
                {
-                       case NUM_TEAM_1: team1_score = 1; break;
-                       case NUM_TEAM_2: team2_score = 1; break;
-                       case NUM_TEAM_3: team3_score = 1; break;
-                       case NUM_TEAM_4: team4_score = 1; break;
+                       Team_SetTeamScore(Team_GetTeam(it.team), 1);
                }
        });
 
        ClearWinners();
+       float team1_score = Team_GetTeamScore(Team_GetTeamFromIndex(1));
+       float team2_score = Team_GetTeamScore(Team_GetTeamFromIndex(2));
+       float team3_score = Team_GetTeamScore(Team_GetTeamFromIndex(3));
+       float team4_score = Team_GetTeamScore(Team_GetTeamFromIndex(4));
        if(team1_score + team2_score + team3_score + team4_score == 0)
        {
                checkrules_equality = true;
@@ -1798,20 +1845,28 @@ float WinningCondition_RanOutOfSpawns()
        {
                float t, i;
                if(team1_score)
-                       t = NUM_TEAM_1;
+                       t = 1;
                else if(team2_score)
-                       t = NUM_TEAM_2;
+                       t = 2;
                else if(team3_score)
-                       t = NUM_TEAM_3;
+                       t = 3;
                else // if(team4_score)
-                       t = NUM_TEAM_4;
-               CheckAllowedTeams(NULL);
+                       t = 4;
+               entity balance = TeamBalance_CheckAllowedTeams(NULL);
                for(i = 0; i < MAX_TEAMSCORE; ++i)
                {
-                       if(t != NUM_TEAM_1) if(c1 >= 0) TeamScore_AddToTeam(NUM_TEAM_1, i, -1000);
-                       if(t != NUM_TEAM_2) if(c2 >= 0) TeamScore_AddToTeam(NUM_TEAM_2, i, -1000);
-                       if(t != NUM_TEAM_3) if(c3 >= 0) TeamScore_AddToTeam(NUM_TEAM_3, i, -1000);
-                       if(t != NUM_TEAM_4) if(c4 >= 0) TeamScore_AddToTeam(NUM_TEAM_4, i, -1000);
+                       for (int j = 1; j <= NUM_TEAMS; ++j)
+                       {
+                               if (t == j)
+                               {
+                                       continue;
+                               }
+                               if (!TeamBalance_IsTeamAllowed(balance, j))
+                               {
+                                       continue;
+                               }
+                               TeamScore_AddToTeam(Team_IndexToTeam(j), i, -1000);
+                       }
                }
 
                AddWinners(team, t);
@@ -2069,12 +2124,12 @@ void EndFrame()
        FOREACH_CLIENT(IS_REAL_CLIENT(it), {
                entity e = IS_SPEC(it) ? it.enemy : it;
                if (e.typehitsound) {
-                       it.typehit_time = time;
+                       STAT(TYPEHIT_TIME, it) = time;
                } else if (e.killsound) {
-                       it.kill_time = time;
+                       STAT(KILL_TIME, it) = time;
                } else if (e.damage_dealt) {
-                       it.hit_time = time;
-                       it.damage_dealt_total += ceil(e.damage_dealt);
+                       STAT(HIT_TIME, it) = time;
+                       STAT(DAMAGE_DEALT_TOTAL, it) += ceil(e.damage_dealt);
                }
        });
        // add 1 frametime because after this, engine SV_Physics