]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blobdiff - qcsrc/server/world.qc
Merge branch 'Mario/monsters' into 'develop'
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / world.qc
index 5e297be46161363ce18c364e1bc4ce0f7d43f8fa..55195217250186bf498db837ac07b236503f3d1b 100644 (file)
@@ -35,7 +35,6 @@
 #include <server/damage.qh>
 #include <server/gamelog.qh>
 #include <server/hook.qh>
-#include <server/intermission.qh>
 #include <server/ipban.qh>
 #include <server/items/items.qh>
 #include <server/main.qh>
@@ -46,7 +45,6 @@
 #include <server/scores_rules.qh>
 #include <server/spawnpoints.qh>
 #include <server/teamplay.qh>
-#include <server/weapons/common.qh>
 #include <server/weapons/weaponstats.qh>
 
 const float LATENCY_THINKRATE = 10;
@@ -279,7 +277,6 @@ void cvar_changes_init()
                BADCVAR("g_duel_not_dm_maps");
                BADCVAR("g_freezetag");
                BADCVAR("g_freezetag_teams");
-               BADCVAR("g_invasion_teams");
                BADCVAR("g_invasion_type");
                BADCVAR("g_jailbreak");
                BADCVAR("g_jailbreak_teams");
@@ -495,6 +492,7 @@ void cvar_changes_init()
                BADCVAR("sv_motd");
                BADCVAR("sv_public");
                BADCVAR("sv_showfps");
+               BADCVAR("sv_showspectators");
                BADCVAR("sv_status_privacy");
                BADCVAR("sv_taunt");
                BADCVAR("sv_vote_call");
@@ -820,11 +818,11 @@ spawnfunc(worldspawn)
 
        if(autocvar_g_campaign)
                CampaignPreInit();
+       else
+               PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
 
        Map_MarkAsRecent(mapname);
 
-       PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
-
        InitGameplayMode();
        static_init_late();
        static_init_precache();
@@ -843,46 +841,15 @@ spawnfunc(worldspawn)
 
        WaypointSprite_Init();
 
-       GameLogInit(); // prepare everything
        // NOTE for matchid:
        // changing the logic generating it is okay. But:
        // it HAS to stay <= 64 chars
        // character set: ASCII 33-126 without the following characters: : ; ' " \ $
-       if(autocvar_sv_eventlog)
-       {
-               string num = strftime_s(); // strftime(false, "%s") isn't reliable, see strftime_s description
-               string s = sprintf("%s.%s.%06d", itos(autocvar_sv_eventlog_files_counter), num, floor(random() * 1000000));
-               matchid = strzone(s);
-
-               GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
-               s = ":gameinfo:mutators:LIST";
-
-               MUTATOR_CALLHOOK(BuildMutatorsString, s);
-               s = M_ARGV(0, string);
-
-               // initialiation stuff, not good in the mutator system
-               if(!autocvar_g_use_ammunition)
-                       s = strcat(s, ":no_use_ammunition");
-
-               // initialiation stuff, not good in the mutator system
-               if(autocvar_g_pickup_items == 0)
-                       s = strcat(s, ":no_pickup_items");
-               if(autocvar_g_pickup_items > 0)
-                       s = strcat(s, ":pickup_items");
+       // strftime(false, "%s") isn't reliable, see strftime_s description
+       matchid = strzone(sprintf("%d.%s.%06d", autocvar_sv_eventlog_files_counter, strftime_s(), random() * 1000000));
 
-               // initialiation stuff, not good in the mutator system
-               if(autocvar_g_weaponarena != "0")
-                       s = strcat(s, ":", autocvar_g_weaponarena, " arena");
-
-               // TODO to mutator system
-               if(autocvar_g_norecoil)
-                       s = strcat(s, ":norecoil");
-
-               GameLogEcho(s);
-               GameLogEcho(":gameinfo:end");
-       }
-       else
-               matchid = strzone(ftos(random()));
+       if(autocvar_sv_eventlog)
+               GameLogInit(); // requires matchid to be set
 
        cvar_set("nextmap", "");
 
@@ -1032,7 +999,7 @@ spawnfunc(light)
        delete(this);
 }
 
-bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance)
+bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance, bool frompos)
 {
     float m = e.dphitcontentsmask;
     e.dphitcontentsmask = goodcontents | badcontents;
@@ -1089,15 +1056,23 @@ bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax
             continue;
 
                // rule 4: we must "see" some spawnpoint or item
-           entity sp = NULL;
-           IL_EACH(g_spawnpoints, checkpvs(mstart, it),
-           {
-               if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
-               {
-                       sp = it;
-                       break;
-               }
-           });
+               entity sp = NULL;
+               if(frompos)
+               {
+                       if((traceline(mstart, e.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
+                               sp = e;
+               }
+               if(!sp)
+               {
+                       IL_EACH(g_spawnpoints, checkpvs(mstart, it),
+                       {
+                               if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1)
+                               {
+                                       sp = it;
+                                       break;
+                               }
+                       });
+               }
                if(!sp)
                {
                        int items_checked = 0;
@@ -1156,7 +1131,7 @@ bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax
 
 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
 {
-       return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance);
+       return MoveToRandomLocationWithinBounds(e, world.mins, world.maxs, goodcontents, badcontents, badsurfaceflags, attempts, maxaboveground, minviewdistance, false);
 }
 
 /*
@@ -1334,7 +1309,7 @@ void NextLevel()
 }
 
 
-float InitiateSuddenDeath()
+int InitiateSuddenDeath()
 {
        // Check first whether normal overtimes could be added before initiating suddendeath mode
        // - for this timelimit_overtime needs to be >0 of course
@@ -1351,9 +1326,14 @@ float InitiateSuddenDeath()
                if(!checkrules_suddendeathend)
                {
                        if(autocvar_g_campaign)
+                       {
                                checkrules_suddendeathend = time; // no suddendeath in campaign
+                       }
                        else
+                       {
                                checkrules_suddendeathend = time + 60 * autocvar_timelimit_suddendeath;
+                               overtimes = -1;
+                       }
                        if(g_race && !g_race_qualifying)
                                race_StartCompleting();
                }
@@ -1364,6 +1344,7 @@ float InitiateSuddenDeath()
 void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
 {
        ++checkrules_overtimesadded;
+       overtimes = checkrules_overtimesadded;
        //add one more overtime by simply extending the timelimit
        cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
        Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
@@ -1624,8 +1605,8 @@ void CheckRules_World()
        if(timelimit > 0)
                timelimit += game_starttime;
 
-       float wantovertime;
-       wantovertime = 0;
+       int overtimes_prev = overtimes;
+       int wantovertime = 0;
 
        if(checkrules_suddendeathend)
        {
@@ -1636,7 +1617,6 @@ void CheckRules_World()
                                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_RACE_FINISHLAP);
                        else
                                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_FRAG);
-                       checkrules_overtimesadded = -1; // Treat sudden death as an overtime
                }
        }
        else
@@ -1712,6 +1692,12 @@ void CheckRules_World()
 
        if(checkrules_status == WINNING_YES)
        {
+               if (overtimes == -1 && overtimes != overtimes_prev)
+               {
+                       // if suddendeathend overtime has just begun, revert it
+                       checkrules_suddendeathend = 0;
+                       overtimes = overtimes_prev;
+               }
                //print("WINNING\n");
                NextLevel();
        }
@@ -1873,25 +1859,25 @@ void readplayerstartcvars()
        else if (s == "all" || s == "1")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "All Weapons";
+               g_weaponarena_list = "All Weapons Arena";
                g_weaponarena_weapons = weapons_all();
        }
        else if (s == "devall")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Dev All Weapons";
+               g_weaponarena_list = "Dev All Weapons Arena";
                g_weaponarena_weapons = weapons_devall();
        }
        else if (s == "most")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Most Weapons";
+               g_weaponarena_list = "Most Weapons Arena";
                g_weaponarena_weapons = weapons_most();
        }
        else if (s == "all_available")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "All Available Weapons";
+               g_weaponarena_list = "All Available Weapons Arena";
 
                // this needs to run after weaponsInMapAll is initialized
                InitializeEntity(NULL, weaponarena_available_all_update, INITPRIO_FINDTARGET);
@@ -1899,7 +1885,7 @@ void readplayerstartcvars()
        else if (s == "devall_available")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Dev All Available Weapons";
+               g_weaponarena_list = "Dev All Available Weapons Arena";
 
                // this needs to run after weaponsInMapAll is initialized
                InitializeEntity(NULL, weaponarena_available_devall_update, INITPRIO_FINDTARGET);
@@ -1907,7 +1893,7 @@ void readplayerstartcvars()
        else if (s == "most_available")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "Most Available Weapons";
+               g_weaponarena_list = "Most Available Weapons Arena";
 
                // this needs to run after weaponsInMapAll is initialized
                InitializeEntity(NULL, weaponarena_available_most_update, INITPRIO_FINDTARGET);
@@ -1915,7 +1901,7 @@ void readplayerstartcvars()
        else if (s == "none")
        {
                g_weaponarena = 1;
-               g_weaponarena_list = "No Weapons";
+               g_weaponarena_list = "No Weapons Arena";
        }
        else
        {
@@ -1929,10 +1915,13 @@ void readplayerstartcvars()
                        if(wep != WEP_Null)
                        {
                                g_weaponarena_weapons |= (wep.m_wepset);
-                               g_weaponarena_list = strcat(g_weaponarena_list, wep.m_name, " & ");
+                               g_weaponarena_list = strcat(g_weaponarena_list, wep.netname, " & ");
                        }
                }
-               g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
+               if (g_weaponarena_list != "") // remove trailing " & "
+                       g_weaponarena_list = substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3);
+               else // no valid weapon found
+                       g_weaponarena_list = "No Weapons Arena";
        }
 
        if (g_weaponarena)
@@ -1940,6 +1929,7 @@ void readplayerstartcvars()
                g_weapon_stay = 0; // incompatible
                start_weapons = g_weaponarena_weapons;
                start_items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
+               g_weaponarena_list = strzone(g_weaponarena_list);
        }
        else
        {
@@ -2130,7 +2120,7 @@ void readlevelcvars()
 
     MUTATOR_CALLHOOK(ReadLevelCvars);
 
-       if (!warmup_stage)
+       if (!warmup_stage && !autocvar_g_campaign)
                game_starttime = time + cvar("g_start_delay");
 
        FOREACH(Weapons, it != WEP_Null, { it.wr_init(it); });