]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/showspecs
authorMario <mario.mario@y7mail.com>
Mon, 27 Jan 2014 06:14:00 +0000 (17:14 +1100)
committerMario <mario.mario@y7mail.com>
Mon, 27 Jan 2014 06:14:00 +0000 (17:14 +1100)
defaultXonotic.cfg
qcsrc/client/Main.qc
qcsrc/client/autocvars.qh
qcsrc/client/hud.qc
qcsrc/client/main.qh
qcsrc/common/constants.qh
qcsrc/server/autocvars.qh
qcsrc/server/cl_client.qc

index c6fa7642be5bb988be1c26272d43a86af5fb67e4..a83a2577b0bd568c9b019cbe906a3554628f5e97 100644 (file)
@@ -1581,3 +1581,6 @@ set cl_simpleitems_postfix "_simple" "posfix to add fo model name when simple it
 set cl_fullbright_items 0 "enable fullbright items (if server allows, controled by g_fullbrightitems)"
 set cl_weapon_stay_color "2 0.5 0.5" "Color of picked up weapons when g_weapon_stay > 0"
 set cl_weapon_stay_alpha 0.75 "Alpha of picked up weapons when g_weapon_stay > 0"
+
+set sv_showspectators 0
+set cl_showspectators 1
index 2ba4130db2a126bfdcf81120ba136957fbbb29b2..545ba592ed864678de5707c0a93cc40c3d2bdc93 100644 (file)
@@ -1190,6 +1190,19 @@ void Net_WeaponComplain()
        }
 }
 
+void Net_ReadSpecInfo()
+{
+       float i;
+       
+       num_spectators = ReadByte();
+       for(i = 0; i < num_spectators; ++i)
+       {
+               local float slot = ReadByte();
+               if(i < MAX_SPECTATORS)
+                       spectatorlist[i] = slot - 1;
+       }
+}
+
 // CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
 // You must ALWAYS first acquire the temporary ID, which is sent as a byte.
 // Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
@@ -1247,6 +1260,10 @@ float CSQC_Parse_TempEntity()
                        cl_notice_read();
                        bHandled = true;
                        break;
+               case TE_CSQC_SPECINFO:
+                       Net_ReadSpecInfo();
+                       bHandled = true;
+                       break;
                default:
                        // No special logic for this temporary entity; return 0 so the engine can handle it
                        bHandled = false;
index 43aab6ae44c73f3c2b0c598bbe4ae3d72014248e..64ef41ff54a11fc377d4e36e03f3d2702e2d2442 100644 (file)
@@ -429,3 +429,4 @@ string autocvar__cl_playermodel;
 float autocvar_cl_deathglow;
 float autocvar_developer_csqcentities;
 float autocvar_g_jetpack_attenuation;
+float autocvar_cl_showspectators;
index 252142506f88731b28e21e679c0bd5d84b7d52b2..08dcd6d382ea212259e0654d21fb8b18348e97bf 100644 (file)
@@ -3734,6 +3734,22 @@ void HUD_InfoMessages(void)
                        s = _("^2Currently in ^1warmup^2 stage!");
                        drawInfoMessage(s)
                }
+               
+               if(autocvar_cl_showspectators)
+               if(num_spectators)
+               if not(spectatee_status)
+               {
+                       s = _("^1Spectating you:");
+                       drawInfoMessage(s)
+                       float limit = min(num_spectators, MAX_SPECTATORS);
+                       float i;
+                       for(i = 0; i < limit; ++i)
+                       {
+                               float slot = spectatorlist[i];
+                               s = strcat("^3", GetPlayerName(slot));
+                               drawInfoMessage(s)
+                       }
+               }
 
                string blinkcolor;
                if(mod(time, 1) >= 0.5)
index 815c20a33ed1788eb16129b136bfe18372f3fe87..ce4f09a44596f67387b8a38ea27ec26be6d888c6 100644 (file)
@@ -147,3 +147,7 @@ entity entcs_receiver[255]; // 255 is the engine limit on maxclients
 float hud;
 float view_quality;
 float framecount;
