]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/client/tuba.qc
ed2964936a3bd3942ba90cf1af2921c5d5197fcd
[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) 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 = spawn();
122                         self.enemy.classname = "tuba_note";
123                         if (Tuba_PitchStep) {
124                                 self.enemy.enemy = spawn();
125                                 self.enemy.enemy.classname = "tuba_note_2";
126                         }
127                         isNew = true;
128                 }
129
130                 self.enemy.tuba_attenuate = att;
131
132                 if (isNew) {
133                         self.note = n;
134                         self.tuba_instrument = i;
135                         upd = true;
136                 }
137         }
138
139         if (f & 2) {
140                 self.enemy.origin_x = ReadCoord();
141                 self.enemy.origin_y = ReadCoord();
142                 self.enemy.origin_z = ReadCoord();
143                 setorigin(self.enemy, self.enemy.origin);
144                 if (self.enemy.enemy) {
145                         setorigin(self.enemy.enemy, self.enemy.origin);
146                 }
147         }
148
149         self.think = Ent_TubaNote_StopSound;
150         self.entremove = Ent_TubaNote_StopSound;
151         self.enemy.think = Ent_TubaNote_Think;
152         self.enemy.nextthink = time + 10;
153
154         if (upd) {
155                 Ent_TubaNote_UpdateSound();
156         }
157 }
158
159 void Tuba_Precache()
160 {
161         Tuba_PitchStep = autocvar_g_balance_tuba_pitchstep;
162         if (Tuba_PitchStep) {
163                 if (!checkextension("DP_SND_SOUND7_WIP2") && !checkextension("DP_SND_SOUND7")) {
164                         LOG_INFO("^1NOTE:^7 requested pitch shifting, but not supported by this engine build\n");
165                         Tuba_PitchStep = 0;
166                 }
167         }
168         for (int n = TUBA_MIN; n <= TUBA_MAX; ++n) {
169                 if (!Tuba_PitchStep || pymod(n, Tuba_PitchStep) == 0) {
170                         for (int i = 0; i < TUBA_INSTRUMENTS; ++i) {
171                                 precache_sound(TUBA_STARTNOTE(i, n));
172                         }
173                 }
174         }
175 }