1 /**
2 	Particles.c
3 	This file contains some default particle behavior definitions as well as helper functions.
4 
5 	@author Zapper
6 */
7 
8 
9 /*-- Helper/Effect Functions --*/
10 
CreateMuzzleFlash(int x,int y,int angle,int size)11 global func CreateMuzzleFlash(int x, int y, int angle, int size)
12 {
13 	// main muzzle flash
14 	CreateParticle("MuzzleFlash", x, y, 0, 0, 10, {Prototype = Particles_MuzzleFlash(), Size = size, Rotation = angle});
15 	// and some additional little sparks
16 	var xdir = Sin(angle, size * 2);
17 	var ydir = -Cos(angle, size * 2);
18 	CreateParticle("StarFlash", x, y, PV_Random(xdir - size, xdir + size), PV_Random(ydir - size, ydir + size), PV_Random(20, 60), Particles_Glimmer(), size);
19 }
20 
21 // documented in /docs/sdk/script/fn
Smoke(int x,int y,int level,int color,bool heavy)22 global func Smoke(int x, int y, int level, int color, bool heavy)
23 {
24 	level = level ?? 10;
25 	var particles = Particles_Smoke(heavy);
26 	if (color)
27 	{
28 		particles.Alpha = PV_Linear((color >> 24) & 0xff, 0);
29 		particles.R = (color >> 16) & 0xff;
30 		particles.G = (color >>  8) & 0xff;
31 		particles.B = (color >>  0) & 0xff;
32 	}
33 	particles.Size = PV_Linear(PV_Random(level/2, level), PV_Random(2 * level, 3 * level));
34 	CreateParticle("Smoke", x, y, PV_Random(-level/3, level/3), PV_Random(-level/2, -level/3), PV_Random(level * 2, level * 10), particles, BoundBy(level/5, 3, 20));
35 }
36 
37 
38 /*-- Particle Definitions --*/
39 
Particles_Dust()40 global func Particles_Dust()
41 {
42 	return
43 	{
44 		CollisionVertex = 500,
45 		OnCollision = PC_Stop(),
46 		ForceX = PV_Wind(20),
47 		ForceY = PV_Gravity(25),
48 		Alpha = PV_KeyFrames(0, 0, 0, 250, 60, 1000, 0),
49 		Rotation = PV_Random(0, 360),
50 		Size = PV_KeyFrames(0, 0, 5, 100, 12, 1000, 7)
51 	};
52 }
53 
Particles_Cloud()54 global func Particles_Cloud()
55 {
56 	return
57 	{
58 		Size = 200,
59 		Attach = ATTACH_MoveRelative,
60 		Phase = PV_Random(0, 15)
61 	};
62 }
63 
Particles_Smoke(bool heavy)64 global func Particles_Smoke(bool heavy)
65 {
66 	return
67 	{
68 		CollisionVertex = 500,
69 		OnCollision = PC_Stop(),
70 		ForceY = PV_Gravity(-100 + heavy*90),
71 		ForceX = PV_Wind(200 - heavy*180),
72 		DampingX = 900, DampingY = 900,
73 		Alpha = PV_Linear(255, 0),
74 		R = 100, G = 100, B = 100,
75 		Size = PV_Linear(PV_Random(4, 10), PV_Random(20, 30)),
76 		Phase = PV_Random(0, 15)
77 	};
78 }
79 
Particles_Fire()80 global func Particles_Fire()
81 {
82 	return
83 	{
84 		CollisionVertex = 0,
85 		OnCollision = PC_Die(),
86 		Phase = PV_Random(0, 3, 10),
87 		ForceY = PV_Gravity(-100),
88 		DampingY = 950,
89 		Alpha = PV_KeyFrames(0, 0, 255, 500, 255, 1000, 0),
90 		BlitMode = GFX_BLIT_Additive,
91 		Size = PV_KeyFrames(0, 0, PV_Random(5, 10), 500, 5, 1000, 0),
92 		Attach = ATTACH_Front,
93 		Rotation = PV_Direction()
94 	};
95 }
96 
Particles_FireTrail()97 global func Particles_FireTrail()
98 {
99 	return
100 	{
101 		Prototype = Particles_Fire(),
102 		ForceY = 0,
103 		Attach = nil,
104 	};
105 }
106 
Particles_Flash(int size)107 global func Particles_Flash(int size)
108 {
109 	return
110 	{
111 		BlitMode = GFX_BLIT_Additive,
112 		Alpha = PV_KeyFrames(0, 0, 128, 250, 64, 1000, 0),
113 		Size = PV_KeyFrames(0, 0, 0, 100, size ?? 160, 1000, 0),
114 		R = 255, G = 255, B = 64
115 	};
116 }
117 
Particles_Magic()118 global func Particles_Magic()
119 {
120 	return
121 	{
122 		BlitMode = GFX_BLIT_Additive,
123 		Alpha = PV_Linear(128, 0),
124 		Size = PV_Linear(0, PV_Random(5, 15)),
125 		CollisionVertex = 500,
126 		OnCollision = PC_Die(),
127 		Rotation = PV_Random(0, 360)
128 	};
129 }
130 
Particles_MagicRing()131 global func Particles_MagicRing()
132 {
133 	return
134 	{
135 		BlitMode = GFX_BLIT_Additive,
136 		Alpha = PV_Linear(100, 0),
137 		Size = PV_KeyFrames(1, 0, 0, 500, 20, 1000, 0),
138 		Attach = ATTACH_Front | ATTACH_MoveRelative
139 	};
140 }
141 
Particles_Spark()142 global func Particles_Spark()
143 {
144 	return
145 	{
146 		BlitMode = GFX_BLIT_Additive,
147 		Size = PV_Linear(PV_Random(5, 15), 0),
148 		CollisionVertex = 500,
149 		OnCollision = PC_Bounce(500),
150 		Rotation = PV_Direction(),
151 		ForceY = PV_Gravity(20)
152 	};
153 }
154 
155 // documented in /docs/sdk/script/fn
Particles_Colored(prototype,color,color2)156 global func Particles_Colored(prototype, color, color2)
157 {
158 	// Colors the given particle. If color2 is given, colors in a random fade between color and color2
159 	if (GetType(color2))
160 	{
161 		return {
162 			Prototype = prototype,
163 			R = PV_Random((color >> 16) & 0xff, (color2 >> 16) & 0xff),
164 			G = PV_Random((color >>  8) & 0xff, (color2 >>  8) & 0xff),
165 			B = PV_Random((color >>  0) & 0xff, (color2 >>  0) & 0xff),
166 		};
167 	}
168 	else
169 		return {
170 			Prototype = prototype,
171 			R = (color >> 16) & 0xff,
172 			G = (color >>  8) & 0xff,
173 			B = (color >>  0) & 0xff
174 		};
175 }
176 
Particles_SparkFire()177 global func Particles_SparkFire()
178 {
179 	return
180 	{
181 		Prototype = Particles_Spark(),
182 		R = 255, G = 200, B = 10
183 	};
184 }
185 
Particles_SmokeTrail()186 global func Particles_SmokeTrail()
187 {
188 	return
189 	{
190 		Prototype = Particles_Smoke(),
191 		ForceY = PV_Gravity(-10),
192 		ForceX = PV_Wind(20),
193 		DampingX = 950, DampingY = 950,
194 		Alpha = PV_Linear(128, 0),
195 		Size = PV_KeyFrames(0, 0, 0, 200, PV_Random(3, 10), 1000, PV_Random(8, 11))
196 	};
197 }
198 
Particles_Material(int color)199 global func Particles_Material(int color)
200 {
201 	return
202 	{
203 		Stretch = PV_Speed(2000),
204 		CollisionVertex = 1000,
205 		OnCollision = PC_Die(),
206 		Size = 1,
207 		Rotation = PV_Direction(),
208 		ForceY = PV_Gravity(100),
209 		R = (color >> 16) & 0xff,
210 		G = (color >>  8) & 0xff,
211 		B = (color >>  0) & 0xff
212 	};
213 }
214 
Particles_Trajectory()215 global func Particles_Trajectory()
216 {
217 	return
218 	{
219 		BlitMode = GFX_BLIT_Additive,
220 		Attach = ATTACH_Front | ATTACH_MoveRelative
221 	};
222 }
223 
Particles_WoodChip()224 global func Particles_WoodChip()
225 {
226 	return
227 	{
228 		Size = PV_Random(1, 3),
229 		Phase = PV_Linear(0, 3),
230 		Alpha = PV_KeyFrames(0, 0, 255, 900, 255, 1000, 0),
231 		CollisionVertex = 500,
232 		OnCollision = PC_Stop(),
233 		ForceX = PV_Wind(50),
234 		ForceY = PV_Gravity(100),
235 		DampingX = 975, DampingY = 975,
236 		Rotation = PV_Direction(PV_Random(750, 1250)),
237 		Attach = ATTACH_Front
238 	};
239 }
240 
Particles_Straw()241 global func Particles_Straw()
242 {
243 	return
244 	{
245 		Prototype = Particles_WoodChip(),
246 		Phase = PV_Random(0, 3),
247 		Size = PV_Random(3, 5),
248 		Attach = nil
249 	};
250 }
251 
Particles_Leaf(int color)252 global func Particles_Leaf(int color)
253 {
254 	return
255 	{
256 		Size = PV_Random(4, 6),
257 		Phase = PV_Random(0, 2),
258 		Rotation = PV_Random(0, 360),
259 		R = (color >> 16) & 0xff,
260 		G = (color >>  8) & 0xff,
261 		B = (color >>  0) & 0xff,
262 		Alpha = PV_KeyFrames(0, 0, 255, 900, 255, 1000, 0),
263 		CollisionVertex = 800,
264 		OnCollision = PC_Die(),
265 		ForceX = PV_Wind(50),
266 		ForceY = PV_Gravity(100),
267 		DampingX = 975, DampingY = 975,
268 		Rotation = PV_Direction(PV_Random(750, 1250)),
269 		Attach = ATTACH_Front
270 	};
271 }
272 
Particles_CottonBalloon()273 global func Particles_CottonBalloon()
274 {
275 	return
276 	{
277 		Prototype = Particles_WoodChip(),
278 		Phase = PV_Random(0, 3),
279 		Size = PV_Random(2, 4),
280 		ForceY = PV_Gravity(10),
281 		DampingX = 900, DampingY = 900,
282 		Attach = nil
283 	};
284 }
285 
Particles_Air()286 global func Particles_Air()
287 {
288 	return
289 	{
290 		Stretch = PV_Speed(500, 1000),
291 		Alpha = PV_Linear(255, 0),
292 		Phase = PV_Random(0, 3),
293 		DampingX = 990, DampingY = 990,
294 		ForceX = PV_Random(-5, 5, 30),
295 		ForceY = PV_Gravity(10, PV_Random(-5, 5)),
296 		Size = PV_KeyFrames(0, 0, 0, 100, PV_Random(20, 30), 1000, 0),
297 		Rotation = PV_Direction(),
298 		CollisionVertex = 1000,
299 		OnCollision = PC_Bounce(500)
300 	};
301 }
302 
Particles_Thrust(int size)303 global func Particles_Thrust(int size)
304 {
305 	size = size ?? 10;
306 	return
307 	{
308 		Size = PV_KeyFrames(0, 0, 0, 50, size, 1000, size * 2),
309 		Alpha = PV_Linear(255, 0),
310 		R = PV_KeyFrames(0, 0, 255, 500, 100, 1000, 50),
311 		G = PV_KeyFrames(0, 0, 255, 500, 100, 1000, 50),
312 		B = PV_KeyFrames(0, 0, 255, 500, 100, 1000, 50),
313 		Phase = PV_Random(0, 3, 10),
314 		Rotation = PV_Random(0, 360),
315 		DampingX = 950, DampingY = 950,
316 		ForceY = PV_KeyFrames(0, 0, 0, 500, 0, 1000, PV_Gravity(20)),
317 		ForceX = PV_KeyFrames(0, 0, 0, 500, 0, 1000, PV_Wind(50)),
318 		CollisionVertex = 750
319 	};
320 }
321 
Particles_MuzzleFlash()322 global func Particles_MuzzleFlash()
323 {
324 	return
325 	{
326 		Attach = ATTACH_Front | ATTACH_MoveRelative,
327 		Size = 20,
328 		Phase = PV_Linear(0, 5),
329 		BlitMode = GFX_BLIT_Additive
330 	};
331 }
332 
Particles_Glimmer()333 global func Particles_Glimmer()
334 {
335 	return
336 	{
337 		Size = PV_Linear(2, 0),
338 	    ForceY = GetGravity(),
339 		DampingY = PV_Linear(1000,700),
340 		DampingX = PV_Linear(1000,700),
341 		Stretch = PV_Speed(1000, 500),
342 		Rotation = PV_Direction(),
343 		OnCollision = PC_Die(),
344 		CollisionVertex = 500,
345 	    R = 255,
346 	    G = PV_Linear(128,32),
347 	    B = PV_Random(0, 128, 2),
348 	    Alpha = PV_Random(255,0,3),
349 		BlitMode = GFX_BLIT_Additive,
350 	};
351 }
352 
Particles_ElectroSpark1()353 global func Particles_ElectroSpark1()
354 {
355 	return
356 	{
357 		Size = PV_Random(5, 9),
358 		Phase = PV_Linear(0, 5),
359 		BlitMode = GFX_BLIT_Additive,
360 		CollisionVertex = 750,
361 		OnCollision = PC_Die(),
362 		Rotation = PV_Direction()
363 	};
364 }
365 
Particles_ElectroSpark2()366 global func Particles_ElectroSpark2()
367 {
368 	return
369 	{
370 		Prototype = Particles_ElectroSpark1(),
371 		Phase = PV_Linear(6, 11),
372 	};
373 }
374 
375 
376 /*-- Weather Particles --*/
377 
Particles_Rain(int color)378 global func Particles_Rain(int color)
379 {
380 	return
381 	{
382 		CollisionVertex = 0,
383 		OnCollision = PC_Die(),
384 		ForceY = PV_Gravity(1000),
385 		Size = PV_Random(10, 30),
386 		R = GetRGBaValue(color, 1),
387 		G = GetRGBaValue(color, 2),
388 		B = GetRGBaValue(color, 3),
389 		Rotation = PV_Direction(),
390 		CollisionDensity = 25,
391 		Stretch = 3000,
392 	};
393 }
394 
Particles_Snow(int color)395 global func Particles_Snow(int color)
396 {
397 	return
398 	{
399 		Phase = PV_Random(0, 16),
400 		CollisionVertex = 0,
401 		OnCollision = PC_Die(),
402 		DampingY = 1000,//PV_Cos(PV_Linear(0,1800),5,990),
403 		ForceY = 0,//GetGravity()/100,//PV_Gravity(100),
404 		// TODO: PV_Random() here?
405 		ForceX = PV_Sin(PV_Step(PV_Random(5, 10), PV_Random(0, 180)), PV_Random(5, 8), 0),
406 		Size = PV_Random(0, 3),
407 		R = GetRGBaValue(color, 1),
408 		G = GetRGBaValue(color, 2),
409 		B = GetRGBaValue(color, 3),
410 		Rotation = PV_Random(360),
411 		CollisionDensity = 25,
412 		Stretch = 1000,
413 	};
414 }
415 
Particles_RainSmall(int color)416 global func Particles_RainSmall(int color)
417 {
418 	return
419 	{
420 		CollisionVertex = 0,
421 		OnCollision = PC_Die(),
422 		ForceY = PV_Gravity(1000),
423 		Size = 1,
424 		R = GetRGBaValue(color, 1),
425 		G = GetRGBaValue(color, 2),
426 		B = GetRGBaValue(color, 3),
427 		Alpha = 200,
428 		Rotation = PV_Direction(),
429 		CollisionDensity = 25,
430 		Stretch = PV_Speed(4000),
431 	};
432 }
433 
Particles_Splash(int color)434 global func Particles_Splash(int color)
435 {
436 	return
437 	{
438 		Phase = PV_Linear(0, 4),
439 		Alpha = PV_KeyFrames(0, 0, 255, 500, 255, 1000, 0),
440 		Size = PV_Random(5, 10),
441 		R = GetRGBaValue(color, 1),
442 		G = GetRGBaValue(color, 2),
443 		B = GetRGBaValue(color, 3),
444 		Rotation = PV_Random(-5,5),
445 		Stretch = PV_Random(500, 1000),
446 	};
447 }
448 
Particles_SplashWater(int color)449 global func Particles_SplashWater(int color)
450 {
451 	return
452 	{
453 		Phase = PV_Linear(0, 13),
454 		Alpha = PV_KeyFrames(0, 0, 255, 500, 255, 1000, 0),
455 		Size = PV_Random(2, 5),
456 		R = GetRGBaValue(color, 1),
457 		G = GetRGBaValue(color, 2),
458 		B = GetRGBaValue(color, 3),
459 		Rotation = PV_Random(-5,5),
460 		Stretch = 3000,
461 		Attach = ATTACH_Back,
462 	};
463 }
464 
Particles_Hail(int color)465 global func Particles_Hail(int color)
466 {
467 	return
468 	{
469 		CollisionVertex = 0,
470 		ForceY = PV_Gravity(1000),
471 		OnCollision = PC_Stop(),
472 		Size = 2,
473 		Alpha = PV_KeyFrames(255, 0, 255, 500, 255, 1000, 0),
474 		R = GetRGBaValue(color, 1),
475 		G = GetRGBaValue(color, 2),
476 		B = GetRGBaValue(color, 3),
477 		Rotation = PV_Random(360),
478 	};
479 }
480