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