]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/tuba.qc
Remove direct server #includes from client
[xonotic/xonotic-data.pk3dir.git] / qcsrc / client / tuba.qc
1 #include "tuba.qh"
2
3 #include "autocvars.qh"
4 #include "main.qh"
5
6 #include "../common/constants.qh"
7 #include "../common/util.qh"
8
9 #include "../warpzonelib/mathlib.qh"
10
11 #define TUBA_STARTNOTE(i, n) strcat("weapons/tuba", (i ? ftos(i) : ""), "_loopnote", ftos(n), ".wav")
12
13 const int TUBA_MIN = -18;
14 const int TUBA_MAX = 27;
15 const int TUBA_INSTRUMENTS = 3;
16
17 class(Tuba) .int note;
18 class(Tuba) .bool tuba_attenuate;
19 class(Tuba) .float tuba_volume;
20 class(Tuba) .float tuba_volume_initial;
21 class(Tuba) .int tuba_instrument;
22
23 int Tuba_PitchStep;
24
25 void tubasound(entity e, bool restart)
26 {
27         string snd1 = string_null;
28         if (Tuba_PitchStep) {
29                 float vol1 = 1;
30                 float speed1 = 1;
31                 string snd2 = string_null;
32                 float vol2 = 0;
33                 float speed2 = 1;
34
35                 int m = pymod(e.note, Tuba_PitchStep);
36                 if (m) {
37                         if (e.note - m < TUBA_MIN) {
38                                 if (restart) {
39                                         snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m + Tuba_PitchStep);
40                                 }
41                                 speed1 = pow(2.0, (m - Tuba_PitchStep) / 12.0);
42                         } else if (e.note - m + Tuba_PitchStep > TUBA_MAX) {
43                                 if (restart) {
44                                         snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m);
45                                 }
46                                 speed1 = pow(2.0, m / 12.0);
47                         } else {
48                                 if (restart) {
49                                         snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m);
50                                 }
51                                 vol1 = cos(M_PI_2 * m / Tuba_PitchStep);
52                                 speed1 = pow(2.0, m / 12.0);
53                                 if (restart) {
54                                         snd2 = TUBA_STARTNOTE(e.tuba_instrument, e.note - m + Tuba_PitchStep);
55                                 }
56                                 vol2 = sin(M_PI_2 * m / Tuba_PitchStep);
57                                 speed2 = pow(2.0, (m - Tuba_PitchStep) / 12.0);
58                         }
59                 } else if (restart) {
60                         snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note);
61                 }
62
63                 sound7(e, CH_TUBA_SINGLE, snd1, e.tuba_volume * vol1, e.tuba_attenuate * autocvar_g_balance_tuba_attenuation, 100 * speed1, 0);
64                 if (vol2) {
65                         sound7(e.enemy, CH_TUBA_SINGLE, snd2, e.tuba_volume * vol2, e.tuba_attenuate * autocvar_g_balance_tuba_attenuation, 100 * speed2, 0);
66                 }
67         } else {
68                 if (restart) {
69                         snd1 = TUBA_STARTNOTE(e.tuba_instrument, e.note);
70                 }
71                 sound(e, CH_TUBA_SINGLE, snd1, e.tuba_volume, e.tuba_attenuate * autocvar_g_balance_tuba_attenuation);
72         }
73 }
74
75 void Ent_TubaNote_Think()
76 {
77         float f = autocvar_g_balance_tuba_fadetime;
78         if (f > 0) {
79                 self.tuba_volume -= frametime * self.tuba_volume_initial / f;
80         } else {
81                 self.tuba_volume = 0;
82         }
83         self.nextthink = time;
84         if (self.tuba_volume <= 0) {
85                 sound(self, CH_TUBA_SINGLE, "misc/null.wav", 0, 0);
86                 if (self.enemy) {
87                         sound(self.enemy, CH_TUBA_SINGLE, "misc/null.wav", 0, 0);
88                         remove(self.enemy);
89                 }
90                 remove(self);
91         } else {
92                 tubasound(self, 0);
93         }
94 }
95
96 void Ent_TubaNote_UpdateSound()
97 {
98         self.enemy.tuba_volume = bound(0, VOL_BASE * autocvar_g_balance_tuba_volume, 1);
99         self.enemy.tuba_volume_initial = self.enemy.tuba_volume;
100         self.enemy.note = self.note;
101         self.enemy.tuba_instrument = self.tuba_instrument;
102         tubasound(self.enemy, 1);
103 }
104
105 void Ent_TubaNote_StopSound()
106 {
107         self.enemy.nextthink = time;
108         self.enemy = world;
109 }
110
111 void Ent_TubaNote(bool isNew)
112 {
113         bool upd = false;
114         int f = ReadByte();
115         if (f & 1) {
116                 int n = ReadChar();
117                 int i = ReadByte();
118                 bool att = (i & 1);
119                 i >>= 1;
120
121                 if (self.enemy) {
122                         if (n != self.note || i != self.tuba_instrument || isNew) {
123                                 Ent_TubaNote_StopSound();
124                         }
125                 } else {
126                         self.enemy = spawn();
127                         self.enemy.classname = "tuba_note";
128                         if (Tuba_PitchStep) {
129                                 self.enemy.enemy = spawn();
130                                 self.enemy.enemy.classname = "tuba_note_2";
131                         }
132                         isNew = true;
133                 }
134
135                 self.enemy.tuba_attenuate = att;
136
137                 if (isNew) {
138                         self.note = n;
139                         self.tuba_instrument = i;
140                         upd = true;
141                 }
142         }
143
144         if (f & 2) {
145                 self.enemy.origin_x = ReadCoord();
146                 self.enemy.origin_y = ReadCoord();
147                 self.enemy.origin_z = ReadCoord();
148                 setorigin(self.enemy, self.enemy.origin);
149                 if (self.enemy.enemy) {
150                         setorigin(self.enemy.enemy, self.enemy.origin);
151                 }
152         }
153
154         self.think = Ent_TubaNote_StopSound;
155         self.entremove = Ent_TubaNote_StopSound;
156         self.enemy.think = Ent_TubaNote_Think;
157         self.enemy.nextthink = time + 10;
158
159         if (upd) {
160                 Ent_TubaNote_UpdateSound();
161         }
162 }
163
164 void Tuba_Precache()
165 {
166         Tuba_PitchStep = autocvar_g_balance_tuba_pitchstep;
167         if (Tuba_PitchStep) {
168                 if (!checkextension("DP_SND_SOUND7_WIP2") && !checkextension("DP_SND_SOUND7")) {
169                         print("^1NOTE:^7 requested pitch shifting, but not supported by this engine build\n");
170                         Tuba_PitchStep = 0;
171                 }
172         }
173         for (int n = TUBA_MIN; n <= TUBA_MAX; ++n) {
174                 if (!Tuba_PitchStep || pymod(n, Tuba_PitchStep) == 0) {
175                         for (int i = 0; i < TUBA_INSTRUMENTS; ++i) {
176                                 precache_sound(TUBA_STARTNOTE(i, n));
177                         }
178                 }
179         }
180 }