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