]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
GlobalSound: register player sounds
authorTimePath <andrew.hardaker1995@gmail.com>
Sun, 8 Nov 2015 07:27:32 +0000 (18:27 +1100)
committerTimePath <andrew.hardaker1995@gmail.com>
Sun, 8 Nov 2015 07:27:32 +0000 (18:27 +1100)
qcsrc/common/effects/qc/globalsound.qc
qcsrc/common/effects/qc/globalsound.qh
qcsrc/common/monsters/sv_monsters.qc
qcsrc/server/command/cmd.qc
qcsrc/server/defs.qh

index 0d21895ec77b8b7682ec91d30d547c95e0ac3113..27a0ead222fe2adc8c0b3516395dd6242288d0e7 100644 (file)
@@ -7,6 +7,7 @@
     #endif
 
        REGISTER_NET_TEMP(globalsound)
+       REGISTER_NET_TEMP(playersound)
 
     #ifdef SVQC
         /**
                        WriteCoord(channel, o.y);
                        WriteCoord(channel, o.z);
         }
+
+        /**
+                * @param from the source entity, its position is sent
+                * @param ps the player sound def
+                * @param r a random number in 0..1
+                */
+               void playersound(int channel, entity from, entity ps, float r, int chan, float vol, float atten)
+               {
+                       if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return;
+                       WriteHeader(channel, playersound);
+                       WriteByte(channel, ps.m_id);
+                       WriteByte(channel, r * 255);
+                       WriteByte(channel, etof(from));
+                       WriteByte(channel, fabs(chan));
+                       WriteByte(channel, floor(vol * 255));
+                       WriteByte(channel, floor(atten * 64));
+                       vector o = from.origin + 0.5 * (from.mins + from.maxs);
+                       WriteCoord(channel, o.x);
+                       WriteCoord(channel, o.y);
+                       WriteCoord(channel, o.z);
+               }
        #endif
 
     string GlobalSound_sample(string pair, float r);
@@ -48,7 +70,7 @@
                        o.x = ReadCoord();
                        o.y = ReadCoord();
                        o.z = ReadCoord();
-                   if (who == player_localnum + 1)
+                   if (who == player_currententnum)
                    {
                        // client knows better, play at current position to unlag
                        entity e = findfloat(world, entnum, who);
                        return true;
                }
 
+               NET_HANDLE(playersound, bool isnew)
+               {
+                       entity ps; ps = PlayerSounds_from(ReadByte());
+                       float r = ReadByte() / 255;
+                       int who = ReadByte();
+                       entity e = findfloat(world, entnum, autocvar_cl_forceplayermodels ? player_currententnum : who);
+                       string s = e.(ps.m_playersoundfld); // TODO: populate this field
+                       string sample = GlobalSound_sample(s, r);
+                       int chan = ReadByte();
+                       float vol = ReadByte() / 255;
+                       float atten = ReadByte() / 64;
+                       vector o;
+                       o.x = ReadCoord();
+                       o.y = ReadCoord();
+                       o.z = ReadCoord();
+                       if (who == player_currententnum)
+                       {
+                               // client knows better, play at current position to unlag
+                               sound7(e, chan, sample, vol, atten, 0, 0);
+                       }
+                       else
+                       {
+                               entity e = new(playersound);
+                               e.origin = o;
+                               sound8(e, o, chan, sample, vol, atten, 0, 0);
+                               remove(e);  // debug with: e.think = SUB_Remove; e.nextthink = time + 1;
+                       }
+                       return true;
+               }
+
        #endif
 
     string GlobalSound_sample(string pair, float r)
 
        #ifdef SVQC
 
-               int GetVoiceMessageVoiceType(string type)
+               entity GetVoiceMessage(string type)
                {
-                       if (type == "taunt") return VOICETYPE_TAUNT;
-                       if (type == "teamshoot") return VOICETYPE_LASTATTACKER;
-                       return VOICETYPE_TEAMRADIO;
+                       FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == true, LAMBDA(return it));
+                       return NULL;
                }
 
