1#include "all.qh" 2#ifdef SVQC 3 4bool autocvar_bot_sound_monopoly; 5 6.entity realowner; 7bool sound_allowed(int to, entity e) 8{ 9 for ( ; ; ) 10 { 11 if (e.classname == "body") e = e.enemy; 12 else if (e.realowner && e.realowner != e) e = e.realowner; 13 else if (e.owner && e.owner != e) e = e.owner; 14 else break; 15 } 16 // sounds to self may always pass 17 if (to == MSG_ONE && e == msg_entity) return true; 18 // sounds by players can be removed 19 if (autocvar_bot_sound_monopoly && IS_REAL_CLIENT(e)) return false; 20 // anything else may pass 21 return true; 22} 23 24/** hack: string precache_sound(string s) = #19; */ 25int precache_sound_index(string s) = #19; 26 27const int SVC_SOUND = 6; 28const int SVC_STOPSOUND = 16; 29 30const int SND_VOLUME = BIT(0); 31const int SND_ATTENUATION = BIT(1); 32const int SND_LARGEENTITY = BIT(3); 33const int SND_LARGESOUND = BIT(4); 34 35void soundtoat(int to, entity e, vector o, int chan, string samp, float vol, float attenu) 36{ 37 if (!sound_allowed(to, e)) return; 38 int entno = etof(e); 39 int idx = precache_sound_index(samp); 40 attenu = floor(attenu * 64); 41 vol = floor(vol * 255); 42 int sflags = 0; 43 if (vol != 255) sflags |= SND_VOLUME; 44 if (attenu != 64) sflags |= SND_ATTENUATION; 45 if (entno >= 8192 || chan < 0 || chan > 7) sflags |= SND_LARGEENTITY; 46 if (idx >= 256) sflags |= SND_LARGESOUND; 47 WriteByte(to, SVC_SOUND); 48 WriteByte(to, sflags); 49 if (sflags & SND_VOLUME) WriteByte(to, vol); 50 if (sflags & SND_ATTENUATION) WriteByte(to, attenu); 51 if (sflags & SND_LARGEENTITY) 52 { 53 WriteShort(to, entno); 54 WriteByte(to, chan); 55 } 56 else 57 { 58 WriteShort(to, (entno << 3) | chan); 59 } 60 if (sflags & SND_LARGESOUND) WriteShort(to, idx); 61 else WriteByte(to, idx); 62 WriteCoord(to, o.x); 63 WriteCoord(to, o.y); 64 WriteCoord(to, o.z); 65} 66 67void soundto(int _dest, entity e, int chan, string samp, float vol, float _atten) 68{ 69 if (!sound_allowed(_dest, e)) return; 70 vector o = e.origin + 0.5 * (e.mins + e.maxs); 71 soundtoat(_dest, e, o, chan, samp, vol, _atten); 72} 73void soundat(entity e, vector o, int chan, string samp, float vol, float _atten) 74{ 75 soundtoat(((chan & 8) ? MSG_ALL : MSG_BROADCAST), e, o, chan, samp, vol, _atten); 76} 77void stopsoundto(int _dest, entity e, int chan) 78{ 79 if (!sound_allowed(_dest, e)) return; 80 int entno = etof(e); 81 if (entno >= 8192 || chan < 0 || chan > 7) 82 { 83 int idx = precache_sound_index(SND(Null)); 84 int sflags = SND_LARGEENTITY; 85 if (idx >= 256) sflags |= SND_LARGESOUND; 86 WriteByte(_dest, SVC_SOUND); 87 WriteByte(_dest, sflags); 88 WriteShort(_dest, entno); 89 WriteByte(_dest, chan); 90 if (sflags & SND_LARGESOUND) WriteShort(_dest, idx); 91 else WriteByte(_dest, idx); 92 WriteCoord(_dest, e.origin.x); 93 WriteCoord(_dest, e.origin.y); 94 WriteCoord(_dest, e.origin.z); 95 } 96 else 97 { 98 WriteByte(_dest, SVC_STOPSOUND); 99 WriteShort(_dest, entno * 8 + chan); 100 } 101} 102void stopsound(entity e, int chan) 103{ 104 if (!sound_allowed(MSG_BROADCAST, e)) return; 105 stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast 106 stopsoundto(MSG_ALL, e, chan); // in case of packet loss 107} 108 109void play2(entity e, string filename) 110{ 111 msg_entity = e; 112 soundtoat(MSG_ONE, NULL, '0 0 0', CH_INFO, filename, VOL_BASE, ATTEN_NONE); 113} 114 115.float spamtime; 116/** use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame) */ 117float spamsound(entity e, int chan, string samp, float vol, float _atten) 118{ 119 if (!sound_allowed(MSG_BROADCAST, e)) return false; 120 if (time > e.spamtime) 121 { 122 e.spamtime = time; 123 _sound(e, chan, samp, vol, _atten); 124 return true; 125 } 126 return false; 127} 128 129void play2team(float t, string filename) 130{ 131 if (autocvar_bot_sound_monopoly) return; 132 FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it) && it.team == t, play2(it, filename)); 133} 134 135void play2all(string samp) 136{ 137 if (autocvar_bot_sound_monopoly) return; 138 _sound(NULL, CH_INFO, samp, VOL_BASE, ATTEN_NONE); 139} 140 141#endif 142