]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Minor cleanup of world.qc, move most intermission and map handling code into intermis...
authorMario <mario.mario@y7mail.com>
Wed, 23 Sep 2020 10:33:53 +0000 (20:33 +1000)
committerMario <mario.mario@y7mail.com>
Wed, 23 Sep 2020 10:33:53 +0000 (20:33 +1000)
30 files changed:
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc
qcsrc/common/gamemodes/gamemode/cts/sv_cts.qc
qcsrc/common/gamemodes/gamemode/race/sv_race.qc
qcsrc/common/mutators/mutator/sandbox/sv_sandbox.qc
qcsrc/common/playerstats.qc
qcsrc/server/_mod.inc
qcsrc/server/_mod.qh
qcsrc/server/campaign.qc
qcsrc/server/client.qc
qcsrc/server/client.qh
qcsrc/server/command/getreplies.qc
qcsrc/server/command/radarmap.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/sv_cmd.qh
qcsrc/server/command/vote.qc
qcsrc/server/hook.qc
qcsrc/server/hook.qh
qcsrc/server/intermission.qc [new file with mode: 0644]
qcsrc/server/intermission.qh [new file with mode: 0644]
qcsrc/server/main.qc
qcsrc/server/main.qh
qcsrc/server/mapvoting.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/race.qc
qcsrc/server/scores.qc
qcsrc/server/spawnpoints.qc
qcsrc/server/weapons/weaponstats.qc
qcsrc/server/world.qc
qcsrc/server/world.qh

index 7e436665953388366df74999cbcb7f2bdc5dbe3b..ffde264b9545bd4cc53f237716a6f019bcc8a0d8 100644 (file)
@@ -7,6 +7,7 @@
 #include <server/command/vote.qh>
 #include <server/client.qh>
 #include <server/gamelog.qh>
+#include <server/intermission.qh>
 #include <server/damage.qh>
 #include <server/world.qh>
 #include <server/items/items.qh>
index 1550c8e8927878d1320270d8ee3e7470217a4a3d..08c4f84be2dfe53b0ab5f0f33f31edfeed0e1cda 100644 (file)
@@ -4,6 +4,7 @@
 #include <server/race.qh>
 #include <server/world.qh>
 #include <server/gamelog.qh>
+#include <server/intermission.qh>
 #include <server/items/spawning.qh>
 #include <server/weapons/common.qh>
 #include <common/mapobjects/triggers.qh>
index 5c6e52f397389e8b4e6f03b4b08d029d1a6819a6..39c72a4593a9878fbe755f1211c977ff8ffd83cb 100644 (file)
@@ -3,6 +3,7 @@
 #include <server/client.qh>
 #include <server/world.qh>
 #include <server/gamelog.qh>
+#include <server/intermission.qh>
 #include <server/race.qh>
 #include <common/ent_cs.qh>
 #include <common/mapobjects/triggers.qh>
index 9458189fd0ed20a448b9da906b3f654c12632452..a9c2d3ef0a69df95e0122727080c39027d1bde1c 100644 (file)
@@ -1,5 +1,7 @@
 #include "sv_sandbox.qh"
 
+#include <server/intermission.qh>
+
 string autocvar_g_sandbox;
 int autocvar_g_sandbox_info;
 bool autocvar_g_sandbox_readonly;
index 3b8c97c4b81626f6d292155e1831269540559b36..0202adb1dad10ccf9346176861585a8b297b65f0 100644 (file)
@@ -8,6 +8,7 @@
     #include <server/client.qh>
     #include "../server/anticheat.qh"
     #include <common/stats.qh>
+    #include <server/intermission.qh>
     #include "../server/scores.qh"
        #include <server/world.qh>
     #include "../server/weapons/accuracy.qh"
index b4c287a89d7014731f92c0714a0af8eb6fcbe182..cdd7d0d26389ba51ef98a5f761f432734d4581c2 100644 (file)
@@ -11,6 +11,7 @@
 #include <server/handicap.qc>
 #include <server/hook.qc>
 #include <server/impulse.qc>
+#include <server/intermission.qc>
 #include <server/ipban.qc>
 #include <server/main.qc>
 #include <server/mapvoting.qc>
index f9b39314ab1787b51ea877b8a66a6f7d4e72dcc9..7d1728f80f32965131c5848c47ce93140a6b458e 100644 (file)
@@ -11,6 +11,7 @@
 #include <server/handicap.qh>
 #include <server/hook.qh>
 #include <server/impulse.qh>
+#include <server/intermission.qh>
 #include <server/ipban.qh>
 #include <server/main.qh>
 #include <server/mapvoting.qh>
index de46e57d508f12fcdb37a95f38da8ebee27da7ac..3153ff111fab853de015b24c90a3b0da9b0dcf23 100644 (file)
@@ -4,6 +4,7 @@
 #include <common/stats.qh>
 
 #include "cheats.qh"
+#include <server/intermission.qh>
 #include "miscfunctions.qh"
 #include "world.qh"
 
index 3afbf4dedf58873d0c1540d8ad667c575036a07d..902172cd0d687753e820df8d2b21e2289db16884 100644 (file)
@@ -16,6 +16,7 @@
 #include "damage.qh"
 #include "handicap.qh"
 #include "hook.qh"
+#include <server/intermission.qh>
 #include "command/common.qh"
 #include "command/vote.qh"
 #include "clientkill.qh"
index a4309822d692d7e2bc8218a275fee8268cc801bc..d074ebe4b5a9b94381770e5d4b022115e80b3518 100644 (file)
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "utils.qh"
+#include <server/intermission.qh>
 #include <common/replicate.qh>
 #include <common/sounds/all.qh>
 
