]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/showspecs
authorMario <mario.mario@y7mail.com>
Fri, 20 Dec 2013 01:19:34 +0000 (12:19 +1100)
committerMario <mario.mario@y7mail.com>
Fri, 20 Dec 2013 01:19:34 +0000 (12:19 +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 dd16de9bc6ee4224b900bf576cfc86ff8e5fce20..353d19c11c6faa29b2f8218e1d98b4442709fcc8 100644 (file)
@@ -1594,3 +1594,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 a06eb5e6584e3ac96f48c489b762ee748ce9a127..1e320048886f730986b0207da806939cd3bf7277 100644 (file)
@@ -1187,6 +1187,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.
@@ -1248,6 +1261,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 403792020ac7c7e08aa6a412f15abd5e98cffa9b..2169d10051afc36c04c5d6cb205a49e338eebbd3 100644 (file)
@@ -427,3 +427,4 @@ string autocvar__cl_playermodel;
 float autocvar_cl_deathglow;
 float autocvar_developer_csqcentities;
 float autocvar_g_jetpack_attenuation;
+float autocvar_cl_showspectators;
index a78177b1991c5783e5e9b185cc5225d6a0d447d3..f24df1e2050ea49ceac401a163ffec32e6f09700 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 55d16953f6a04d4a5e4f9bc8c289b5981654704e..58d2c19a7c3e349f020addf2219432aa7df2adf7 100644 (file)
@@ -42,6 +42,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 19187a39deeab1c16cab1a8b05834d997dcb35d0..349bf90dd223e627a34271e7bf7aedfea44b1ca1 100644 (file)
@@ -1248,3 +1248,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 d803602ad6ccd6c229e5b61ffa20f4dfc976b6ae..b7ca56b84aaaf1a88d7606264cc4fc30c8b3a477 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)
        {
@@ -609,6 +612,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
@@ -1246,6 +1251,8 @@ Called when a client disconnects from the server
 void ReadyCount();
 void ClientDisconnect (void)
 {
+       UpdateSpectators(self, world);
+
        if(self.vehicle)
            vehicles_exit(VHEF_RELESE);
 
@@ -1767,13 +1774,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()
 {
@@ -1852,7 +1888,10 @@ float SpectateNext()
        }
 
        if (other)
+       {
                self.enemy = other;
+               UpdateSpectators(world, world);
+       }
 
        return SpectateSet();
 }
@@ -1892,6 +1931,7 @@ float SpectatePrev()
                        other = first;
        }
        self.enemy = other;
+       UpdateSpectators(world, world);
        return SpectateSet();
 }