-               .string GetVoiceMessageSampleField(string type)
+               entity GetPlayerSound(string type)
+               {
+                       FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == false, LAMBDA(return it));
+                       return NULL;
+               }
+
+               .string _GetPlayerSoundSampleField(string type, bool voice)
                {
                        GetPlayerSoundSampleField_notFound = false;
-                       switch (type)
-                       {
-                               #define X(m) case #m: return playersound_##m;
-                               ALLVOICEMSGS(X)
-               #undef X
-                       }
+                       entity e = voice ? GetVoiceMessage(type) : GetPlayerSound(type);
+                       if (e) return e.m_playersoundfld;
                        GetPlayerSoundSampleField_notFound = true;
-                       return playersound_taunt;
+                       return playersound_taunt.m_playersoundfld;
+               }
+
+               .string GetVoiceMessageSampleField(string type)
+               {
+                       return _GetPlayerSoundSampleField(type, true);
                }
 
                .string GetPlayerSoundSampleField(string type)
                {
-                       GetPlayerSoundSampleField_notFound = false;
-                       switch (type)
-                       {
-                               #define X(m) case #m: return playersound_##m;
-                               ALLPLAYERSOUNDS(X)
-               #undef X
-                       }
-                       GetPlayerSoundSampleField_notFound = true;
-                       return playersound_taunt;
+                       return _GetPlayerSoundSampleField(type, false);
                }
 
                string allvoicesamples;
 
                        if (!allvoicesamples)
                        {
-                               #define X(m) allvoicesamples = strcat(allvoicesamples, " ", #m);
-                               ALLVOICEMSGS(X)
-               #undef X
+                               FOREACH(PlayerSounds, it.instanceOfVoiceMessage, LAMBDA(
+                                       allvoicesamples = strcat(allvoicesamples, " ", it.m_playersoundstr)
+                               ));
                                allvoicesamples = strzone(substring(allvoicesamples, 1, -1));
                        }
                }
 
                void ClearPlayerSounds(entity this)
                {
-                       #define X(m) \
-                               if (this.playersound_##m) \
-                               { \
-                                       strunzone(this.playersound_##m); \
-                                       this.playersound_##m = string_null; \
+                       FOREACH(PlayerSounds, true, LAMBDA(
+                               .string fld = it.m_playersoundfld;
+                               if (this.(fld))
+                               {
+                                       strunzone(this.(fld));
+                                       this.(fld) = string_null;
                                }
-                       ALLPLAYERSOUNDS(X)
-                       ALLVOICEMSGS(X)
-               #undef X
+                       ));
                }
 
-               bool LoadPlayerSounds(string f, bool strict)
+               bool LoadPlayerSounds(entity this, string f, bool strict)
                {
-                       SELFPARAM();
                        int fh = fopen(f, FILE_READ);
                        if (fh < 0)
                        {
                                }
                                string file = argv(1);
                                string variants = argv(2);
-                               if (self.(field)) strunzone(self.(field));
-                               self.(field) = strzone(strcat(file, " ", variants));
+                               if (this.(field)) strunzone(this.(field));
+                               this.(field) = strzone(strcat(file, " ", variants));
                        }
                        fclose(fh);
                        return true;
                        this.modelindex_for_playersound = this.modelindex;
                        this.skin_for_playersound = this.skin;
                        ClearPlayerSounds(this);
-                       LoadPlayerSounds("sound/player/default.sounds", true);
+                       LoadPlayerSounds(this, "sound/player/default.sounds", true);
                        if (autocvar_g_debug_defaultsounds) return;
-                       if (!LoadPlayerSounds(get_model_datafilename(this.model, this.skin, "sounds"), false))
-                               LoadPlayerSounds(get_model_datafilename(
+                       if (!LoadPlayerSounds(this, get_model_datafilename(this.model, this.skin, "sounds"), false))
+                               LoadPlayerSounds(this, get_model_datafilename(
                                        this.model, 0,
                                        "sounds"),
                                        true);
                }
 
-               void _GlobalSound(entity gs, string sample, int chan, int voicetype, bool fake)
+               void _GlobalSound(entity gs, entity ps, string sample, int chan, int voicetype, bool fake)
                {
                        SELFPARAM();
-                       if (gs == NULL && sample == "") return;
+                       if (gs == NULL && ps == NULL && sample == "") return;
                        float r = random();
+                       if (ps)  // TODO: remove
+                       {
+                               sample = this.(ps.m_playersoundfld);
+                               ps = NULL;
+                       }
                        if (sample != "") sample = GlobalSound_sample(sample, r);
                        switch (voicetype)
                        {
                                                {
                                                        float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE;
                                                        if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten);
+                                                       else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten);
                                                        else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten);
                                                }
                                        }
                                        if (IS_REAL_CLIENT(msg_entity))
                                        {
                                            if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NONE);
+                                           else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASE, ATTEN_NONE);
                                            else soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NONE);
                                        }
                                        break;
                                                { \
                                                        float atten = (msg_entity.cvar_cl_voice_directional == 1) ? ATTEN_MIN : ATTEN_NONE; \
                                                        if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten); \
