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