]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/sounds/all.qc
Merge branch 'master' into Mirio/balance
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / sounds / all.qc
1 #include "all.qh"
2 #ifdef SVQC
3
4 bool autocvar_bot_sound_monopoly;
5
6 .entity realowner;
7 bool 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; */
25 int precache_sound_index(string s) = #19;
26
27 const int SVC_SOUND = 6;
28 const int SVC_STOPSOUND = 16;
29
30 const int SND_VOLUME = BIT(0);
31 const int SND_ATTENUATION = BIT(1);
32 const int SND_LARGEENTITY = BIT(3);
33 const int SND_LARGESOUND = BIT(4);
34
35 void 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
67 void 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 }
73 void 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 }
77 void 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 }
102 void 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
109 void 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) */
117 float 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
129 void 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
135 void 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