+                                                       else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten); \
                                                        else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
                                                } \
                                                while (0)
                                                                        ATTEN_MAX) \
                                                                        : ATTEN_NONE; \
                                                                if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten); \
+                                                               else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASEVOICE, atten); \
                                 else soundto(MSG_ONE, this, chan, sample, VOL_BASEVOICE, atten); \
                                                        } \
                                                } \
                                        if (fake)
                                        {
                                                if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+                                               else if (ps) playersound(MSG_ONE, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
                         else soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NORM);
                                        }
                                        else
                                        {
                                        if (gs) globalsound(MSG_ALL, this, gs, r, chan, VOL_BASE, ATTEN_NORM);
+                                       else if (ps) playersound(MSG_ALL, this, ps, r, chan, VOL_BASE, ATTEN_NORM);
                         else _sound(this, chan, sample, VOL_BASE, ATTEN_NORM);
                                        }
                                        break;
                        }
                }
 
-               void PlayerSound(.string samplefield, int chan, float voicetype)
-               {
-                       SELFPARAM();
-                       _GlobalSound(NULL, this.(samplefield), chan, voicetype, false);
-               }
-
-               void VoiceMessage(string type, string msg)
-               {
-                       SELFPARAM();
-                       var.string sample = GetVoiceMessageSampleField(type);
-                       if (GetPlayerSoundSampleField_notFound)
-                       {
-                               sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
-                               return;
-                       }
-                       int voicetype = GetVoiceMessageVoiceType(type);
-                       bool ownteam = (voicetype == VOICETYPE_TEAMRADIO);
-                       int flood = Say(this, ownteam, world, msg, true);
-                       bool fake;
-                       if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true;
-                       else if (flood > 0) fake = false;
-                       else return;
-                       _GlobalSound(NULL, this.(sample), CH_VOICE, voicetype, fake);
-               }
        #endif
 #endif
index 926e0ba042f8e4a96ceff26aa372fd3e12f7a0ac..d120c05554efad8af193ec5cb698729679e33004 100644 (file)
@@ -2,31 +2,69 @@
 #define GLOBALSOUND_H
 
 // player sounds, voice messages
-// TODO implemented fall and falling
-#define ALLPLAYERSOUNDS(X) \
-       X(death) \
-       X(drown) \
-       X(fall) \
-       X(falling) \
-       X(gasp) \
-       X(jump) \
-       X(pain100) \
-       X(pain25) \
-       X(pain50) \
-       X(pain75)
 