+
+float num_spectators;
+#define MAX_SPECTATORS 7
+float spectatorlist[MAX_SPECTATORS];
index e02fad45f06090b6b3d8e24bfed12f7ade651548..58612bd76d9ee7bb8ceb3b13a77573107f18b7a3 100644 (file)
@@ -41,6 +41,7 @@ const float TE_CSQC_MINELAYER_MAXMINES = 110;
 const float TE_CSQC_HAGAR_MAXROCKETS = 111;
 const float TE_CSQC_VEHICLESETUP = 112;
 const float TE_CSQC_SVNOTICE = 113;
+const float TE_CSQC_SPECINFO = 114;
 
 const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
 const float RACE_NET_CHECKPOINT_CLEAR = 1;
index fc9181d56c473061faf366bf2b1c697f3bd969de..0f5e1635642d55ff9bcdfdf2ee368b4d89f70dc0 100644 (file)
@@ -1269,3 +1269,4 @@ float autocvar_g_campcheck_damage;
 float autocvar_g_campcheck_distance;
 float autocvar_g_campcheck_interval;
 float autocvar_g_jump_grunt;
+float autocvar_sv_showspectators;
index 691c4930e995978bc50135e3185260b659fd6979..8bc0e458950b09b8de619e07d445eda3133fbb5f 100644 (file)
@@ -136,6 +136,7 @@ putting a client as observer in the server
 =============
 */
 void FixPlayermodel();
+void UpdateSpectators(entity is_spec, entity is_player);
 void PutObserverInServer (void)
 {
        entity  spot;
@@ -153,6 +154,8 @@ void PutObserverInServer (void)
                WriteByte(MSG_ONE, SVC_SETVIEW);
                WriteEntity(MSG_ONE, self);
        }
+       
+       UpdateSpectators(self, self); // don't update spectators or spectatees
 
        if((g_race && g_race_qualifying) || g_cts)
        {
@@ -617,6 +620,8 @@ void PutClientInServer (void)
        {
                PutObserverInServer ();
        }
+       
+       UpdateSpectators(((IS_PLAYER(self)) ? world : self), ((IS_SPEC(self) || IS_OBSERVER(self)) ? self : world));
 }
 
 .float ebouncefactor, ebouncestop; // electro's values
@@ -1254,6 +1259,8 @@ Called when a client disconnects from the server
 void ReadyCount();
 void ClientDisconnect (void)
 {
+       UpdateSpectators(self, world);
+
        if(self.vehicle)
            vehicles_exit(VHEF_RELESE);
 
@@ -1773,13 +1780,42 @@ float SpectateUpdate() {
                return 0;
 
        if (!IS_PLAYER(self.enemy))
+       {
+               self.enemy = world;
                return 0;
+       }
 
        SpectateCopy(self.enemy);
 
        return 1;
 }
 
+void UpdateSpectators(entity is_spec, entity is_player)
+{
+       entity head, spec;
+       float specs = 0;
+       FOR_EACH_REALCLIENT(head)
+       {
+               msg_entity = head;
+               WriteByte(MSG_ONE, SVC_TEMPENTITY);
+               WriteByte(MSG_ONE, TE_CSQC_SPECINFO);
+               
+               specs = 0;
+               
+               FOR_EACH_SPEC(spec) if(spec.enemy == head && is_player != spec && spec != is_player)
+                       ++specs;
+       
+               if(IS_SPEC(head) || IS_OBSERVER(head) || head == is_spec || !autocvar_sv_showspectators)
+               {
+                       WriteByte(MSG_ONE, 0);
+                       continue;
+               }
+               
+               WriteByte(MSG_ONE, specs);
+               FOR_EACH_SPEC(spec) if(spec.enemy == head && is_player != spec)
+                       WriteByte(MSG_ONE, num_for_edict(spec));
+       }
+}
 
 float SpectateSet()
 {
@@ -1858,7 +1894,10 @@ float SpectateNext()
        }
 
        if (other)
+       {
                self.enemy = other;
+               UpdateSpectators(world, world);
+       }
 
        return SpectateSet();
 }
@@ -1898,6 +1937,7 @@ float SpectatePrev()
                        other = first;
        }
        self.enemy = other;
+       UpdateSpectators(world, world);
        return SpectateSet();
 }