1 .float dphitcontentsmask;
\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
11 .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
\r
12 .vector movedir; // trace direction
\r
14 void Draw_PointParticles()
\r
21 sz = self.maxs - self.mins;
\r
22 n = BGMScript(self);
\r
23 if(self.absolute == 2)
\r
26 n = self.just_toggled ? self.impulse : 0;
\r
28 n = self.impulse * drawframetime;
\r
32 n *= self.impulse * drawframetime;
\r
33 if(self.just_toggled)
\r
40 for(i = random(); i <= n && fail <= 64*n; ++i)
\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
48 if(self.movedir != '0 0 0')
\r
50 traceline(p, p + normalize(self.movedir) * 4096, 0, world);
\r
52 pointparticles(self.cnt, p, trace_plane_normal * vlen(self.movedir) + self.velocity + randomvec() * self.waterlevel, self.count);
\r
56 pointparticles(self.cnt, p, self.velocity + randomvec() * self.waterlevel, self.count);
\r
58 if(self.noise != "")
\r
61 sound(self, CHAN_AUTO, self.noise, VOL_BASE * self.volume, self.atten);
\r
63 self.just_toggled = 0;
\r
65 else if(self.absolute)
\r
74 void Ent_PointParticles_Remove()
\r
77 strunzone(self.noise);
\r
78 self.noise = string_null;
\r
80 strunzone(self.bgmscript);
\r
81 self.bgmscript = string_null;
\r
84 void Ent_PointParticles()
\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
98 self.origin_x = ReadCoord();
\r
99 self.origin_y = ReadCoord();
\r
100 self.origin_z = ReadCoord();
\r
104 self.modelindex = ReadShort();
\r
107 if(self.modelindex)
\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
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
126 self.mins = self.maxs = '0 0 0';
\r
129 self.cnt = ReadShort(); // effect number
\r
133 self.velocity = decompressShortVector(ReadShort());
\r
134 self.movedir = decompressShortVector(ReadShort());
\r
138 self.velocity = self.movedir = '0 0 0';
\r
142 self.waterlevel = ReadShort() / 16.0;
\r
143 self.count = ReadByte() / 16.0;
\r
147 self.waterlevel = 0;
\r
151 strunzone(self.noise);
\r
153 strunzone(self.bgmscript);
\r
154 self.noise = strzone(ReadString());
\r
155 if(self.noise != "")
\r
157 self.atten = ReadByte() / 64.0;
\r
158 self.volume = ReadByte() / 255.0;
\r
160 self.bgmscript = strzone(ReadString());
\r
161 if(self.bgmscript != "")
\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
168 BGMScript_InitEntity(self);
\r
173 self.absolute = (self.impulse >= 0);
\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
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
191 .float glow_color; // palette index
\r
194 te_particlerain(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);
\r
199 te_particlesnow(self.origin + self.mins, self.origin + self.maxs, self.velocity, self.count * drawframetime, self.glow_color);
\r
202 void Ent_RainOrSnow()
\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
215 self.mins = -0.5 * self.maxs;
\r
216 self.maxs = 0.5 * self.maxs;
\r
217 self.origin = self.origin - self.mins;
\r
219 setorigin(self, self.origin);
\r
220 setsize(self, self.mins, self.maxs);
\r
221 self.solid = SOLID_NOT;
\r
223 self.draw = Draw_Rain;
\r
225 self.draw = Draw_Snow;
\r
229 void zcurveparticles(float effectnum, vector start, vector end, float end_dz, float speed, float depth)
\r
232 // IF IT WERE A STRAIGHT LINE, it'd end end_dz above end
\r
235 mid = (start + end) * 0.5;
\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
246 zcurve.velocity = speed * normalize(end - start);
\r
247 trailparticles(zcurve, effectnum, start, end);
\r
251 zcurveparticles(effectnum, start, mid, end_dz, speed, depth);
\r
252 zcurveparticles(effectnum, mid, end, end_dz, speed, depth);
\r
256 void Net_ReadZCurveParticles()
\r
260 float effectnum, speed;
\r
265 zcurve.classname = "zcurve";
\r
268 effectnum = ReadShort();
\r
270 start_x = ReadCoord();
\r
271 start_y = ReadCoord();
\r
272 start_z = ReadCoord();
\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
283 while(!(speed & 0x8000));
\r