@@ -316,8 +317,6 @@ void ClientData_Touch(entity e);
 
 int nJoinAllowed(entity this, entity ignore);
 
-void FixIntermissionClient(entity e);
-
 void checkSpectatorBlock(entity this);
 
 void PlayerUseKey(entity this);
index 3262974898a1a284858dcf3ef325c6eb393569ec..1cf124ad3c054d5c77999367d6573fea38f222dd 100644 (file)
@@ -2,6 +2,7 @@
 
 #include <common/weapons/_all.qh>
 #include <common/stats.qh>
+#include <server/intermission.qh>
 #include <server/world.qh>
 #include <server/miscfunctions.qh>
 
index 6e73777a0f0321e55bd02ae54749e6f13623d914..4d3992239061fbc6e18937cca9a23e4c2aed1f59 100644 (file)
@@ -6,6 +6,8 @@
 
 #include "../world.qh"
 
+#include <server/intermission.qh>
+
 #include <common/util.qh>
 
 #include <lib/csqcmodel/sv_model.qh>
index 7de740bdde1049fc7b1f8c7c8e4d797ef91df4ae..281297b049e8a90ed2c1ab23f364dc2ba286c8d0 100644 (file)
@@ -16,6 +16,7 @@
 #include "../world.qh"
 #include "../ipban.qh"
 #include "../teamplay.qh"
+#include <server/intermission.qh>
 
 #include "../bot/api.qh"
 
index bf0dafa9cfffe0698723624f29088e4fc2c37c74..8beb8fd5248cbf03807ac6a6f9a5a84b907f38e3 100644 (file)
@@ -7,8 +7,6 @@
 bool shuffleteams_on_reset_map;
 void shuffleteams();
 
-string GotoMap(string m);
-
 void race_deleteTime(string map, float pos);
 
 // used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
index ee8a8e8db9a1550ec56cd407d3d2d0e05d6ccede..3d0cb29749baf3501a92360cd4a2014c23a832e4 100644 (file)
@@ -12,6 +12,7 @@
 #include "common.qh"
 
 #include "../damage.qh"
+#include <server/intermission.qh>
 #include "../world.qh"
 #include "../teamplay.qh"
 #include "../race.qh"
index 6042a48e1a61edae4c6bd572d3564f051e959017..a84a37fc3d894cb7fe61b7af88341271365f6ce5 100644 (file)
@@ -414,7 +414,8 @@ void FireGrapplingHook(entity actor, .entity weaponentity)
        Net_LinkEntity(missile, false, 0, GrapplingHookSend);
 }
 
