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