X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=qcsrc%2Fcommon%2Feffects%2Fqc%2Fglobalsound.qc;h=a2653238e7ebea30ad5a22f26203adf9156c66e1;hb=6a611fb362129440369cb09a590023d6292102e9;hp=0d21895ec77b8b7682ec91d30d547c95e0ac3113;hpb=11699a3c83f90d15c9bd86f69497e77fb4880083;p=xonotic%2Fxonotic-data.pk3dir.git diff --git a/qcsrc/common/effects/qc/globalsound.qc b/qcsrc/common/effects/qc/globalsound.qc index 0d21895ec..a2653238e 100644 --- a/qcsrc/common/effects/qc/globalsound.qc +++ b/qcsrc/common/effects/qc/globalsound.qc @@ -1,84 +1,172 @@ #include "globalsound.qh" + +#include + #ifdef IMPLEMENTATION - #include "../../animdecide.qh" + #include - #ifdef SVQC - #include "../../../server/cl_player.qh" - #endif + #ifdef SVQC + #include + #endif REGISTER_NET_TEMP(globalsound) + REGISTER_NET_TEMP(playersound) - #ifdef SVQC - /** - * @param from the source entity, its position is sent - * @param gs the global sound def - * @param r a random number in 0..1 - */ - void globalsound(int channel, entity from, entity gs, float r, int chan, float vol, float atten) - { - if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return; - WriteHeader(channel, globalsound); - WriteByte(channel, gs.m_id); - WriteByte(channel, r * 255); - WriteByte(channel, etof(from)); - WriteByte(channel, fabs(chan)); - WriteByte(channel, floor(vol * 255)); - WriteByte(channel, floor(atten * 64)); + string GlobalSound_sample(string pair, float r); + + #ifdef SVQC + /** + * @param from the source entity, its position is sent + * @param gs the global sound def + * @param r a random number in 0..1 + */ + void globalsound(int channel, entity from, entity gs, float r, int chan, float _vol, float _atten) + { + //assert(IS_PLAYER(from), eprint(from)); + if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return; + if (!autocvar_g_debug_globalsounds) { + string sample = GlobalSound_sample(gs.m_globalsoundstr, r); + switch (channel) { + case MSG_ONE: + soundto(channel, from, chan, sample, _vol, _atten); + break; + case MSG_ALL: + _sound(from, chan, sample, _vol, _atten); + break; + } + return; + } + WriteHeader(channel, globalsound); + WriteByte(channel, gs.m_id); + WriteByte(channel, r * 255); + WriteByte(channel, etof(from)); + WriteByte(channel, chan); + WriteByte(channel, floor(_vol * 255)); + WriteByte(channel, floor(_atten * 64)); + entcs_force_origin(from); 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); + /** + * @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) + { + //assert(IS_PLAYER(from), eprint(from)); + if (channel == MSG_ONE && !IS_REAL_CLIENT(msg_entity)) return; + if (!autocvar_g_debug_globalsounds) { + //UpdatePlayerSounds(from); + string s = from.(ps.m_playersoundfld); + string sample = GlobalSound_sample(s, r); + switch (channel) { + case MSG_ONE: + soundto(channel, from, chan, sample, _vol, _atten); + break; + case MSG_ALL: + _sound(from, chan, sample, _vol, _atten); + break; + } + return; + } + WriteHeader(channel, playersound); + WriteByte(channel, ps.m_id); + WriteByte(channel, r * 255); + WriteByte(channel, etof(from)); + WriteByte(channel, chan); + WriteByte(channel, floor(_vol * 255)); + WriteByte(channel, floor(_atten * 64)); + entcs_force_origin(from); + vector o = from.origin + 0.5 * (from.mins + from.maxs); + WriteCoord(channel, o.x); + WriteCoord(channel, o.y); + WriteCoord(channel, o.z); + } + #endif #ifdef CSQC NET_HANDLE(globalsound, bool isnew) { - entity gs = GlobalSounds_from(ReadByte()); - float r = ReadByte() / 255; - string sample = GlobalSound_sample(gs.m_globalsoundstr, r); - int who = ReadByte(); - int chan = ReadByte(); - float vol = ReadByte() / 255; - float atten = ReadByte() / 64; + entity gs = GlobalSounds_from(ReadByte()); + float r = ReadByte() / 255; + string sample = GlobalSound_sample(gs.m_globalsoundstr, r); + int who = ReadByte(); + entity e = entcs_receiver(who - 1); + int chan = ReadSByte(); + float vol = ReadByte() / 255; + float atten = ReadByte() / 64; + vector o; + o.x = ReadCoord(); + o.y = ReadCoord(); + o.z = ReadCoord(); + // TODO: is this really what we want to be doing? Footsteps that follow the player at head height? + if (who == player_currententnum) e = findfloat(NULL, entnum, who); // play at camera position for full volume + else if (e) e.origin = o; + if (e) + { + sound7(e, chan, sample, vol, atten, 0, 0); + } + else + { + // Can this happen? + LOG_WARNINGF("Missing entcs data for player %d\n", who); + sound8(e, o, chan, sample, vol, atten, 0, 0); + } + return true; + } + + NET_HANDLE(playersound, bool isnew) + { + entity ps = PlayerSounds_from(ReadByte()); + float r = ReadByte() / 255; + int who = ReadByte(); + entity e = entcs_receiver(who - 1); + UpdatePlayerSounds(e); + string s = e.(ps.m_playersoundfld); + string sample = GlobalSound_sample(s, r); + int chan = ReadSByte(); + float vol = ReadByte() / 255; + float atten = ReadByte() / 64; vector o; o.x = ReadCoord(); o.y = ReadCoord(); o.z = ReadCoord(); - if (who == player_localnum + 1) - { - // client knows better, play at current position to unlag - entity e = findfloat(world, entnum, who); + if (who == player_currententnum) e = findfloat(NULL, entnum, who); // play at camera position for full volume + else if (e) e.origin = o; + if (e) + { + // TODO: for non-visible players, origin should probably continue to be updated as long as the sound is playing sound7(e, chan, sample, vol, atten, 0, 0); - } - else - { - entity e = new(globalsound); - e.origin = o; + } + else + { + // Can this happen? + LOG_WARNINGF("Missing entcs data for player %d\n", who); 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) - { - int n; - { - string s = cdr(pair); - if (s) n = stof(s); - else n = 0; - } - string sample = car(pair); - if (n > 0) sample = sprintf("%s%d.wav", sample, floor(r * n + 1)); // randomization - else sample = sprintf("%s.wav", sample); - return sample; - } + string GlobalSound_sample(string pair, float r) + { + int n; + { + string s = cdr(pair); + if (s) n = stof(s); + else n = 0; + } + string sample = car(pair); + if (n > 0) sample = sprintf("%s%d.wav", sample, floor(r * n + 1)); // randomization + else sample = sprintf("%s.wav", sample); + return sample; + } void PrecacheGlobalSound(string sample) { @@ -100,90 +188,76 @@ } } - #ifdef SVQC + entity GetVoiceMessage(string type) + { + FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == true, return it); + return NULL; + } - int GetVoiceMessageVoiceType(string type) - { - if (type == "taunt") return VOICETYPE_TAUNT; - if (type == "teamshoot") return VOICETYPE_LASTATTACKER; - return VOICETYPE_TEAMRADIO; - } + entity GetPlayerSound(string type) + { + FOREACH(PlayerSounds, it.m_playersoundstr == type && it.instanceOfVoiceMessage == false, return it); + return NULL; + } + + .string _GetPlayerSoundSampleField(string type, bool voice) + { + GetPlayerSoundSampleField_notFound = false; + entity e = voice ? GetVoiceMessage(type) : GetPlayerSound(type); + if (e) return e.m_playersoundfld; + GetPlayerSoundSampleField_notFound = true; + return playersound_taunt.m_playersoundfld; + } - .string GetVoiceMessageSampleField(string type) + .string GetVoiceMessageSampleField(string type) + { + return _GetPlayerSoundSampleField(type, true); + } + + void PrecachePlayerSounds(string f) + { + int fh = fopen(f, FILE_READ); + if (fh < 0) { - GetPlayerSoundSampleField_notFound = false; - switch (type) - { - #define X(m) case #m: return playersound_##m; - ALLVOICEMSGS(X) - #undef X - } - GetPlayerSoundSampleField_notFound = true; - return playersound_taunt; + LOG_WARNINGF("Player sound file not found: %s\n", f); + return; } - - .string GetPlayerSoundSampleField(string type) + for (string s; (s = fgets(fh)); ) { - GetPlayerSoundSampleField_notFound = false; - switch (type) + int n = tokenize_console(s); + if (n != 3) { - #define X(m) case #m: return playersound_##m; - ALLPLAYERSOUNDS(X) - #undef X + if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s); + continue; } - GetPlayerSoundSampleField_notFound = true; - return playersound_taunt; + string file = argv(1); + string variants = argv(2); + PrecacheGlobalSound(strcat(file, " ", variants)); } + fclose(fh); + } - string allvoicesamples; + //#ifdef CSQC - void PrecachePlayerSounds(string f) + .string GetPlayerSoundSampleField(string type) { - int fh = fopen(f, FILE_READ); - if (fh < 0) - { - LOG_WARNINGF("Player sound file not found: %s\n", f); - return; - } - for (string s; (s = fgets(fh)); ) - { - int n = tokenize_console(s); - if (n != 3) - { - if (n != 0) LOG_WARNINGF("Invalid sound info line: %s\n", s); - continue; - } - string file = argv(1); - string variants = argv(2); - PrecacheGlobalSound(strcat(file, " ", variants)); - } - fclose(fh); - - if (!allvoicesamples) - { - #define X(m) allvoicesamples = strcat(allvoicesamples, " ", #m); - ALLVOICEMSGS(X) - #undef X - allvoicesamples = strzone(substring(allvoicesamples, 1, -1)); - } + return _GetPlayerSoundSampleField(type, false); } void ClearPlayerSounds(entity this) { - #define X(m) \ - if (this.playersound_##m) \ - { \ - strunzone(this.playersound_##m); \ - this.playersound_##m = string_null; \ + FOREACH(PlayerSounds, true, { + .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) { @@ -208,35 +282,44 @@ } 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; } - .int modelindex_for_playersound; + .string model_for_playersound; .int skin_for_playersound; + bool autocvar_g_debug_defaultsounds; + void UpdatePlayerSounds(entity this) { - if (this.modelindex == this.modelindex_for_playersound && this.skin == this.skin_for_playersound) return; - this.modelindex_for_playersound = this.modelindex; + if (this.model == this.model_for_playersound && this.skin == this.skin_for_playersound) return; + if (this.model_for_playersound) strunzone(this.model_for_playersound); + this.model_for_playersound = strzone(this.model); this.skin_for_playersound = this.skin; ClearPlayerSounds(this); - LoadPlayerSounds("sound/player/default.sounds", true); + LoadPlayerSounds(this, "sound/player/default.sounds", true); + if (this.model == "null" + #ifdef SVQC + && autocvar_g_debug_globalsounds + #endif + ) return; if (autocvar_g_debug_defaultsounds) return; - if (!LoadPlayerSounds(get_model_datafilename(this.model, this.skin, "sounds"), false)) - LoadPlayerSounds(get_model_datafilename( - this.model, 0, - "sounds"), - true); + if (LoadPlayerSounds(this, get_model_datafilename(this.model, this.skin, "sounds"), false)) return; + LoadPlayerSounds(this, get_model_datafilename(this.model, 0, "sounds"), true); } - void _GlobalSound(entity gs, string sample, int chan, int voicetype, bool fake) + //#endif + + #ifdef SVQC + + void _GlobalSound(entity this, 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; + if(this.classname == "body") return; float r = random(); if (sample != "") sample = GlobalSound_sample(sample, r); switch (voicetype) @@ -252,6 +335,7 @@ { 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); } } @@ -259,29 +343,30 @@ msg_entity = this; if (IS_REAL_CLIENT(msg_entity)) { - if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NONE); - else soundto(MSG_ONE, this, chan, sample, VOL_BASE, ATTEN_NONE); + 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; } case VOICETYPE_TEAMRADIO: { #define X() \ - do \ + MACRO_BEGIN \ { \ 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) + } MACRO_END if (fake) { msg_entity = this; X(); } else { - FOR_EACH_REALCLIENT(msg_entity) - { - if (!teamplay || msg_entity.team == this.team) X(); - } + FOREACH_CLIENT(IS_REAL_CLIENT(it) && (!teamplay || msg_entity.team == this.team), { + msg_entity = it; + X(); + }); } #undef X break; @@ -290,14 +375,14 @@ case VOICETYPE_TAUNT: { if (voicetype == VOICETYPE_AUTOTAUNT) if (!sv_autotaunt) { break; }else {} - else if (IS_PLAYER(this) && this.deadflag == DEAD_NO) animdecide_setaction(this, ANIMACTION_TAUNT, + else if (IS_PLAYER(this) && !IS_DEAD(this)) animdecide_setaction(this, ANIMACTION_TAUNT, true); if (!sv_taunt) break; if (autocvar_sv_gentle) break; float tauntrand = 0; if (voicetype == VOICETYPE_AUTOTAUNT) tauntrand = random(); #define X() \ - do \ + MACRO_BEGIN \ { \ if (voicetype != VOICETYPE_AUTOTAUNT || tauntrand < msg_entity.cvar_cl_autotaunt) \ { \ @@ -306,10 +391,10 @@ ATTEN_MAX) \ : ATTEN_NONE; \ if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASEVOICE, atten); \ - else soundto(MSG_ONE, this, chan, sample, 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) + } MACRO_END if (fake) { msg_entity = this; @@ -317,10 +402,10 @@ } else { - FOR_EACH_REALCLIENT(msg_entity) - { + FOREACH_CLIENT(IS_REAL_CLIENT(it), { + msg_entity = it; X(); - } + }); } #undef X break; @@ -331,12 +416,14 @@ if (fake) { if (gs) globalsound(MSG_ONE, this, gs, r, chan, VOL_BASE, ATTEN_NORM); - else soundto(MSG_ONE, this, chan, sample, 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 _sound(this, chan, sample, VOL_BASE, ATTEN_NORM); + 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; } @@ -348,29 +435,5 @@ } } - 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