-void GrappleHookInit()
+// NOTE: using PRECACHE here to make sure it's called after everything else
+PRECACHE(GrappleHookInit)
 {
        if(g_grappling_hook)
        {
index 1ed78e2745d9d4a4cdfff18792f9399af50fb7e6..3be5d6716bff1375ed3214404f4c3c079d0a2dcf 100644 (file)
@@ -18,6 +18,5 @@ const float HOOK_WAITING_FOR_RELEASE = BIT(4);
 .float hook_state;
 .int state;
 
-void GrappleHookInit();
 vector hook_shotorigin[4];
 
diff --git a/qcsrc/server/intermission.qc b/qcsrc/server/intermission.qc
new file mode 100644 (file)
index 0000000..fe2e0de
--- /dev/null
@@ -0,0 +1,479 @@
+#include "mapvoting.qh"
+
+#include <common/mapinfo.qh>
+#include <common/util.qh>
+#include <server/bot/api.qh>
+#include <server/campaign.qh>
+#include <server/client.qh>
+#include <server/mapvoting.qh>
+#include <server/scores_rules.qh>
+#include <server/world.qh>
+
+string GetGametype()
+{
+       return MapInfo_Type_ToString(MapInfo_LoadedGametype);
+}
+
+string GetMapname()
+{
+       return mapname;
+}
+
+float Map_Count, Map_Current;
+string Map_Current_Name;
+
+// NOTE: this now expects the map list to be already tokenized and the count in Map_Count
+int GetMaplistPosition()
+{
+       string map = GetMapname();
+       int idx = autocvar_g_maplist_index;
+
+       if(idx >= 0)
+       {
+               if(idx < Map_Count)
+               {
+                       if(map == argv(idx))
+                       {
+                               return idx;
+                       }
+               }
+       }
+
+       for(int pos = 0; pos < Map_Count; ++pos)
+       {
+               if(map == argv(pos))
+                       return pos;
+       }
+
+       // resume normal maplist rotation if current map is not in g_maplist
+       return idx;
+}
+
+bool MapHasRightSize(string map)
+{
+       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")))
+               {
+                       LOG_TRACE(checkwp_msg, ": no waypoints");
+                       return false;
+               }
+               LOG_TRACE(checkwp_msg, ": has waypoints");
+       }
+
+       if(autocvar_g_maplist_ignore_sizes)
+               return true;
+
+       // open map size restriction file
+       string opensize_msg = strcat("opensize ", map);
+       float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
+       int player_limit = ((autocvar_g_maplist_sizes_count_maxplayers) ? GetPlayerLimit() : 0);
+       int pcount = ((player_limit > 0) ? min(player_count, player_limit) : player_count); // bind it to the player limit so that forced spectators don't influence the limits
+       if(!autocvar_g_maplist_sizes_count_bots)
+               pcount -= currentbots;
+       if(fh >= 0)
+       {
+               opensize_msg = strcat(opensize_msg, ": ok, ");
+               int mapmin = stoi(fgets(fh));
+               int mapmax = stoi(fgets(fh));
+               fclose(fh);
+               if(pcount < mapmin)
+               {
+                       LOG_TRACE(opensize_msg, "not enough");
+                       return false;
+               }
+               if(mapmax && pcount > mapmax)
+               {
+                       LOG_TRACE(opensize_msg, "too many");
+                       return false;
+               }
+               LOG_TRACE(opensize_msg, "right size");
+               return true;
+       }
+       LOG_TRACE(opensize_msg, ": not found");
+       return true;
+}
+
+string Map_Filename(int position)
+{
+       return strcat("maps/", argv(position), ".bsp");
+}
+
+void Map_MarkAsRecent(string m)
+{
+       cvar_set("g_maplist_mostrecent", strwords(cons(m, autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
+}
+
+bool Map_IsRecent(string m)
+{
+       return strhasword(autocvar_g_maplist_mostrecent, m);
+}
+
+bool Map_Check(int position, float pass)
+{
+       string filename;
+       string map_next;
+       map_next = argv(position);
+       if(pass <= 1)
+       {
+               if(Map_IsRecent(map_next))
+                       return false;
+       }
+       filename = Map_Filename(position);
+       if(MapInfo_CheckMap(map_next))
+       {
+               if(pass == 2)
+                       return true;
+               if(MapHasRightSize(map_next))
+                       return true;
+               return false;
+       }
+       else
+               LOG_DEBUG( "Couldn't select '", filename, "'..." );
+
+       return false;
+}
+
+void Map_Goto_SetStr(string nextmapname)
+{
+       if(getmapname_stored != "")
+               strunzone(getmapname_stored);
+       if(nextmapname == "")
+               getmapname_stored = "";
+       else
+               getmapname_stored = strzone(nextmapname);
+}
+
+void Map_Goto_SetFloat(float position)
+{
+       cvar_set("g_maplist_index", ftos(position));
+       Map_Goto_SetStr(argv(position));
+}
+
+void Map_Goto(float reinit)
+{
+       MapInfo_LoadMap(getmapname_stored, 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 pass, i;
+
+       LOG_TRACE("Trying MaplistMethod_Iterate");
+
+       for(pass = 1; pass <= 2; ++pass)
+       {
+               for(i = 1; i < Map_Count; ++i)
+               {
+                       float mapindex;
+                       mapindex = (i + Map_Current) % Map_Count;
+                       if(Map_Check(mapindex, pass))
+                               return mapindex;
+               }
+       }
+       return -1;
+}
+
+float MaplistMethod_Repeat() // fallback method
+{
+       LOG_TRACE("Trying MaplistMethod_Repeat");
+
+       if(Map_Check(Map_Current, 2))
+               return Map_Current;
+       return -2;
+}
+
+float MaplistMethod_Random() // random map selection
+{
+       float i, imax;
+
+       LOG_TRACE("Trying MaplistMethod_Random");
+
+       imax = 42;
+
+       for(i = 0; i <= imax; ++i)
+       {
+               float mapindex;
+               mapindex = (Map_Current + floor(random() * (Map_Count - 1) + 1)) % Map_Count; // any OTHER map
+               if(Map_Check(mapindex, 1))
+                       return mapindex;
+       }
+       return -1;
+}
+
+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
+{
+       float i, j, imax, insertpos;
+
+       LOG_TRACE("Trying MaplistMethod_Shuffle");
+
+       imax = 42;
+
+       for(i = 0; i <= imax; ++i)
+       {
+               string newlist;
+
+               // now reinsert this at another position
+               insertpos = (random() ** (1 / exponent));       // ]0, 1]
+               insertpos = insertpos * (Map_Count - 1);       // ]0, Map_Count - 1]
+               insertpos = ceil(insertpos) + 1;               // {2, 3, 4, ..., Map_Count}
+               LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos));
+
+               // insert the current map there
+               newlist = "";
+               for(j = 1; j < insertpos; ++j)                 // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
+                       newlist = strcat(newlist, " ", argv(j));
+               newlist = strcat(newlist, " ", argv(0));       // now insert the just selected map
+               for(j = insertpos; j < Map_Count; ++j)         // i == Map_Count: no loop, has just been inserted as last
+                       newlist = strcat(newlist, " ", argv(j));
+               newlist = substring(newlist, 1, strlen(newlist) - 1);
+               cvar_set("g_maplist", newlist);
+               Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+
+               // NOTE: the selected map has just been inserted at (insertpos-1)th position
+               Map_Current = insertpos - 1; // this is not really valid, but this way the fallback has a chance of working
+               if(Map_Check(Map_Current, 1))
+                       return Map_Current;
+       }
+       return -1;
+}
+
+void Maplist_Init()
+{
+       float i = Map_Count = 0;
+       if(autocvar_g_maplist != "")
+       {
+               Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+               for (i = 0; i < Map_Count; ++i)
+               {
+                       if (Map_Check(i, 2))
+                               break;
+               }
+       }
+
+       if (i == Map_Count)
+       {
+               bprint( "Maplist contains no usable maps!  Resetting it to default map list.\n" );
+               cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags() | MAPINFO_FLAG_NOAUTOMAPLIST));
+               if(autocvar_g_maplist_shuffle)
+                       ShuffleMaplist();
+               if(!server_is_dedicated)
+                       localcmd("\nmenu_cmd sync\n");
+               Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+       }
+       if(Map_Count == 0)
+               error("empty maplist, cannot select a new map");
+       Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
+
+       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
+}
+
+string GetNextMap()
+{
+       Maplist_Init();
+       float nextMap = -1;
+
+       if(nextMap == -1)
+               if(autocvar_g_maplist_shuffle > 0)
+                       nextMap = MaplistMethod_Shuffle(autocvar_g_maplist_shuffle + 1);
+
+       if(nextMap == -1)
+               if(autocvar_g_maplist_selectrandom)
+                       nextMap = MaplistMethod_Random();
+
+       if(nextMap == -1)
+               nextMap = MaplistMethod_Iterate();
+
+       if(nextMap == -1)
+               nextMap = MaplistMethod_Repeat();
+
+       if(nextMap >= 0)
+       {
+               Map_Goto_SetFloat(nextMap);
+               return getmapname_stored;
+       }
+
+       return "";
+}
+
+float DoNextMapOverride(float reinit)
+{
+       if(autocvar_g_campaign)
+       {
+               CampaignPostIntermission();
+               alreadychangedlevel = true;
+               return true;
+       }
+       if(autocvar_quit_when_empty)
+       {
+               if(player_count <= currentbots)
+               {
+                       localcmd("quit\n");
+                       alreadychangedlevel = true;
+                       return true;
+               }
+       }
+       if(autocvar_quit_and_redirect != "")
+       {
+               redirection_target = strzone(autocvar_quit_and_redirect);
+               alreadychangedlevel = true;
+               return true;
+       }
+       if (!reinit && autocvar_samelevel) // if samelevel is set, stay on same level
+       {
+               localcmd("restart\n");
+               alreadychangedlevel = true;
+               return true;
+       }
+       if(autocvar_nextmap != "")
+       {
+               string m;
+               m = GameTypeVote_MapInfo_FixName(autocvar_nextmap);
+               cvar_set("nextmap",m);
+
+               if(!m || gametypevote)
+                       return false;
+               if(autocvar_sv_vote_gametype)
+               {
+                       Map_Goto_SetStr(m);
+                       return false;
+               }
+
+               if(MapInfo_CheckMap(m))
+               {
+                       Map_Goto_SetStr(m);
+                       Map_Goto(reinit);
+                       alreadychangedlevel = true;
+                       return true;
+               }
+       }
+       if(!reinit && autocvar_lastlevel)
+       {
+               cvar_settemp_restore();
+               localcmd("set lastlevel 0\ntogglemenu 1\n");
+               alreadychangedlevel = true;
+               return true;
+       }
+       return false;
+}
+
+void GotoNextMap(float reinit)
+{
+       //string nextmap;
+       //float n, nummaps;
+       //string s;
+       if (alreadychangedlevel)
+               return;
+       alreadychangedlevel = true;
+
+       string nextMap = GetNextMap();
+       if(nextMap == "")
+               error("Everything is broken - cannot find a next map. Please report this to the developers.");
+       Map_Goto(reinit);
+}
+
+void ShuffleMaplist()
+{
+       cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
+}
+
+string GotoMap(string m)
+{
+       m = GameTypeVote_MapInfo_FixName(m);
+       if (!m)
+               return "The map you suggested is not available on this server.";
+       if (!autocvar_sv_vote_gametype)
+       if(!MapInfo_CheckMap(m))
+               return "The map you suggested does not support the current game mode.";
+       cvar_set("nextmap", m);
+       cvar_set("timelimit", "-1");
+       if(mapvote_initialized || alreadychangedlevel)
+       {
+               if(DoNextMapOverride(0))
+                       return "Map switch initiated.";
+               else
+                       return "Hm... no. For some reason I like THIS map more.";
+       }
+       else
+               return "Map switch will happen after scoreboard.";
+}
+
+
+/*
+============
+IntermissionThink
+
+When the player presses attack or jump, change to the next level
+============
+*/
+.float autoscreenshot;
+void IntermissionThink(entity this)
+{
+       FixIntermissionClient(this);
+
+       float server_screenshot = (autocvar_sv_autoscreenshot && CS(this).cvar_cl_autoscreenshot);
+       float client_screenshot = (CS(this).cvar_cl_autoscreenshot == 2);
+
+       if( (server_screenshot || client_screenshot)
+               && ((this.autoscreenshot > 0) && (time > this.autoscreenshot)) )
+       {
+               this.autoscreenshot = -1;
+               if(IS_REAL_CLIENT(this)) { stuffcmd(this, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), strftime(false, "%s"))); }
+               return;
+       }
+
+       if (time < intermission_exittime)
+               return;
+
+       if(!mapvote_initialized)
+               if (time < intermission_exittime + 10 && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_ATCK2(this) || PHYS_INPUT_BUTTON_HOOK(this) || PHYS_INPUT_BUTTON_USE(this)))
+                       return;
+
+       MapVote_Start();
+}
+
+void FixIntermissionClient(entity e)
+{
+       if(!e.autoscreenshot) // initial call
+       {
+               e.autoscreenshot = time + 0.8;  // used for autoscreenshot
+               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)
+               {
+                   .entity weaponentity = weaponentities[slot];
+                       if(e.(weaponentity))
+                       {
+                               e.(weaponentity).effects = EF_NODRAW;
+                               if (e.(weaponentity).weaponchild)
+                                       e.(weaponentity).weaponchild.effects = EF_NODRAW;
+                       }
+               }
+               if(IS_REAL_CLIENT(e))
+               {
+                       stuffcmd(e, "\nscr_printspeed 1000000\n");
+                       RandomSelection_Init();
+                       FOREACH_WORD(autocvar_sv_intermission_cdtrack, true, {
+                               RandomSelection_AddString(it, 1, 1);
+                       });
+                       if (RandomSelection_chosen_string != "")
+                       {
+                               stuffcmd(e, sprintf("\ncd loop %s\n", RandomSelection_chosen_string));
+                       }
+                       msg_entity = e;
+                       WriteByte(MSG_ONE, SVC_INTERMISSION);
+               }
+       }
+}
diff --git a/qcsrc/server/intermission.qh b/qcsrc/server/intermission.qh
new file mode 100644 (file)
index 0000000..03458eb
--- /dev/null
@@ -0,0 +1,31 @@
+#pragma once
+
+float intermission_running;
+float intermission_exittime;
+float alreadychangedlevel;
+
+string GetGametype();
+
+string GetMapname();
+
+void IntermissionThink(entity this);
+
+void FixIntermissionClient(entity e);
+
+void GotoNextMap(float reinit);
+
+bool Map_IsRecent(string m);
+
+string GetNextMap();
+
+void ShuffleMaplist();
+
+void Map_Goto_SetStr(string nextmapname);
+
+void Map_Goto(float reinit);
+
+void Map_MarkAsRecent(string m);
+
+float DoNextMapOverride(float reinit);
+
+string GotoMap(string m);
index 3db2a0f8e7c9ea227126aec2f1d26629a5fbf7d6..0983d4621fad6365d74865f7b070607658efa9c3 100644 (file)
@@ -209,7 +209,6 @@ void make_safe_for_remove(entity e)
     }
 }
 