-#define ALLVOICEMSGS(X) \
-       X(attack) \
-       X(attackinfive) \
-       X(coverme) \
-       X(defend) \
-       X(freelance) \
-       X(incoming) \
-       X(meet) \
-       X(needhelp) \
-       X(seenflag) \
-       X(taunt) \
-       X(teamshoot)
+.string m_playersoundstr;
+..string m_playersoundfld;
+
+REGISTRY(PlayerSounds, BITS(8) - 1)
+#define PlayerSounds_from(i) _PlayerSounds_from(i, NULL)
+#define REGISTER_PLAYERSOUND(id) \
+       .string _playersound_##id; \
+       REGISTER(RegisterPlayerSounds, playersound, PlayerSounds, id, m_id, new(PlayerSound)) \
+       { \
+               make_pure(this); \
+               this.m_playersoundstr = #id; \
+               this.m_playersoundfld = _playersound_##id; \
+       }
+REGISTER_REGISTRY(RegisterPlayerSounds)
+REGISTRY_SORT(PlayerSounds, 0)
+STATIC_INIT(PlayerSounds_renumber) { FOREACH(PlayerSounds, true, LAMBDA(it.m_id = i)); }
+REGISTRY_CHECK(PlayerSounds)
+
+// TODO implement fall and falling
+
+REGISTER_PLAYERSOUND(death)
+REGISTER_PLAYERSOUND(drown)
+REGISTER_PLAYERSOUND(fall)
+REGISTER_PLAYERSOUND(falling)
+REGISTER_PLAYERSOUND(gasp)
+REGISTER_PLAYERSOUND(jump)
+REGISTER_PLAYERSOUND(pain100)
+REGISTER_PLAYERSOUND(pain25)
+REGISTER_PLAYERSOUND(pain50)
+REGISTER_PLAYERSOUND(pain75)
+
+.bool instanceOfVoiceMessage;
+.int m_playersoundvt;
+#define REGISTER_VOICEMSG(id, vt) \
+       .string _playersound_##id; \
+       REGISTER(RegisterPlayerSounds, playersound, PlayerSounds, id, m_id, new(VoiceMessage)) \
+       { \
+               make_pure(this); \
+               this.instanceOfVoiceMessage = true; \
+               this.m_playersoundstr = #id; \
+               this.m_playersoundfld = _playersound_##id; \
+               this.m_playersoundvt = vt; \
+       }
+
+const int VOICETYPE_PLAYERSOUND = 10;
+const int VOICETYPE_TEAMRADIO = 11;
+const int VOICETYPE_LASTATTACKER = 12;
+const int VOICETYPE_LASTATTACKER_ONLY = 13;
+const int VOICETYPE_AUTOTAUNT = 14;
+const int VOICETYPE_TAUNT = 15;
+
+REGISTER_VOICEMSG(attack, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(attackinfive, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(coverme, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(defend, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(freelance, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(incoming, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(meet, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(needhelp, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(seenflag, VOICETYPE_TEAMRADIO)
+REGISTER_VOICEMSG(taunt, VOICETYPE_TAUNT)
+REGISTER_VOICEMSG(teamshoot, VOICETYPE_LASTATTACKER)
 
 // reserved sound names for the future (some models lack sounds for them):
 // _VOICEMSG(flagcarriertakingdamage)
@@ -67,24 +105,31 @@ REGISTER_GLOBALSOUND(FALL_METAL, "misc/metalhitground 4")
 
 #ifdef SVQC
 
-       #define X(m) .string playersound_##m;
-       ALLPLAYERSOUNDS(X)
-       ALLVOICEMSGS(X)
-       #undef X
-
        bool GetPlayerSoundSampleField_notFound;
-       float GetVoiceMessageVoiceType(string type);
        .string GetVoiceMessageSampleField(string type);
        .string GetPlayerSoundSampleField(string type);
        void PrecachePlayerSounds(string f);
        void ClearPlayerSounds(entity this);
-       float LoadPlayerSounds(string f, bool strict);
+       float LoadPlayerSounds(entity this, string f, bool strict);
        void UpdatePlayerSounds(entity this);
-       #define FakeGlobalSound(sample, chan, voicetype) _GlobalSound(NULL, sample, chan, voicetype, true)
-       void _GlobalSound(entity gs, string sample, float chan, float voicetype, bool fake);
-       #define GlobalSound(def, chan, voicetype) _GlobalSound(def, string_null, chan, voicetype, false)
-       void PlayerSound(.string samplefield, float chan, float voicetype);
-       void VoiceMessage(string type, string msg);
+       void _GlobalSound(entity gs, entity ps, string sample, float chan, float voicetype, bool fake);
+       #define GlobalSound(def, chan, voicetype) _GlobalSound(def, NULL, string_null, chan, voicetype, false)
+       #define GlobalSound_string(def, chan, voicetype) _GlobalSound(NULL, NULL, def, chan, voicetype, false)
+       #define PlayerSound(def, chan, voicetype) _GlobalSound(NULL, def, string_null, chan, voicetype, false)
+       #define VoiceMessage(def, msg) \
+       do \
+       { \
+               entity VM = def; \
+               int voicetype = VM.m_playersoundvt; \
+               bool ownteam = (voicetype == VOICETYPE_TEAMRADIO); \
+               int flood = Say(this, ownteam, world, msg, true); \
+               bool fake; \
+               if (IS_SPEC(this) || IS_OBSERVER(this) || flood < 0) fake = true; \
+               else if (flood > 0) fake = false; \
+               else break; \
+               _GlobalSound(NULL, VM, string_null, CH_VOICE, voicetype, fake); \
+       } \
+       while (0)
 
 #endif
 
index 6c35de85f4bf9a8ae62bb1b1534b8f937a36306a..702e8ee39d010bc67d77dff3b4f5118d9485421c 100644 (file)
@@ -346,7 +346,7 @@ void Monster_Sound(.string samplefield, float sound_delay, float delaytoo, float
        if(delaytoo)
        if(time < self.msound_delay)
                return; // too early
-       _GlobalSound(NULL, self.(samplefield), chan, VOICETYPE_PLAYERSOUND, false);
+       GlobalSound_string(self.(samplefield), chan, VOICETYPE_PLAYERSOUND);
 
        self.msound_delay = time + sound_delay;
 }
index ac21bc62dcc61b6ff73d68350ae9cafa38699b4c..6cac1c4f0620fb5a224e6d8dd2c0a5a39a865873 100644 (file)
@@ -601,8 +601,14 @@ void ClientCommand_voice(float request, float argc, string command)
                {
                        if (argv(1) != "")
                        {
-                               if (argc >= 3) VoiceMessage(argv(1), substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
-                               else VoiceMessage(argv(1), "");
+                               entity e = GetVoiceMessage(argv(1));
+                               if (!e)
+                               {
+                                       sprint(this, sprintf("Invalid voice. Use one of: %s\n", allvoicesamples));
+                                       return;
+                               }
+                               if (argc >= 3) VoiceMessage(e, substring(command, argv_start_index(2), argv_end_index(-1) - argv_start_index(2)));
+                               else VoiceMessage(e, "");
 
                                return;
                        }
index 094eb453192a6e7b48ce2204d39ea18acdc150d9..16a7c779be9736147ee7ca9c0984e9b9f61562f0 100644 (file)
@@ -301,13 +301,6 @@ float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
 
 float next_pingtime;
 
-const float VOICETYPE_PLAYERSOUND = 10;
-const float VOICETYPE_TEAMRADIO = 11;
-const float VOICETYPE_LASTATTACKER = 12;
-const float VOICETYPE_LASTATTACKER_ONLY = 13;
-const float VOICETYPE_AUTOTAUNT = 14;
-const float VOICETYPE_TAUNT = 15;
-
 // autotaunt system
 .float cvar_cl_autotaunt;
 .float cvar_cl_voice_directional;