]> de.git.xonotic.org Git - voretournament/voretournament.git/blob - data/qcsrc/client/particles.qc
Initial checkout of Vore Tournament 0.1.alpha.
[voretournament/voretournament.git] / data / qcsrc / client / particles.qc
1 .float dphitcontentsmask;\r
2 \r
3 .float cnt; // effect number\r
4 .vector velocity; // particle velocity\r
5 .float waterlevel; // direction jitter\r
6 .float count; // count multiplier\r
7 .float impulse; // density\r
8 .string noise; // sound\r
9 .float atten;\r
10 .float volume;\r
11 .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle\r
12 .vector movedir; // trace direction\r
13 \r
14 void Draw_PointParticles()\r
15 {\r
16         float n, i, fail;\r
17         vector p;\r
18         vector sz;\r
19         vector o;\r
20         o = self.origin;\r
21         sz = self.maxs - self.mins;\r
22         n = BGMScript(self);\r
23         if(self.absolute == 2)\r
24         {\r
25                 if(n >= 0)\r
26                         n = self.just_toggled ? self.impulse : 0;\r
27                 else\r
28                         n = self.impulse * drawframetime;\r
29         }\r
30         else\r
31         {\r
32                 n *= self.impulse * drawframetime;\r
33                 if(self.just_toggled)\r
34                         if(n < 1)\r
35                                 n = 1;\r
36         }\r
37         if(n == 0)\r
38                 return;\r
39         fail = 0;\r
40         for(i = random(); i <= n && fail <= 64*n; ++i)\r
41         {\r
42                 p = o + self.mins;\r
43                 p_x += random() * sz_x;\r
44                 p_y += random() * sz_y;\r
45                 p_z += random() * sz_z;\r
46                 if(WarpZoneLib_BoxTouchesBrush(p, p, self, world))\r
47                 {\r
48                         if(self.movedir != '0 0 0')\r
49                         {\r
50                                 traceline(p, p + normalize(self.movedir) * 4096, 0, world);\r
51                                 p = trace_endpos;\r
52                                 pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count);\r
53                         }\r
54                         else\r
55                         {\r
56                                 pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count);\r
57                         }\r
58                         if(self.noise != "")\r
59                         {\r
60                                 self.origin = p;\r
61                                 sound(self, CHAN_AUTO, self.noise, VOL_BASE * self.volume, self.atten);\r
62                         }\r
63                         self.just_toggled = 0;\r
64                 }\r
65                 else if(self.absolute)\r
66                 {\r
67                         ++fail;\r
68                         --i;\r
69                 }\r
70         }\r
71         self.origin = o;\r
72 }\r
73 \r
74 void Ent_PointParticles_Remove()\r
75 {\r
76         if(self.noise)\r
77                 strunzone(self.noise);\r
78         self.noise = string_null;\r
79         if(self.bgmscript)\r
80                 strunzone(self.bgmscript);\r
81         self.bgmscript = string_null;\r
82 }\r
83 \r
84 void Ent_PointParticles()\r
85 {\r
86         float f, i;\r
87         vector v;\r
88         f = ReadByte();\r
89         if(f & 2)\r
90         {\r
91                 i = ReadCoord(); // density (<0: point, >0: volume)\r
92                 if(i && !self.impulse && self.cnt) // self.cnt check is so it only happens if the ent already existed\r
93                         self.just_toggled = 1;\r
94                 self.impulse = i;\r
95         }\r
96         if(f & 4)\r
97         {\r
98                 self.origin_x = ReadCoord();\r
99                 self.origin_y = ReadCoord();\r
100                 self.origin_z = ReadCoord();\r
101         }\r
102         if(f & 1)\r
103         {\r
104                 self.modelindex = ReadShort();\r
105                 if(f & 0x80)\r
106                 {\r
107                         if(self.modelindex)\r
108                         {\r
109                                 self.mins_x = ReadCoord();\r
110                                 self.mins_y = ReadCoord();\r
111                                 self.mins_z = ReadCoord();\r
112                                 self.maxs_x = ReadCoord();\r
113                                 self.maxs_y = ReadCoord();\r
114                                 self.maxs_z = ReadCoord();\r
115                         }\r
116                         else\r
117                         {\r
118                                 self.mins    = '0 0 0';\r
119                                 self.maxs_x = ReadCoord();\r
120                                 self.maxs_y = ReadCoord();\r
121                                 self.maxs_z = ReadCoord();\r
122                         }\r
123                 }\r
124                 else\r
125                 {\r
126                         self.mins = self.maxs = '0 0 0';\r
127                 }\r
128 \r
129                 self.cnt = ReadShort(); // effect number\r
130 \r
131                 if(f & 0x20)\r
132                 {\r
133                         self.velocity = decompressShortVector(ReadShort());\r
134                         self.movedir = decompressShortVector(ReadShort());\r
135                 }\r
136                 else\r
137                 {\r
138                         self.velocity = self.movedir = '0 0 0';\r
139                 }\r
140                 if(f & 0x40)\r
141                 {\r
142                         self.waterlevel = ReadShort() / 16.0;\r
143                         self.count = ReadByte() / 16.0;\r
144                 }\r
145                 else\r
146                 {\r
147                         self.waterlevel = 0;\r
148                         self.count = 1;\r
149                 }\r
150                 if(self.noise)\r
151                         strunzone(self.noise);\r
152                 if(self.bgmscript)\r
153                         strunzone(self.bgmscript);\r
154                 self.noise = strzone(ReadString());\r
155                 if(self.noise != "")\r
156                 {\r
157                         self.atten = ReadByte() / 64.0;\r
158                         self.volume = ReadByte() / 255.0;\r
159                 }\r
160                 self.bgmscript = strzone(ReadString());\r
161                 if(self.bgmscript != "")\r
162                 {\r
163                         self.bgmscriptattack = ReadByte() / 64.0;\r
164                         self.bgmscriptdecay = ReadByte() / 64.0;\r
165                         self.bgmscriptsustain = ReadByte() / 255.0;\r
166                         self.bgmscriptrelease = ReadByte() / 64.0;\r
167                 }\r
168                 BGMScript_InitEntity(self);\r
169         }\r
170 \r
171         if(f & 2)\r
172         {\r
173                 self.absolute = (self.impulse >= 0);\r
174                 if(!self.absolute)\r
175                 {\r
176                         v = self.maxs - self.mins;\r
177                         self.impulse *= -v_x * v_y * v_z / 262144; // relative: particles per 64^3 cube\r
178                 }\r
179         }\r
180 \r
181         if(f & 0x10)\r
182                 self.absolute = 2;\r
183 \r
184         setorigin(self, self.origin);\r
185         setsize(self, self.mins, self.maxs);\r
186         self.solid = SOLID_NOT;\r
187         self.draw = Draw_PointParticles;\r
188         self.entremove = Ent_PointParticles_Remove;\r
189 }\r
190 \r
191 .float glow_color; // palette index\r
192 void Draw_Rain()\r
193 {\r
194     te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);\r
195 }\r
196 \r
197 void Draw_Snow()\r
198 {\r
199     te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);\r
200 }\r
201 \r
202 void Ent_RainOrSnow()\r
203 {\r
204         self.impulse = ReadByte(); // Rain, Snow, or Whatever\r
205         self.origin_x = ReadCoord();\r
206         self.origin_y = ReadCoord();\r
207         self.origin_z = ReadCoord();\r
208         self.maxs_x = ReadCoord();\r
209         self.maxs_y = ReadCoord();\r
210         self.maxs_z = ReadCoord();\r
211         self.velocity = decompressShortVector(ReadShort());\r
212         self.count = ReadShort() * 10;\r
213         self.glow_color = ReadByte(); // color\r
214 \r
215         self.mins    = -0.5 * self.maxs;\r
216         self.maxs    =  0.5 * self.maxs;\r
217         self.origin  = self.origin - self.mins;\r
218 \r
219         setorigin(self, self.origin);\r
220         setsize(self, self.mins, self.maxs);\r
221         self.solid = SOLID_NOT;\r
222         if(self.impulse)\r
223                 self.draw = Draw_Rain;\r
224         else\r
225                 self.draw = Draw_Snow;\r
226 }\r
227 \r
228 entity zcurve;\r
229 void zcurveparticles(float effectnum, vector start, vector end, float end_dz, float speed, float depth)\r
230 {\r
231         // end_dz:\r
232         //   IF IT WERE A STRAIGHT LINE, it'd end end_dz above end\r
233 \r
234         vector mid;\r
235         mid = (start + end) * 0.5;\r
236 \r
237         end_dz *= 0.25;\r
238         mid_z += end_dz;\r
239 \r
240         --depth;\r
241         if(depth < 0 || normalize(mid - start) * normalize(end - start) > 0.999999)\r
242         // TODO make this a variable threshold\r
243         // currently: 0.081 degrees\r
244         // 0.99999 would be 0.256 degrees and is visible\r
245         {\r
246                 zcurve.velocity = speed * normalize(end - start);\r
247                 trailparticles(zcurve, effectnum, start, end);\r
248         }\r
249         else\r
250         {\r
251                 zcurveparticles(effectnum, start, mid, end_dz, speed, depth);\r
252                 zcurveparticles(effectnum, mid, end, end_dz, speed, depth);\r
253         }\r
254 }\r
255 \r
256 void Net_ReadZCurveParticles()\r
257 {\r
258         vector start, end;\r
259         float end_dz;\r
260         float effectnum, speed;\r
261 \r
262         if(!zcurve)\r
263         {\r
264                 zcurve = spawn();\r
265                 zcurve.classname = "zcurve";\r
266         }\r
267 \r
268         effectnum = ReadShort();\r
269 \r
270         start_x = ReadCoord();\r
271         start_y = ReadCoord();\r
272         start_z = ReadCoord();\r
273 \r
274         do\r
275         {\r
276                 end_x = ReadCoord();\r
277                 end_y = ReadCoord();\r
278                 end_z = ReadCoord();\r
279                 end_dz = ReadCoord();\r
280                 speed = ReadShort();\r
281                 zcurveparticles(effectnum, start, end, end_dz, 16 * (speed & 0x7FFF), 5); // at most 32 segments\r
282         }\r
283         while(!(speed & 0x8000));\r
284 }\r
285 \r
286 void Net_ReadNexgunBeamParticle()\r
287 {\r
288         vector shotorg, endpos;\r
289         shotorg_x = ReadCoord(); shotorg_y = ReadCoord(); shotorg_z = ReadCoord();\r
290         endpos_x = ReadCoord(); endpos_y = ReadCoord(); endpos_z = ReadCoord();\r
291         \r
292         pointparticles(particleeffectnum("nex_muzzleflash"), shotorg, normalize(endpos - shotorg) * 1000, 1);\r
293         \r
294         //draw either the old v2.3 beam or the new beam\r
295         if (cvar("cl_particles_oldnexbeam") && (getstati(STAT_ALLOW_OLDNEXBEAM) || isdemo()))\r
296                 WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), shotorg, endpos);\r
297         else\r
298                 WarpZone_TrailParticles(world, particleeffectnum("nex_beam"), shotorg, endpos);\r
299 }\r