]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/triggers/target/music.qc
Merge branch 'master' into Mario/bulldozer
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / triggers / target / music.qc
1 #if defined(CSQC)
2 #elif defined(MENUQC)
3 #elif defined(SVQC)
4     #include "../../constants.qh"
5     #include "../../../server/constants.qh"
6     #include "../../../server/defs.qh"
7 #endif
8
9 REGISTER_NET_TEMP(TE_CSQC_TARGET_MUSIC)
10 REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_MUSIC)
11
12 #ifdef SVQC
13
14 // values:
15 //   volume
16 //   noise
17 //   targetname
18 //   lifetime
19 //   fade_time
20 //   fade_rate
21 // when triggered, the music is overridden for activator until lifetime (or forever, if lifetime is 0)
22 // when targetname is not set, THIS ONE is default
23 void target_music_sendto(float to, float is)
24 {SELFPARAM();
25         WriteHeader(to, TE_CSQC_TARGET_MUSIC);
26         WriteShort(to, num_for_edict(self));
27         WriteByte(to, self.volume * 255.0 * is);
28         WriteByte(to, self.fade_time * 16.0);
29         WriteByte(to, self.fade_rate * 16.0);
30         WriteByte(to, self.lifetime);
31         WriteString(to, self.noise);
32 }
33 void target_music_reset()
34 {SELFPARAM();
35         if(self.targetname == "")
36                 target_music_sendto(MSG_ALL, 1);
37 }
38 void target_music_kill()
39 {
40         for(self = world; (self = find(self, classname, "target_music")); )
41         {
42                 self.volume = 0;
43                 if(self.targetname == "")
44                         target_music_sendto(MSG_ALL, 1);
45                 else
46                         target_music_sendto(MSG_ALL, 0);
47         }
48 }
49 void target_music_use()
50 {
51         if(!activator)
52                 return;
53         if(IS_REAL_CLIENT(activator))
54         {
55                 msg_entity = activator;
56                 target_music_sendto(MSG_ONE, 1);
57         }
58         entity head;
59         FOR_EACH_SPEC(head) if(head.enemy == activator) { msg_entity = head; target_music_sendto(MSG_ONE, 1); }
60 }
61 spawnfunc(target_music)
62 {
63         self.use = target_music_use;
64         self.reset = target_music_reset;
65         if(!self.volume)
66                 self.volume = 1;
67         if(self.targetname == "")
68                 target_music_sendto(MSG_INIT, 1);
69         else
70                 target_music_sendto(MSG_INIT, 0);
71 }
72 void TargetMusic_RestoreGame()
73 {SELFPARAM();
74         for(entity e = world; (e = find(e, classname, "target_music")); )
75         {
76                 setself(e);
77                 if(self.targetname == "")
78                         target_music_sendto(MSG_INIT, 1);
79                 else
80                         target_music_sendto(MSG_INIT, 0);
81         }
82 }
83 // values:
84 //   volume
85 //   noise
86 //   targetname
87 //   fade_time
88 // spawnflags:
89 //   1 = START_OFF
90 // when triggered, it is disabled/enabled for everyone
91 bool trigger_music_SendEntity(entity this, entity to, float sf)
92 {
93         WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
94         sf &= ~0x80;
95         if(self.cnt)
96                 sf |= 0x80;
97         WriteByte(MSG_ENTITY, sf);
98         if(sf & 4)
99         {
100                 WriteCoord(MSG_ENTITY, self.origin.x);
101                 WriteCoord(MSG_ENTITY, self.origin.y);
102                 WriteCoord(MSG_ENTITY, self.origin.z);
103         }
104         if(sf & 1)
105         {
106                 if(self.model != "null")
107                 {
108                         WriteShort(MSG_ENTITY, self.modelindex);
109                         WriteCoord(MSG_ENTITY, self.mins.x);
110                         WriteCoord(MSG_ENTITY, self.mins.y);
111                         WriteCoord(MSG_ENTITY, self.mins.z);
112                         WriteCoord(MSG_ENTITY, self.maxs.x);
113                         WriteCoord(MSG_ENTITY, self.maxs.y);
114                         WriteCoord(MSG_ENTITY, self.maxs.z);
115                 }
116                 else
117                 {
118                         WriteShort(MSG_ENTITY, 0);
119                         WriteCoord(MSG_ENTITY, self.maxs.x);
120                         WriteCoord(MSG_ENTITY, self.maxs.y);
121                         WriteCoord(MSG_ENTITY, self.maxs.z);
122                 }
123                 WriteByte(MSG_ENTITY, self.volume * 255.0);
124                 WriteByte(MSG_ENTITY, self.fade_time * 16.0);
125                 WriteByte(MSG_ENTITY, self.fade_rate * 16.0);
126                 WriteString(MSG_ENTITY, self.noise);
127         }
128         return 1;
129 }
130 void trigger_music_reset()
131 {SELFPARAM();
132         self.cnt = !(self.spawnflags & 1);
133         self.SendFlags |= 0x80;
134 }
135 void trigger_music_use()
136 {SELFPARAM();
137         self.cnt = !self.cnt;
138         self.SendFlags |= 0x80;
139 }
140 spawnfunc(trigger_music)
141 {
142         if(self.model != "")
143                 _setmodel(self, self.model);
144         if(!self.volume)
145                 self.volume = 1;
146         if(!self.modelindex)
147         {
148                 setorigin(self, self.origin + self.mins);
149                 setsize(self, '0 0 0', self.maxs - self.mins);
150         }
151         trigger_music_reset();
152
153         self.use = trigger_music_use;
154         self.reset = trigger_music_reset;
155
156         Net_LinkEntity(self, false, 0, trigger_music_SendEntity);
157 }
158 #elif defined(CSQC)
159
160 void TargetMusic_Advance()
161 {
162         // run AFTER all the thinks!
163         entity best, e;
164         float vol, vol0;
165         best = music_default;
166         if(music_target && time < music_target.lifetime)
167                 best = music_target;
168         if(music_trigger)
169                 best = music_trigger;
170         for(e = world; (e = findfloat(e, enttype, NET_ENT_CLIENT_TRIGGER_MUSIC.m_id)); ) if(e.noise)
171         {
172                 vol0 = e.lastvol;
173                 if(getsoundtime(e, CH_BGM_SINGLE) < 0)
174                 {
175                         vol0 = -1;
176                 }
177                 if(e == best)
178                 {
179                         // increase volume
180                         if(e.fade_time > 0)
181                                 e.state = bound(0, e.state + frametime / e.fade_time, 1);
182                         else
183                                 e.state = 1;
184                 }
185                 else
186                 {
187                         // decrease volume
188                         if(e.fade_rate > 0)
189                                 e.state = bound(0, e.state - frametime / e.fade_rate, 1);
190                         else
191                                 e.state = 0;
192                 }
193                 vol = e.state * e.volume * autocvar_bgmvolume;
194                 if(vol != vol0)
195                 {
196                         if(vol0 < 0)
197                                 _sound(e, CH_BGM_SINGLE, e.noise, vol, ATTEN_NONE); // restart
198                         else
199                                 _sound(e, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
200                         e.lastvol = vol;
201                 }
202         }
203         music_trigger = world;
204
205         if(best)
206                 bgmtime = getsoundtime(best, CH_BGM_SINGLE);
207         else
208                 bgmtime = gettime(GETTIME_CDTRACK);
209 }
210
211 NET_HANDLE(TE_CSQC_TARGET_MUSIC, bool isNew)
212 {
213         Net_TargetMusic();
214         return true;
215 }
216
217 void Net_TargetMusic()
218 {
219         int id = ReadShort();
220         float vol = ReadByte() / 255.0;
221         float fai = ReadByte() / 16.0;
222         float fao = ReadByte() / 16.0;
223         float tim = ReadByte();
224         string noi = ReadString();
225
226         entity e;
227         for(e = world; (e = findfloat(e, enttype, NET_ENT_CLIENT_TRIGGER_MUSIC.m_id)); )
228         {
229                 if(e.count == id)
230                         break;
231         }
232         if(!e)
233         {
234                 e = spawn();
235                 e.enttype = NET_ENT_CLIENT_TRIGGER_MUSIC.m_id;
236                 e.count = id;
237         }
238         if(e.noise != noi)
239         {
240                 if(e.noise)
241                         strunzone(e.noise);
242                 e.noise = strzone(noi);
243                 precache_sound(e.noise);
244                 _sound(e, CH_BGM_SINGLE, e.noise, 0, ATTEN_NONE);
245                 if(getsoundtime(e, CH_BGM_SINGLE) < 0)
246                 {
247                         LOG_TRACEF("Cannot initialize sound %s\n", e.noise);
248                         strunzone(e.noise);
249                         e.noise = string_null;
250                 }
251         }
252         e.volume = vol;
253         e.fade_time = fai;
254         e.fade_rate = fao;
255         if(vol > 0)
256         {
257                 if(tim == 0)
258                 {
259                         music_default = e;
260                         if(!music_disabled)
261                         {
262                                 e.state = 2;
263                                 cvar_settemp("music_playlist_index", "-1"); // don't use playlists
264                                 localcmd("cd stop\n"); // just in case
265                                 music_disabled = 1;
266                         }
267                 }
268                 else
269                 {
270                         music_target = e;
271                         e.lifetime = time + tim;
272                 }
273         }
274 }
275
276 void Ent_TriggerMusic_Think()
277 {SELFPARAM();
278         if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, self, world))
279         {
280                 music_trigger = self;
281         }
282         self.nextthink = time;
283 }
284
285 void Ent_TriggerMusic_Remove()
286 {SELFPARAM();
287         if(self.noise)
288                 strunzone(self.noise);
289         self.noise = string_null;
290 }
291
292 NET_HANDLE(ENT_CLIENT_TRIGGER_MUSIC, bool isnew)
293 {
294         int f = ReadByte();
295         if(f & 4)
296         {
297                 self.origin_x = ReadCoord();
298                 self.origin_y = ReadCoord();
299                 self.origin_z = ReadCoord();
300         }
301         if(f & 1)
302         {
303                 self.modelindex = ReadShort();
304                 if(self.modelindex)
305                 {
306                         self.mins_x = ReadCoord();
307                         self.mins_y = ReadCoord();
308                         self.mins_z = ReadCoord();
309                         self.maxs_x = ReadCoord();
310                         self.maxs_y = ReadCoord();
311                         self.maxs_z = ReadCoord();
312                 }
313                 else
314                 {
315                         self.mins    = '0 0 0';
316                         self.maxs_x = ReadCoord();
317                         self.maxs_y = ReadCoord();
318                         self.maxs_z = ReadCoord();
319                 }
320
321                 self.volume = ReadByte() / 255.0;
322                 self.fade_time = ReadByte() / 16.0;
323                 self.fade_rate = ReadByte() / 16.0;
324                 string s = self.noise;
325                 if(self.noise)
326                         strunzone(self.noise);
327                 self.noise = strzone(ReadString());
328                 if(self.noise != s)
329                 {
330                         precache_sound(self.noise);
331                         _sound(self, CH_BGM_SINGLE, self.noise, 0, ATTEN_NONE);
332                         if(getsoundtime(self, CH_BGM_SINGLE) < 0)
333                         {
334                                 LOG_TRACEF("Cannot initialize sound %s\n", self.noise);
335                                 strunzone(self.noise);
336                                 self.noise = string_null;
337                         }
338                 }
339         }
340
341         setorigin(self, self.origin);
342         setsize(self, self.mins, self.maxs);
343         self.cnt = 1;
344         self.think = Ent_TriggerMusic_Think;
345         self.nextthink = time;
346         return true;
347 }
348
349 #endif