-.float remove_except_protected_forbidden;
 void remove_except_protected(entity e)
 {
        if(e.remove_except_protected_forbidden)
index 515ec62e61fba5b1336a411c7bfa8d397929c254..a8c86fe2f2f304c5b4fe0c9ac4c42cea17232244 100644 (file)
@@ -3,6 +3,9 @@
 /** print(), but only print if the server is not local */
 void dedicated_print(string input);
 
+.float remove_except_protected_forbidden;
+void remove_except_protected(entity e);
+
 void remove_safely(entity e);
 
 void remove_unsafely(entity e);
index ac64f630ff1d5181372a33c21fb4e67bde03588a..bdd563b81c99156f632a47ce1be21e9087e1d418 100644 (file)
@@ -4,6 +4,7 @@
 #include <common/weapons/_all.qh>
 #include <common/stats.qh>
 #include <server/gamelog.qh>
+#include <server/intermission.qh>
 #include <server/miscfunctions.qh>
 #include "world.qh"
 #include "command/cmd.qh"
index df830d13edd7467566fa5631b2692588b21a10ba..b748c17a00ccd96fd25ac4efc93f2ee242d7e1a0 100644 (file)
@@ -8,6 +8,7 @@
 #include "world.qh"
 #include <server/gamelog.qh>
 #include "ipban.qh"
+#include <server/intermission.qh>
 #include <server/items/items.qh>
 #include <server/mutators/_mod.qh>
 #include <server/spawnpoints.qh>
index 82618160a479588af2714f93c3d40fd087970447..0f37cfac73a32df98095a984de87d97bb53d0db8 100644 (file)
@@ -5,6 +5,7 @@
 #include <server/client.qh>
 #include <server/world.qh>
 
+#include <server/intermission.qh>
 #include <server/items/items.qh>
 
 #include <server/mutators/_mod.qh>
index c2de3c9cc63e830a1859f7a16989a3e66d08c55e..5014e02aedb0836af94e33a7405f58c2899a764e 100644 (file)
@@ -3,6 +3,7 @@
 #include <common/weapons/_all.qh>
 #include <common/stats.qh>
 #include <server/damage.qh>
+#include <server/intermission.qh>
 #include <server/world.qh>
 #include <server/miscfunctions.qh>
 #include <server/weapons/common.qh>
index e4e1d236aba4c11690c06c50dc99a03bd9dcb0c1..7bd776989b6d0cc5a8e73e5c93d829f84285b506 100644 (file)
@@ -3,6 +3,7 @@
 #include "command/common.qh"
 #include <common/weapons/_all.qh>
 #include "client.qh"
+#include <server/intermission.qh>
 #include <server/world.qh>
 #include <server/miscfunctions.qh>
 #include <server/mutators/_mod.qh>
index b629ef168449af6f5280a1fd5469ddacc2bc645b..532d631180203e50af27fddbdab40fd8820836ec 100644 (file)
@@ -16,6 +16,7 @@
 #include "../common/util.qh"
 #include "../lib/warpzone/common.qh"
 #include "../lib/warpzone/util_server.qh"
+#include <server/intermission.qh>
 #include <server/utils.qh>
 #include <server/command/vote.qh>
 
index 552ab67310b929bb27606b76378519341c042741..02ba234ea990f9a4844473c6f2830a5b5f5dc738 100644 (file)
@@ -1,5 +1,6 @@
 #include "weaponstats.qh"
 
+#include <server/intermission.qh>
 #include <common/weapons/_all.qh>
 #include <common/stats.qh>
 #include <server/miscfunctions.qh>
index 89c478ab792a619a31f0b4f134c639cfa22c2fd7..329aab0876c3e337fb53ae93476ff0c35be4d188 100644 (file)
@@ -14,6 +14,8 @@
 #include <server/gamelog.qh>
 #include <server/damage.qh>
 #include "ipban.qh"
+#include <server/intermission.qh>
+#include <server/main.qh>
 #include "mapvoting.qh"
 #include <server/mutators/_mod.qh>
 #include "race.qh"
@@ -96,7 +98,6 @@ void PingPLReport_Spawn()
 }
 
 const float SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS = 1;
-string redirection_target;
 float world_initialized;
 
 void SetDefaultAlpha()
@@ -627,7 +628,7 @@ STATIC_INIT_EARLY(maxclients)
        }
 }
 
-void default_delayedinit(entity this)
+void GameplayMode_DelayedInit(entity this)
 {
        if(!scores_initialized)
                ScoreRules_generic();
@@ -677,11 +678,10 @@ void InitGameplayMode()
        cache_mutatormsg = strzone("");
        cache_lastmutatormsg = strzone("");
 
-       InitializeEntity(NULL, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK);
+       InitializeEntity(NULL, GameplayMode_DelayedInit, INITPRIO_GAMETYPE_FALLBACK);
 }
 
-void Map_MarkAsRecent(string m);
-float world_already_spawned;
+bool world_already_spawned;
 spawnfunc(worldspawn)
 {
        server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
@@ -814,7 +814,6 @@ spawnfunc(worldspawn)
        static_init_late();
        static_init_precache();
        readlevelcvars();
-       GrappleHookInit();
 
        GameRules_limit_fallbacks();
 
@@ -1020,415 +1019,6 @@ spawnfunc(light)
        delete(this);
 }
 
-string GetGametype()
-{
-       return MapInfo_Type_ToString(MapInfo_LoadedGametype);
-}
-
-string GetMapname()
-{
-       return mapname;
-}
-
-float Map_Count, Map_Current;
-string Map_Current_Name;
-
-// NOTE: this now expects the map list to be already tokenized and the count in Map_Count
-int GetMaplistPosition()
-{
-       string map = GetMapname();
-       int idx = autocvar_g_maplist_index;
-
-       if(idx >= 0)
-       {
-               if(idx < Map_Count)
-               {
-                       if(map == argv(idx))
-                       {
-                               return idx;
-                       }
-               }
-       }
-
-       for(int pos = 0; pos < Map_Count; ++pos)
-       {
-               if(map == argv(pos))
-                       return pos;
-       }
-
-       // resume normal maplist rotation if current map is not in g_maplist
-       return idx;
-}
-
-bool MapHasRightSize(string map)
-{
-       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")))
-               {
-                       LOG_TRACE(checkwp_msg, ": no waypoints");
-                       return false;
-               }
-               LOG_TRACE(checkwp_msg, ": has waypoints");
-       }
-
-       if(autocvar_g_maplist_ignore_sizes)
-               return true;
-
-       // open map size restriction file
-       string opensize_msg = strcat("opensize ", map);
-       float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
-       int player_limit = ((autocvar_g_maplist_sizes_count_maxplayers) ? GetPlayerLimit() : 0);
-       int pcount = ((player_limit > 0) ? min(player_count, player_limit) : player_count); // bind it to the player limit so that forced spectators don't influence the limits
-       if(!autocvar_g_maplist_sizes_count_bots)
-               pcount -= currentbots;
-       if(fh >= 0)
-       {
-               opensize_msg = strcat(opensize_msg, ": ok, ");
-               int mapmin = stoi(fgets(fh));
-               int mapmax = stoi(fgets(fh));
-               fclose(fh);
-               if(pcount < mapmin)
-               {
-                       LOG_TRACE(opensize_msg, "not enough");
-                       return false;
-               }
-               if(mapmax && pcount > mapmax)
-               {
-                       LOG_TRACE(opensize_msg, "too many");
-                       return false;
-               }
-               LOG_TRACE(opensize_msg, "right size");
-               return true;
-       }
-       LOG_TRACE(opensize_msg, ": not found");
-       return true;
-}
-
-string Map_Filename(float position)
-{
-       return strcat("maps/", argv(position), ".bsp");
-}
-
-void Map_MarkAsRecent(string m)
-{
-       cvar_set("g_maplist_mostrecent", strwords(cons(m, autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
-}
-
-float Map_IsRecent(string m)
-{
-       return strhasword(autocvar_g_maplist_mostrecent, m);
-}
-
-float Map_Check(float position, float pass)
-{
-       string filename;
-       string map_next;
-       map_next = argv(position);
-       if(pass <= 1)
-       {
-               if(Map_IsRecent(map_next))
-                       return 0;
-       }
-       filename = Map_Filename(position);
-       if(MapInfo_CheckMap(map_next))
-       {
-               if(pass == 2)
-                       return 1;
-               if(MapHasRightSize(map_next))
-                       return 1;
-               return 0;
-       }
-       else
-               LOG_DEBUG( "Couldn't select '", filename, "'..." );
-
-       return 0;
-}
-
-void Map_Goto_SetStr(string nextmapname)
-{
-       if(getmapname_stored != "")
-               strunzone(getmapname_stored);
-       if(nextmapname == "")
-               getmapname_stored = "";
-       else
-               getmapname_stored = strzone(nextmapname);
-}
-
-void Map_Goto_SetFloat(float position)
-{
-       cvar_set("g_maplist_index", ftos(position));
-       Map_Goto_SetStr(argv(position));
-}
-
-void Map_Goto(float reinit)
-{
-       MapInfo_LoadMap(getmapname_stored, 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 pass, i;
-
-       LOG_TRACE("Trying MaplistMethod_Iterate");
-
-       for(pass = 1; pass <= 2; ++pass)
-       {
-               for(i = 1; i < Map_Count; ++i)
-               {
-                       float mapindex;
-                       mapindex = (i + Map_Current) % Map_Count;
-                       if(Map_Check(mapindex, pass))
-                               return mapindex;
-               }
-       }
-       return -1;
-}
-
-float MaplistMethod_Repeat() // fallback method
-{
-       LOG_TRACE("Trying MaplistMethod_Repeat");
-
-       if(Map_Check(Map_Current, 2))
-               return Map_Current;
-       return -2;
-}
-
-float MaplistMethod_Random() // random map selection
-{
-       float i, imax;
-
-       LOG_TRACE("Trying MaplistMethod_Random");
-
-       imax = 42;
-
-       for(i = 0; i <= imax; ++i)
-       {
-               float mapindex;
-               mapindex = (Map_Current + floor(random() * (Map_Count - 1) + 1)) % Map_Count; // any OTHER map
-               if(Map_Check(mapindex, 1))
-                       return mapindex;
-       }
-       return -1;
-}
-
-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
-{
-       float i, j, imax, insertpos;
-
-       LOG_TRACE("Trying MaplistMethod_Shuffle");
-
-       imax = 42;
-
-       for(i = 0; i <= imax; ++i)
-       {
-               string newlist;
-
-               // now reinsert this at another position
-               insertpos = (random() ** (1 / exponent));       // ]0, 1]
-               insertpos = insertpos * (Map_Count - 1);       // ]0, Map_Count - 1]
-               insertpos = ceil(insertpos) + 1;               // {2, 3, 4, ..., Map_Count}
-               LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos));
-
-               // insert the current map there
-               newlist = "";
-               for(j = 1; j < insertpos; ++j)                 // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
-                       newlist = strcat(newlist, " ", argv(j));
-               newlist = strcat(newlist, " ", argv(0));       // now insert the just selected map
-               for(j = insertpos; j < Map_Count; ++j)         // i == Map_Count: no loop, has just been inserted as last
-                       newlist = strcat(newlist, " ", argv(j));
-               newlist = substring(newlist, 1, strlen(newlist) - 1);
-               cvar_set("g_maplist", newlist);
-               Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
-
-               // NOTE: the selected map has just been inserted at (insertpos-1)th position
-               Map_Current = insertpos - 1; // this is not really valid, but this way the fallback has a chance of working
-               if(Map_Check(Map_Current, 1))
-                       return Map_Current;
-       }
-       return -1;
-}
-
-void Maplist_Init()
-{
-       float i = Map_Count = 0;
-       if(autocvar_g_maplist != "")
-       {
-               Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
-               for (i = 0; i < Map_Count; ++i)
-               {
-                       if (Map_Check(i, 2))
-                               break;
-               }
-       }
-
-       if (i == Map_Count)
-       {
-               bprint( "Maplist contains no usable maps!  Resetting it to default map list.\n" );
-               cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags() | MAPINFO_FLAG_NOAUTOMAPLIST));
-               if(autocvar_g_maplist_shuffle)
-                       ShuffleMaplist();
-               if(!server_is_dedicated)
-                       localcmd("\nmenu_cmd sync\n");
-               Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
-       }
-       if(Map_Count == 0)
-               error("empty maplist, cannot select a new map");
-       Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
-
-       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
-}
-
-string GetNextMap()
-{
-       Maplist_Init();
-       float nextMap = -1;
-
-       if(nextMap == -1)
-               if(autocvar_g_maplist_shuffle > 0)
-                       nextMap = MaplistMethod_Shuffle(autocvar_g_maplist_shuffle + 1);
-
-       if(nextMap == -1)
-               if(autocvar_g_maplist_selectrandom)
-                       nextMap = MaplistMethod_Random();
-
-       if(nextMap == -1)
-               nextMap = MaplistMethod_Iterate();
-
-       if(nextMap == -1)
-               nextMap = MaplistMethod_Repeat();
-
-       if(nextMap >= 0)
-       {
-               Map_Goto_SetFloat(nextMap);
-               return getmapname_stored;
-       }
-
-       return "";
-}
-
-float DoNextMapOverride(float reinit)
-{
-       if(autocvar_g_campaign)
-       {
-               CampaignPostIntermission();
-               alreadychangedlevel = true;
-               return true;
-       }
-       if(autocvar_quit_when_empty)
-       {
-               if(player_count <= currentbots)
-               {
-                       localcmd("quit\n");
-                       alreadychangedlevel = true;
-                       return true;
-               }
-       }
-       if(autocvar_quit_and_redirect != "")
-       {
-               redirection_target = strzone(autocvar_quit_and_redirect);
-               alreadychangedlevel = true;
-               return true;
-       }
-       if (!reinit && autocvar_samelevel) // if samelevel is set, stay on same level
-       {
-               localcmd("restart\n");
-               alreadychangedlevel = true;
-               return true;
-       }
-       if(autocvar_nextmap != "")
-       {
-               string m;
-               m = GameTypeVote_MapInfo_FixName(autocvar_nextmap);
-               cvar_set("nextmap",m);
-
-               if(!m || gametypevote)
-                       return false;
-               if(autocvar_sv_vote_gametype)
-               {
-                       Map_Goto_SetStr(m);
-                       return false;
-               }
-
-               if(MapInfo_CheckMap(m))
-               {
-                       Map_Goto_SetStr(m);
-                       Map_Goto(reinit);
-                       alreadychangedlevel = true;
-                       return true;
-               }
-       }
-       if(!reinit && autocvar_lastlevel)
-       {
-               cvar_settemp_restore();
-               localcmd("set lastlevel 0\ntogglemenu 1\n");
-               alreadychangedlevel = true;
-               return true;
-       }
-       return false;
-}
-
-void GotoNextMap(float reinit)
-{
-       //string nextmap;
-       //float n, nummaps;
-       //string s;
-       if (alreadychangedlevel)
-               return;
-       alreadychangedlevel = true;
-
-       string nextMap = GetNextMap();
-       if(nextMap == "")
-               error("Everything is broken - cannot find a next map. Please report this to the developers.");
-       Map_Goto(reinit);
-}
-
-
-/*
-============
-IntermissionThink
-
-When the player presses attack or jump, change to the next level
-============
-*/
-.float autoscreenshot;
-void IntermissionThink(entity this)
-{
-       FixIntermissionClient(this);
-
-       float server_screenshot = (autocvar_sv_autoscreenshot && CS(this).cvar_cl_autoscreenshot);
-       float client_screenshot = (CS(this).cvar_cl_autoscreenshot == 2);
-
-       if( (server_screenshot || client_screenshot)
-               && ((this.autoscreenshot > 0) && (time > this.autoscreenshot)) )
-       {
-               this.autoscreenshot = -1;
-               if(IS_REAL_CLIENT(this)) { stuffcmd(this, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), strftime(false, "%s"))); }
-               return;
-       }
-
-       if (time < intermission_exittime)
-               return;
-
-       if(!mapvote_initialized)
-               if (time < intermission_exittime + 10 && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_ATCK2(this) || PHYS_INPUT_BUTTON_HOOK(this) || PHYS_INPUT_BUTTON_USE(this)))
-                       return;
-
-       MapVote_Start();
-}
-
 /*
 ===============================================================================
 
@@ -1539,40 +1129,6 @@ void DumpStats(float final)
        }
 }
 
-void FixIntermissionClient(entity e)
-{
-       if(!e.autoscreenshot) // initial call
-       {
-               e.autoscreenshot = time + 0.8;  // used for autoscreenshot
-               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)
-               {
-                   .entity weaponentity = weaponentities[slot];
-                       if(e.(weaponentity))
-                       {
-                               e.(weaponentity).effects = EF_NODRAW;
-                               if (e.(weaponentity).weaponchild)
-                                       e.(weaponentity).weaponchild.effects = EF_NODRAW;
-                       }
-               }
-               if(IS_REAL_CLIENT(e))
-               {
-                       stuffcmd(e, "\nscr_printspeed 1000000\n");
-                       RandomSelection_Init();
-                       FOREACH_WORD(autocvar_sv_intermission_cdtrack, true, {
-                               RandomSelection_AddString(it, 1, 1);
-                       });
-                       if (RandomSelection_chosen_string != "")
-                       {
-                               stuffcmd(e, sprintf("\ncd loop %s\n", RandomSelection_chosen_string));
-                       }
-                       msg_entity = e;
-                       WriteByte(MSG_ONE, SVC_INTERMISSION);
-               }
-       }
-}
-
 /*
 go to the next level for deathmatch
 only called if a time or frag limit has expired
@@ -1713,11 +1269,6 @@ void ClearWinners()
        FOREACH_CLIENT(IS_PLAYER(it), { it.winning = 0; });
 }
 
-void ShuffleMaplist()
-{
-       cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
-}
-
 int fragsleft_last;
 float WinningCondition_Scores(float limit, float leadlimit)
 {
@@ -2017,27 +1568,6 @@ void CheckRules_World()
        }
 }
 
-string GotoMap(string m)
-{
-       m = GameTypeVote_MapInfo_FixName(m);
-       if (!m)
-               return "The map you suggested is not available on this server.";
-       if (!autocvar_sv_vote_gametype)
-       if(!MapInfo_CheckMap(m))
-               return "The map you suggested does not support the current game mode.";
-       cvar_set("nextmap", m);
-       cvar_set("timelimit", "-1");
-       if(mapvote_initialized || alreadychangedlevel)
-       {
-               if(DoNextMapOverride(0))
-                       return "Map switch initiated.";
-               else
-                       return "Hm... no. For some reason I like THIS map more.";
-       }
-       else
-               return "Map switch will happen after scoreboard.";
-}
-
 bool autocvar_sv_gameplayfix_multiplethinksperframe = true;
 void RunThink(entity this)
 {
index f49346a1cd21d9ce5f1cc7d6a4206ea6a316f4e1..3d8ca997300665db47da85ebb49661b320b93cd1 100644 (file)
@@ -22,9 +22,7 @@ string matchid;
 
 .string fog;
 
-float intermission_running;
-float intermission_exittime;
-float alreadychangedlevel;
+string redirection_target;
 
 string cache_mutatormsg;
 string cache_lastmutatormsg;
@@ -44,23 +42,11 @@ const int WINNING_STARTSUDDENDEATHOVERTIME = 3; // no winner, enter suddendeath
 
 float WinningCondition_Scores(float limit, float leadlimit);
 void SetWinners(.float field, float value);
-void IntermissionThink(entity this);
-void GotoNextMap(float reinit);
 void ReadyRestart();
 
-string GetGametype();
-
 void DumpStats(float final);
-float Map_IsRecent(string m);
-string GetNextMap();
-void ShuffleMaplist();
-void Map_Goto_SetStr(string nextmapname);
-void Map_Goto(float reinit);
-void Map_MarkAsRecent(string m);
-float DoNextMapOverride(float reinit);
 void CheckRules_World();
 float RedirectionThink();
-string GetMapname();
 
 IntrusiveList g_moveables;
 STATIC_INIT(g_moveables) { g_moveables = IL_NEW(); }