1 #include <stdlib.h>
2 #include <math.h>
3 #ifndef WINDOWS
4  #include <locale.h>
5 #endif
6 #include <errno.h>
7 #include "particles.h"
8 #include "asc.h"
9 #include "draw_scene.h"
10 #include "elconfig.h"
11 #include "errors.h"
12 #ifdef OPENGL_TRACE
13 #include "gl_init.h"
14 #endif
15 #include "pathfinder.h"
16 #include "string.h"
17 #include "sound.h"
18 #include "textures.h"
19 #include "tiles.h"
20 #include "translate.h"
21 #include "vmath.h"
22 #ifdef CLUSTER_INSIDES
23 #include "cluster.h"
24 #endif
25 #include "eye_candy_wrapper.h"
26 #include "translate.h"
27 #include "io/elpathwrapper.h"
28 #include "io/elfilewrapper.h"
29 #ifdef MAP_EDITOR
30 #include "map_editor/3d_objects.h"
31 #include "map_editor/lights.h"
32 #else
33 #include "3d_objects.h"
34 #include "lights.h"
35 #endif
36 #include "image_loading.h"
37 
38 #ifdef NEW_SOUND
39 static int real_add_particle_sys (const char *file_name, float x_pos, float y_pos, float z_pos, unsigned int dynamic);
40 #endif // NEW_SOUND
41 
42 #define TELEPORTER_PARTICLE_SYS 0
43 #define TELEPORT_PARTICLE_SYS 1
44 #define BAG_PARTICLE_SYS 2
45 #define BURST_PARTICLE_SYS 3
46 #define FIRE_PARTICLE_SYS 4
47 #define FOUNTAIN_PARTICLE_SYS 5
48 
49 #define PARTICLE_RANDOM(min,max) (min+(max-min)*(rand()/(float)RAND_MAX))
50 #define PARTICLE_RANDOM2(min,max) (min+0.5*(max-min)+0.5*(max-min)/(float)((rand()%200)-100+0.5))
51 
52 #define PART_SYS_VISIBLE_DIST_SQ 20*20
53 
54 #define MAX_PARTICLE_TEXTURES 16 // The maximum number of textures used for particle systems
55 
56 #ifdef ELC
57 int use_point_particles = 1;
58 #else
59 int use_point_particles = 0;
60 #endif
61 int particles_percentage=100;
62 int enable_blood = 0;
63 SDL_mutex *particles_list_mutex;	//used for locking between the timer and main threads
64 static int particle_textures[MAX_PARTICLE_TEXTURES];
65 particle_sys *particles_list[MAX_PARTICLE_SYSTEMS];
66 
67 /******************************************************
68  *           PARTICLE SYSTEM DEFINITIONS              *
69  ******************************************************/
70 #define MAX_PARTICLE_DEFS 500
71 particle_sys_def *defs_list[MAX_PARTICLE_DEFS];
72 
73 void destroy_all_particle_defs();
74 
part_strcmp(char * s1,char * s2)75 int part_strcmp(char * s1, char *s2)
76 {
77 	while(*s1 && *s2)
78 		{
79 			if(*s1!=*s2 && (*s1!='/' && *s1!='\\' && *s2!='/' && *s2!='\\' )) return 1;
80 			s1++;s2++;
81 		}
82 	return *s1!=*s2;
83 }
84 
85 // Grum: perhaps the addition of a sound definition to the files would warrant
86 // a version number update (from 2 to 3), but it'll still work with v. 2 system
87 // (without sound, of course), so I'll leave it
88 #define PARTICLE_DEF_VERSION 2
89 
load_particle_def(const char * filename)90 particle_sys_def *load_particle_def(const char *filename)
91 {
92 	int version=0,i;
93 	char cleanpath[128];
94 	int fscanf_error = 0;
95 	FILE *f=NULL;
96 	particle_sys_def *def=NULL;
97 
98 	clean_file_name(cleanpath, filename, sizeof(cleanpath));
99 
100 	//Check if it's already loaded
101 	for(i=0;i<MAX_PARTICLE_DEFS;i++)
102 		if(defs_list[i] && !part_strcmp(cleanpath,defs_list[i]->file_name))
103 			return defs_list[i];
104 
105 	//Check if we have a free slot for it
106 	for(i=0;i<MAX_PARTICLE_DEFS;i++)
107 		if(!defs_list[i])
108 			{
109 				defs_list[i]=(particle_sys_def *)calloc(1,sizeof(particle_sys_def));
110 				def=defs_list[i];
111 				break;
112 			}
113 	if(!def)return NULL;
114 
115 	f=open_file_data(cleanpath,"r");
116 	if(f == NULL){
117 		LOG_ERROR("%s: %s \"%s\": %s\n", reg_error_str, cant_open_file, cleanpath, strerror(errno));
118 		free(def);
119 		defs_list[i]=NULL;
120 		return NULL;
121 	}
122 
123 	// initialize defaults
124 	def->sound_nr = -1;
125 
126 	if (fscanf(f,"%i\n",&version) != 1) fscanf_error = 1;
127 
128 	if(version!=PARTICLE_DEF_VERSION)
129 		{
130 			LOG_ERROR(particles_filever_wrong,filename,version,PARTICLE_DEF_VERSION);
131 			fclose(f);
132 			return NULL;
133 		}
134 #ifndef WINDOWS
135 	setlocale(LC_NUMERIC,"en_US");
136 #endif
137 	// System info
138 	safe_snprintf(def->file_name, sizeof(def->file_name), "%s", filename);
139 	if (!fscanf_error && fscanf(f,"%i\n",&def->part_sys_type) != 1) fscanf_error = 2;
140 	if (!fscanf_error && fscanf(f,"%x,%x\n",&def->sblend,&def->dblend) != 2) fscanf_error = 3;
141 	if (!fscanf_error && fscanf(f,"%i\n",&def->total_particle_no) != 1) fscanf_error = 4;
142 	if (!fscanf_error && fscanf(f,"%i\n",&def->ttl) != 1) fscanf_error = 5;
143 	if (!fscanf_error && fscanf(f,"%i\n",&def->part_texture) != 1) fscanf_error = 6;
144 	if (!fscanf_error && fscanf(f,"%f\n",&def->part_size) != 1) fscanf_error = 7;
145 	if (!fscanf_error && fscanf(f,"%i\n",&def->random_func) != 1) fscanf_error = 8;
146 	// Particle creation info
147 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->minx,&def->miny,&def->minz) != 3) fscanf_error = 9;
148 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->maxx,&def->maxy,&def->maxz) != 3) fscanf_error = 10;
149 	if (!fscanf_error && fscanf(f,"%f\n",&def->constrain_rad_sq) != 1) fscanf_error = 11;
150 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->vel_minx,&def->vel_miny,&def->vel_minz) != 3) fscanf_error = 12;
151 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->vel_maxx,&def->vel_maxy,&def->vel_maxz) != 3) fscanf_error = 13;
152 	if (!fscanf_error && fscanf(f,"%f,%f,%f,%f\n",&def->minr,&def->ming,&def->minb,&def->mina) != 4) fscanf_error = 14;
153 	if (!fscanf_error && fscanf(f,"%f,%f,%f,%f\n",&def->maxr,&def->maxg,&def->maxb,&def->maxa) != 4) fscanf_error = 15;
154 	// Particle update info
155 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->acc_minx,&def->acc_miny,&def->acc_minz) != 3) fscanf_error = 16;
156 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->acc_maxx,&def->acc_maxy,&def->acc_maxz) != 3) fscanf_error = 17;
157 	if (!fscanf_error && fscanf(f,"%f,%f,%f,%f\n",
158 	       &def->mindr,&def->mindg,&def->mindb,&def->minda) != 4) fscanf_error = 18;
159 	if (!fscanf_error && fscanf(f,"%f,%f,%f,%f\n",
160 	       &def->maxdr,&def->maxdg,&def->maxdb,&def->maxda) != 4) fscanf_error = 19;
161 	if (!fscanf_error && fscanf(f,"%i\n",&def->use_light) != 1) fscanf_error = 20;
162 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->lightx,&def->lighty,&def->lightz) != 3) fscanf_error = 21;
163 	if (!fscanf_error && fscanf(f,"%f,%f,%f\n",&def->lightr,&def->lightg,&def->lightb) != 3) fscanf_error = 22;
164 #ifdef NEW_SOUND
165 	if (!fscanf_error && fscanf (f, "%d\n", &def->sound_nr) != 3) fscanf_error = 23;
166 #endif	//NEW_SOUND
167 
168 	// Most particale files lack the last few lines and so always fail the test - only report really bad ones.
169 	if (fscanf_error != 0 && fscanf_error < 20)
170 		LOG_ERROR("%s(): fscanf error file=[%s] line %d\n", __FUNCTION__, filename, fscanf_error);
171 #if DEBUG
172 	if (fscanf_error != 0)
173 		printf("%s(): fscanf error file=[%s] line %d\n", __FUNCTION__, filename, fscanf_error);
174 #endif
175 
176 	if(def->total_particle_no>MAX_PARTICLES)
177 		{
178 		  LOG_ERROR(particle_system_overrun,filename,def->total_particle_no,MAX_PARTICLES);
179 		  def->total_particle_no=MAX_PARTICLES;
180 		}
181 	if(def->constrain_rad_sq>0.0)
182 		{
183 			float rad=sqrt(def->constrain_rad_sq);
184 			int fixed=def->minx>rad || def->maxx<-rad || def->miny>rad || def->maxy<-rad;
185 			if(def->minx>rad)def->minx=rad-0.1;
186 			if(def->maxx<-rad)def->maxx=-rad+0.1;
187 			if(def->miny>rad)def->miny=rad-0.1;
188 			if(def->maxy<-rad)def->maxy=-rad+0.1;
189 			if(def->minx*def->maxx>0.0 || def->miny*def->maxy>0.0)
190 				{
191 					float dist=def->minx*def->minx+def->miny*def->miny;
192 					if(dist>def->constrain_rad_sq)
193 						{
194 							def->minx*=sqrt(def->constrain_rad_sq/dist)-0.1;
195 							def->miny*=sqrt(def->constrain_rad_sq/dist)-0.1;
196 							fixed=1;
197 						}
198 					dist=def->minx*def->minx+def->maxy*def->maxy;
199 					if(dist>def->constrain_rad_sq)
200 						{
201 							def->minx*=sqrt(def->constrain_rad_sq/dist)-0.1;
202 							def->maxy*=sqrt(def->constrain_rad_sq/dist)-0.1;
203 							fixed=1;
204 						}
205 					dist=def->maxx*def->maxx+def->maxy*def->maxy;
206 					if(dist>def->constrain_rad_sq)
207 						{
208 							def->maxx*=sqrt(def->constrain_rad_sq/dist)-0.1;
209 							def->maxy*=sqrt(def->constrain_rad_sq/dist)-0.1;
210 							fixed=1;
211 						}
212 					dist=def->maxx*def->maxx+def->miny*def->miny;
213 					if(dist>def->constrain_rad_sq)
214 						{
215 							def->maxx*=sqrt(def->constrain_rad_sq/dist)-0.1;
216 							def->miny*=sqrt(def->constrain_rad_sq/dist)-0.1;
217 							fixed=1;
218 						}
219 				}
220 			if(fixed)
221 				{
222 					LOG_ERROR(particle_strange_pos,filename);
223 				}
224 
225 		}
226 
227 	fclose(f);
228 
229 	return def;
230 }
231 
calc_particle_random_min_max(float f1,float f2,float * v_min,float * v_max)232 static __inline__ void calc_particle_random_min_max(float f1, float f2, float* v_min, float* v_max)
233 {
234 	if (f1 < f2)
235 	{
236 		*v_min = f1;
237 		*v_max = f2;
238 	}
239 	else
240 	{
241 		*v_min = f2;
242 		*v_max = f1;
243 	}
244 }
245 
calc_particle_random2_min_max(float f1,float f2,float * v_min,float * v_max)246 static __inline__ void calc_particle_random2_min_max(float f1, float f2, float* v_min, float* v_max)
247 {
248 	*v_min = (f1+f2)*0.5f-fabsf(f2-f1);
249 	*v_max = (f1+f2)*0.5f+fabsf(f2-f1);
250 }
251 
calc_bounding_box_for_particle_sys(AABBOX * bbox,particle_sys * system_id)252 void calc_bounding_box_for_particle_sys(AABBOX* bbox, particle_sys *system_id)
253 {
254 	unsigned int count;
255 	float p_max, p_min, p_step, sq;
256 	VECTOR3 pv_min, pv_max, pv_v_min, pv_v_max, pv_acc_min, pv_acc_max;
257 
258 	sq = sqrt(system_id->def->constrain_rad_sq);
259 	if (system_id->def->random_func == 0)
260 	{
261 		calc_particle_random_min_max(system_id->def->vel_minx, system_id->def->vel_maxx, &p_min, &p_max);
262 		pv_v_min[X] = p_min;
263 		pv_v_max[X] = p_max;
264 		calc_particle_random_min_max(system_id->def->vel_miny, system_id->def->vel_maxy, &p_min, &p_max);
265 		pv_v_min[Y] = p_min;
266 		pv_v_max[Y] = p_max;
267 		calc_particle_random_min_max(system_id->def->vel_minz, system_id->def->vel_maxz, &p_min, &p_max);
268 		pv_v_min[Z] = p_min;
269 		pv_v_max[Z] = p_max;
270 
271 		if (system_id->def->constrain_rad_sq > 0.0f)
272 		{
273 			pv_min[X] = -sq;
274 			pv_min[Y] = -sq;
275 			pv_max[X] = sq;
276 			pv_max[Y] = sq;
277 		}
278 		else
279 		{
280 			calc_particle_random_min_max(system_id->def->minx, system_id->def->maxx, &p_min, &p_max);
281 			pv_min[X] = p_min;
282 			pv_max[X] = p_max;
283 			calc_particle_random_min_max(system_id->def->miny, system_id->def->maxy, &p_min, &p_max);
284 			pv_min[Y] = p_min;
285 			pv_max[Y] = p_max;
286 		}
287 		calc_particle_random_min_max(system_id->def->minz, system_id->def->maxz, &p_min, &p_max);
288 		pv_min[Z] = p_min;
289 		pv_max[Z] = p_max;
290 	}
291 	else
292 	{
293 		calc_particle_random2_min_max(system_id->def->vel_minx, system_id->def->vel_maxx, &p_min, &p_max);
294 		pv_v_min[X] = p_min;
295 		pv_v_max[X] = p_max;
296 		calc_particle_random2_min_max(system_id->def->vel_miny, system_id->def->vel_maxy, &p_min, &p_max);
297 		pv_v_min[Y] = p_min;
298 		pv_v_max[Y] = p_max;
299 		calc_particle_random2_min_max(system_id->def->vel_minz, system_id->def->vel_maxz, &p_min, &p_max);
300 		pv_v_min[Z] = p_min;
301 		pv_v_max[Z] = p_max;
302 
303 		if (system_id->def->constrain_rad_sq > 0.0f)
304 		{
305 			pv_min[X] = -sq;
306 			pv_min[Y] = -sq;
307 			pv_max[X] = sq;
308 			pv_max[Y] = sq;
309 		}
310 		else
311 		{
312 			calc_particle_random2_min_max(system_id->def->minx, system_id->def->maxx, &p_min, &p_max);
313 			pv_min[X] = p_min;
314 			pv_max[X] = p_max;
315 			calc_particle_random2_min_max(system_id->def->miny, system_id->def->maxy, &p_min, &p_max);
316 			pv_min[Y] = p_min;
317 			pv_max[Y] = p_max;
318 		}
319 		calc_particle_random2_min_max(system_id->def->minz, system_id->def->maxz, &p_min, &p_max);
320 		pv_min[Z] = p_min;
321 		pv_max[Z] = p_max;
322 	}
323 
324 	switch (system_id->def->part_sys_type)
325 	{
326 		case(TELEPORTER_PARTICLE_SYS):
327                 case(TELEPORT_PARTICLE_SYS):
328 			calc_particle_random2_min_max(system_id->def->acc_minx, system_id->def->acc_maxx, &p_min, &p_max);
329 			pv_acc_min[X] = p_min;
330 			pv_acc_max[X] = p_max;
331 			calc_particle_random2_min_max(system_id->def->acc_miny, system_id->def->acc_maxy, &p_min, &p_max);
332 			pv_acc_min[Y] = p_min;
333 			pv_acc_max[Y] = p_max;
334 			calc_particle_random2_min_max(system_id->def->acc_minz, system_id->def->acc_maxz, &p_min, &p_max);
335 			pv_acc_min[Z] = p_min;
336 			pv_acc_max[Z] = p_max;
337 			p_step = pv_acc_min[Z]+pv_v_min[Z];
338 			count = ceil(2.0f/p_step);
339 			bbox->bbmin[X] = min2f(pv_min[X], pv_min[X]+count*(pv_v_min[X]+pv_acc_min[X]));
340 			bbox->bbmin[Y] = min2f(pv_min[Y], pv_min[Y]+count*(pv_v_min[Y]+pv_acc_max[X]));
341 			bbox->bbmin[Z] = min2f(pv_min[Z], pv_min[Z]+count*(pv_v_min[Z]+pv_acc_min[Y]));
342 			bbox->bbmax[X] = max2f(pv_max[X], pv_max[X]+count*(pv_v_max[X]+pv_acc_max[Y]));
343 			bbox->bbmax[Y] = max2f(pv_max[Y], pv_max[Y]+count*(pv_v_max[Y]+pv_acc_min[Z]));
344 			bbox->bbmax[Z] = max2f(pv_max[Z], pv_max[Z]+count*(pv_v_max[Z]+pv_acc_min[Z]));
345 			break;
346 		case(BAG_PARTICLE_SYS):
347 			calc_particle_random2_min_max(system_id->def->acc_minx, system_id->def->acc_maxx, &p_min, &p_max);
348 			pv_acc_min[X] = p_min;
349 			pv_acc_max[X] = p_max;
350 			calc_particle_random2_min_max(system_id->def->acc_miny, system_id->def->acc_maxy, &p_min, &p_max);
351 			pv_acc_min[Y] = p_min;
352 			pv_acc_max[Y] = p_max;
353 			calc_particle_random2_min_max(system_id->def->acc_minz, system_id->def->acc_maxz, &p_min, &p_max);
354 			pv_acc_min[Z] = p_min;
355 			pv_acc_max[Z] = p_max;
356 			p_step = pv_acc_min[Z]+pv_v_min[Z];
357 			count = ceil(1.0f/p_step);
358 			bbox->bbmin[X] = min2f(pv_min[X], pv_min[X]+count*(pv_v_min[X]+pv_acc_min[X]));
359 			bbox->bbmin[Y] = min2f(pv_min[Y], pv_min[Y]+count*(pv_v_min[Y]+pv_acc_max[X]));
360 			bbox->bbmin[Z] = min2f(pv_min[Z], pv_min[Z]+count*(pv_v_min[Z]+pv_acc_min[Y]));
361 			bbox->bbmax[X] = max2f(pv_max[X], pv_max[X]+count*(pv_v_max[X]+pv_acc_max[Y]));
362 			bbox->bbmax[Y] = max2f(pv_max[Y], pv_max[Y]+count*(pv_v_max[Y]+pv_acc_min[Z]));
363 			bbox->bbmax[Z] = max2f(pv_max[Z], pv_max[Z]+count*(pv_v_max[Z]+pv_acc_min[Z]));
364 			break;
365 		case(BURST_PARTICLE_SYS):
366 			sq *= 3;
367 			bbox->bbmin[X] = -sq;
368 			bbox->bbmin[Y] = -sq;
369 			bbox->bbmin[Z] = -sq;
370 			bbox->bbmax[X] = sq;
371 			bbox->bbmax[Y] = sq;
372 			bbox->bbmax[Z] = sq;
373 			break;
374 		case(FIRE_PARTICLE_SYS):
375 		case(FOUNTAIN_PARTICLE_SYS):
376 			calc_particle_random_min_max(system_id->def->acc_minx, system_id->def->acc_maxx, &p_min, &p_max);
377 			pv_acc_min[X] = p_min;
378 			pv_acc_max[X] = p_max;
379 			calc_particle_random_min_max(system_id->def->acc_miny, system_id->def->acc_maxy, &p_min, &p_max);
380 			pv_acc_min[Y] = p_min;
381 			pv_acc_max[Y] = p_max;
382 			calc_particle_random_min_max(system_id->def->acc_minz, system_id->def->acc_maxz, &p_min, &p_max);
383 			pv_acc_min[Z] = p_min;
384 			pv_acc_max[Z] = p_max;
385 
386 			if (system_id->def->random_func == 0)
387 				calc_particle_random_min_max(system_id->def->mina, system_id->def->maxa, &p_min, &p_max);
388 			else calc_particle_random2_min_max(system_id->def->mina, system_id->def->maxa, &p_min, &p_max);
389 			p_step = p_min;
390 			calc_particle_random_min_max(system_id->def->minda, system_id->def->maxda, &p_min, &p_max);
391 			count = ceil(p_max/(-p_step));
392 			bbox->bbmin[X] = min2f(pv_min[X], pv_min[X]+count*pv_v_min[X]+count*(count+1)*0.5f*pv_acc_min[X]);
393 			bbox->bbmin[Y] = min2f(pv_min[Y], pv_min[Y]+count*pv_v_min[Y]+count*(count+1)*0.5f*pv_acc_max[X]);
394 			bbox->bbmin[Z] = min2f(pv_min[Z], pv_min[Z]+count*pv_v_min[Z]+count*(count+1)*0.5f*pv_acc_min[Y]);
395 			bbox->bbmax[X] = max2f(pv_max[X], pv_max[X]+count*pv_v_max[X]+count*(count+1)*0.5f*pv_acc_max[Y]);
396 			bbox->bbmax[Y] = max2f(pv_max[Y], pv_max[Y]+count*pv_v_max[Y]+count*(count+1)*0.5f*pv_acc_min[Z]);
397 			bbox->bbmax[Z] = max2f(pv_max[Z], pv_max[Z]+count*pv_v_max[Z]+count*(count+1)*0.5f*pv_acc_min[Z]);
398 			break;
399 	}
400 
401 	bbox->bbmin[X] += system_id->x_pos;
402 	bbox->bbmin[Y] += system_id->y_pos;
403 	bbox->bbmin[Z] += system_id->z_pos;
404 	bbox->bbmax[X] += system_id->x_pos;
405 	bbox->bbmax[Y] += system_id->y_pos;
406 	bbox->bbmax[Z] += system_id->z_pos;
407 }
408 
409 #ifndef MAP_EDITOR
destroy_partice_sys_without_lock(int i)410 static __inline__ void destroy_partice_sys_without_lock(int i)
411 {
412 	if ((i < 0) || (i >= MAX_PARTICLE_SYSTEMS)) return;
413 	if (particles_list[i] == NULL) return;
414 	if(particles_list[i]->def && particles_list[i]->def->use_light && lights_list[particles_list[i]->light])
415 		destroy_light(particles_list[i]->light);
416 #ifdef NEW_SOUND
417 	stop_sound_at_location(particles_list[i]->x_pos, particles_list[i]->y_pos);
418 #endif // NEW_SOUND
419 	delete_particle_from_abt(main_bbox_tree, i);
420 	free(particles_list[i]);
421 	particles_list[i] = NULL;
422 }
423 
424 //void destroy_particle_sys(int i)
425 //{
426 //	LOCK_PARTICLES_LIST();
427 //	destroy_partice_sys_without_lock(i);
428 //	UNLOCK_PARTICLES_LIST();
429 //}
430 
431 #endif // !MAP_EDITOR
432 
433 #ifdef MAP_EDITOR2
434 #define MAP_EDITOR
435 #endif
436 
437 #ifdef MAP_EDITOR
save_particle_def(particle_sys_def * def)438 int save_particle_def(particle_sys_def *def)
439 {
440 	char cleanpath[128];
441 	FILE *f=NULL;
442 
443 	clean_file_name(cleanpath, def->file_name, sizeof(cleanpath));
444 
445 	f=open_file_data(cleanpath,"w");
446 	if(f == NULL){
447 		LOG_ERROR("%s: %s \"%s\": %s\n", reg_error_str, cant_open_file, cleanpath, strerror(errno));
448 		return 0;
449 	}
450 
451 	fprintf(f,"%i\n",PARTICLE_DEF_VERSION);
452 
453 	// System info
454 	fprintf(f,"%i\n",def->part_sys_type);
455 	fprintf(f,"%x,%x\n",def->sblend,def->dblend);
456 	fprintf(f,"%i\n",def->total_particle_no);
457 	fprintf(f,"%i\n",def->ttl);
458 	fprintf(f,"%i\n",def->part_texture);
459 	fprintf(f,"%f\n",def->part_size);
460 	fprintf(f,"%i\n",def->random_func);
461 	// Particle creation info
462 	fprintf(f,"%f,%f,%f\n",def->minx,def->miny,def->minz);
463 	fprintf(f,"%f,%f,%f\n",def->maxx,def->maxy,def->maxz);
464 	fprintf(f,"%f\n",def->constrain_rad_sq);
465 	fprintf(f,"%f,%f,%f\n",def->vel_minx,def->vel_miny,def->vel_minz);
466 	fprintf(f,"%f,%f,%f\n",def->vel_maxx,def->vel_maxy,def->vel_maxz);
467 	fprintf(f,"%f,%f,%f,%f\n",def->minr,def->ming,def->minb,def->mina);
468 	fprintf(f,"%f,%f,%f,%f\n",def->maxr,def->maxg,def->maxb,def->maxa);
469 	// Particle update info
470 	fprintf(f,"%f,%f,%f\n",def->acc_minx,def->acc_miny,def->acc_minz);
471 	fprintf(f,"%f,%f,%f\n",def->acc_maxx,def->acc_maxy,def->acc_maxz);
472 	fprintf(f,"%f,%f,%f,%f\n",def->mindr,def->mindg,def->mindb,def->minda);
473 	fprintf(f,"%f,%f,%f,%f\n",def->maxdr,def->maxdg,def->maxdb,def->maxda);
474 	// Particle light info
475 	fprintf(f,"%i\n",def->use_light);
476 	fprintf(f,"%f,%f,%f\n",def->lightx,def->lighty,def->lightz);
477 	fprintf(f,"%f,%f,%f\n",def->lightr,def->lightg,def->lightb);
478 
479 	fclose(f);
480 	return 1;
481 }
482 #endif
483 #ifdef MAP_EDITOR2
484 #undef MAP_EDITOR
485 #endif
486 
487 /*******************************************************************
488  *            INITIALIZATION AND CLEANUP FUNCTIONS                 *
489  *******************************************************************/
490 //Threading support for particles_list
init_particles()491 void init_particles ()
492 {
493 	int i;
494 
495 	for (i = 0; i < MAX_PARTICLE_TEXTURES; i++)
496 	{
497 		char buffer[256], filename[256];
498 
499 		safe_snprintf (filename, sizeof(filename), "./textures/particle%d", i);
500 
501 		if (check_image_name(filename, sizeof(buffer), buffer) == 1)
502 		{
503 			particle_textures[i] = load_texture_cached(buffer, tt_mesh);
504 		}
505 		else
506 		{
507 			particle_textures[i] = -1;
508 		}
509 	}
510 
511 	particles_list_mutex = SDL_CreateMutex();
512 	LOCK_PARTICLES_LIST ();   // lock it to avoid timing issues
513 	for (i = 0; i < MAX_PARTICLE_SYSTEMS; i++)
514 		particles_list[i] = NULL;
515 	for (i = 0; i < MAX_PARTICLE_DEFS; i++)
516 		defs_list[i] = NULL;
517 	UNLOCK_PARTICLES_LIST (); // release now that we are done
518 }
519 
end_particles()520 void end_particles ()
521 {
522 	LOCK_PARTICLES_LIST();
523 	destroy_all_particles();
524 	destroy_all_particle_defs();
525 	UNLOCK_PARTICLES_LIST();
526 	SDL_DestroyMutex(particles_list_mutex);
527 	particles_list_mutex=NULL;
528 }
529 
destroy_all_particle_defs()530 void destroy_all_particle_defs()
531 {
532 	int i;
533 	for(i=0;i<MAX_PARTICLE_DEFS;i++)
534 		{
535 			if(defs_list[i] != NULL) {
536 				free(defs_list[i]);
537 				defs_list[i] = NULL;
538 			}
539 		}
540 }
541 
destroy_all_particles()542 void destroy_all_particles()
543 {
544 	int i;
545 
546 	LOCK_PARTICLES_LIST();
547 	for(i=0;i<MAX_PARTICLE_SYSTEMS;i++)
548 		{
549 #ifndef	MAP_EDITOR
550 			destroy_partice_sys_without_lock(i);
551 #else
552 			if(!particles_list[i])continue;
553 			if(particles_list[i]->def && particles_list[i]->def->use_light && lights_list[particles_list[i]->light]) {
554 				free(lights_list[particles_list[i]->light]);
555 				lights_list[particles_list[i]->light]=NULL;
556 			}
557 			free(particles_list[i]);
558 			particles_list[i]=0;
559 #endif
560 		}
561 	UNLOCK_PARTICLES_LIST();
562 
563 }
564 #ifndef MAP_EDITOR
add_fire_at_tile(int kind,Uint16 x_tile,Uint16 y_tile,float z)565 void add_fire_at_tile (int kind, Uint16 x_tile, Uint16 y_tile, float z)
566 {
567 	float x = 0.5f * x_tile + 0.25f;
568 	float y = 0.5f * y_tile + 0.25f;
569 
570 	switch (kind)
571 	{
572 		case 2:
573 			add_particle_sys ("./particles/fire_big.part", x, y, z, 1);
574 			break;
575 		case 1:
576 		default:
577 			add_particle_sys ("./particles/fire_small.part", x, y, z, 1);
578 			break;
579 	}
580 }
581 
remove_fire_at_tile(Uint16 x_tile,Uint16 y_tile)582 void remove_fire_at_tile (Uint16 x_tile, Uint16 y_tile)
583 {
584 	size_t i;
585 	float x = 0.5f * x_tile + 0.25f;
586 	float y = 0.5f * y_tile + 0.25f;
587 
588 	ec_delete_effect_loc_type(x, y, EC_CAMPFIRE);
589 	LOCK_PARTICLES_LIST();
590 	for (i = 0; i < MAX_PARTICLE_SYSTEMS; i++)
591 	{
592 		particle_sys *sys = particles_list[i];
593 		if (particles_list[i] && strncmp (sys->def->file_name, "./particles/fire_", 17) == 0 && sys->x_pos == x && sys->y_pos == y)
594 			destroy_partice_sys_without_lock(i);
595 	}
596 	UNLOCK_PARTICLES_LIST();
597 
598 #ifdef NEW_SOUND
599 	stop_sound_at_location(x_tile, y_tile);
600 #endif // NEW_SOUND
601 	return;
602 }
603 #endif // !MAPEDITOR
604 /*********************************************************************
605  *          CREATION OF NEW PARTICLES AND SYSTEMS                    *
606  *********************************************************************/
607 #ifndef	MAP_EDITOR
608 
rotate_vector3f(float * vector,float x,float y,float z)609 void rotate_vector3f(float *vector, float x, float y, float z)
610 {
611 	// rotation matrixes
612 	float rot_x[9];
613 	float rot_y[9];
614 	float rot_z[9];
615 	float result_x[3];
616 	float result_y[3];
617 	MAT3_ROT_X(rot_x, x * (M_PI / 180.0f));
618 	MAT3_ROT_Y(rot_y, y * (M_PI / 180.0f));
619 	MAT3_ROT_Z(rot_z, z * (M_PI / 180.0f));
620 	// rotate around x achsis
621 	MAT3_VECT3_MULT(result_x, rot_x, vector);
622 	// rotate around y achsis
623 	MAT3_VECT3_MULT(result_y, rot_y, result_x);
624 	// rotate around z achsis
625 	MAT3_VECT3_MULT(vector, rot_z, result_y);
626 }
627 
add_ec_effect_to_e3d(object3d * e3d)628 void add_ec_effect_to_e3d(object3d* e3d)
629 {
630 	ec_bounds *bounds = ec_create_bounds_list();
631 	float shift[3] = { 0.0f, 0.0f, 0.0f };
632 	// useful for debugging:
633 	// ec_create_fountain(e3d->x_pos + shift[0], e3d->y_pos + shift[1], e3d->z_pos + shift[2], 0.0, 1.0, (e3d->z_pos >= 0.8 ? e3d->z_pos - 0.8 : 0.0), 0, 1.0, (poor_man ? 6 : 10));
634 	// printf("%f %f %s %i\n", e3d->x_pos*2, e3d->y_pos*2, e3d->file_name, e3d->self_lit);
635 	if (strstr(e3d->file_name, "/lantern1.e3d"))
636 	{
637 		ec_add_smooth_polygon_bound(bounds, 2.0, 0.25);
638 		shift[2] += 0.25f; // add height
639 		rotate_vector3f(shift, e3d->x_rot, e3d->y_rot, e3d->z_rot);
640 		ec_create_fireflies(e3d->x_pos + shift[0], e3d->y_pos + shift[1], e3d->z_pos + shift[2], 1.0, 1.0, 0.00625, 1.0, bounds);
641 	}
642 	else if (strstr(e3d->file_name, "/lantern2.e3d"))
643 	{
644 		ec_add_smooth_polygon_bound(bounds, 2.0, 0.25);
645 		shift[2] += 0.25f; // add height
646 		rotate_vector3f(shift, e3d->x_rot, e3d->y_rot, e3d->z_rot);
647 		ec_create_fireflies(e3d->x_pos + shift[0], e3d->y_pos + shift[1], e3d->z_pos + shift[2], 1.0, 1.0, 0.005, 1.0, bounds);
648 	}
649 	else if (strstr(e3d->file_name, "/lantern3.e3d"))
650 	{
651 		ec_add_smooth_polygon_bound(bounds, 2.0, 0.25);
652 		shift[2] += 0.25f; // add height
653 		rotate_vector3f(shift, e3d->x_rot, e3d->y_rot, e3d->z_rot);
654 		ec_create_fireflies(e3d->x_pos + shift[0], e3d->y_pos + shift[1], e3d->z_pos + shift[2], 1.0, 1.0, 0.005, 1.0, bounds);
655 	}
656 	else if (strstr(e3d->file_name, "/light1.e3d"))
657 	{
658 		ec_add_smooth_polygon_bound(bounds, 2.0, 0.33);
659 		shift[2] += 2.85f; // add height
660 		rotate_vector3f(shift, e3d->x_rot, e3d->y_rot, e3d->z_rot);
661 		ec_create_fireflies(e3d->x_pos + shift[0], e3d->y_pos + shift[1], e3d->z_pos + shift[2], 1.0, 1.0, 0.01, 1.0, bounds);
662 	}
663 	else if (strstr(e3d->file_name, "/light2.e3d"))
664 	{
665 		ec_add_smooth_polygon_bound(bounds, 2.0, 0.4);
666 		shift[2] += 2.95f; // add height
667 		rotate_vector3f(shift, e3d->x_rot, e3d->y_rot, e3d->z_rot);
668 		ec_create_fireflies(e3d->x_pos + shift[0], e3d->y_pos + shift[1], e3d->z_pos + shift[2], 1.0, 1.0, 0.0125, 1.0, bounds);
669 	}
670 	else if (strstr(e3d->file_name, "/light3.e3d"))
671 	{
672 		ec_add_smooth_polygon_bound(bounds, 2.0, 0.33);
673 		shift[2] += 3.5f; // add height
674 		shift[0] -= 0.33f; // the light is not centered
675 		rotate_vector3f(shift, e3d->x_rot, e3d->y_rot, e3d->z_rot);
676 		ec_create_fireflies(e3d->x_pos + shift[0], e3d->y_pos + shift[1], e3d->z_pos + shift[2], 1.0, 1.0, 0.015, 1.0, bounds);
677 	}
678 	else if (strstr(e3d->file_name, "/light4.e3d"))
679 	{
680 		ec_add_smooth_polygon_bound(bounds, 2.0, 0.4);
681 		shift[2] += 1.75f; // add height
682 		ec_create_fireflies(e3d->x_pos, e3d->y_pos, e3d->z_pos + 1.75f, 1.0, 1.0, 0.0075, 1.0, bounds);
683 	}
684 	ec_free_bounds_list(bounds);
685 }
686 
687 #ifdef NEW_SOUND
688 // Wrapper for map sounds (checks for existing sounds in similar location for multi-particle-system effects)
add_map_particle_sys(const char * file_name,float x_pos,float y_pos,float z_pos,unsigned int dynamic)689 int add_map_particle_sys(const char *file_name, float x_pos, float y_pos, float z_pos, unsigned int dynamic)
690 {
691 	int snd;
692 
693 	if (!no_sound)
694 	{
695 		snd = get_sound_index_for_particle_file_name(file_name);
696 		if (snd >= 0)
697 		{
698 			add_map_sound(snd, (x_pos - 0.25f) * 2, (y_pos - 0.25f) * 2);
699 		}
700 	}
701 	return real_add_particle_sys(file_name, x_pos, y_pos, z_pos, dynamic);
702 }
703 
704 // Wrapper for regular (event triggered) particle systems (no location check)
add_particle_sys(const char * file_name,float x_pos,float y_pos,float z_pos,unsigned int dynamic)705 int add_particle_sys (const char *file_name, float x_pos, float y_pos, float z_pos, unsigned int dynamic)
706 {
707 	int snd;
708 
709 	if (!no_sound)
710 	{
711 		snd = get_sound_index_for_particle_file_name(file_name);
712 		if (snd >= 0)
713 		{
714 			add_particle_sound(snd, (x_pos - 0.25f) * 2, (y_pos - 0.25f) * 2);
715 		}
716 	}
717 	return real_add_particle_sys(file_name, x_pos, y_pos, z_pos, dynamic);
718 }
719 
real_add_particle_sys(const char * file_name,float x_pos,float y_pos,float z_pos,unsigned int dynamic)720 static int real_add_particle_sys (const char *file_name, float x_pos, float y_pos, float z_pos, unsigned int dynamic)
721 #else
722 int add_particle_sys (const char *file_name, float x_pos, float y_pos, float z_pos, unsigned int dynamic)
723 #endif // NEW_SOUND
724 #else // !MAP_EDITOR
725 int add_particle_sys (const char *file_name, float x_pos, float y_pos, float z_pos)
726 #endif
727 {
728 #ifndef MAP_EDITOR
729 
730 	if (use_eye_candy)
731 	{
732 		if (!strncmp("fou", file_name + 12, 3))
733 			ec_create_fountain(x_pos, y_pos, z_pos + 0.15, 0.0, 1.0, (z_pos >= 0.8 ? z_pos - 0.8 : 0.0), 0, 1.0, (poor_man ? 6 : 10));
734 		else if ((use_fancy_smoke) && (!strncmp("smo", file_name + 12, 3)))
735 		{
736 			if (file_name[17] == '1')
737 				ec_create_smoke(x_pos, y_pos, z_pos, 0.0, 1.0, 0.3, (poor_man ? 6 : 10));
738 			else if (file_name[17] == '2')
739 				ec_create_smoke(x_pos, y_pos, z_pos, 0.0, 1.0, 0.45, (poor_man ? 6 : 10));
740 			else if (file_name[17] == '3')
741 				ec_create_smoke(x_pos, y_pos, z_pos, 0.0, 1.0, 1.6, (poor_man ? 6 : 10));
742 			else if (file_name[17] == '_')
743 				ec_create_smoke(x_pos, y_pos, z_pos, 0.0, 1.0, 1.1, (poor_man ? 6 : 10));
744 			else
745 				ec_create_smoke(x_pos, y_pos, z_pos, 0.0, 1.0, 0.5, (poor_man ? 6 : 10));
746 		}
747 		else if (!strncmp("tel", file_name + 12, 3))
748 		{
749 			if (file_name[21] == 'i')
750 			{
751 				ec_create_selfmagic_teleport_to_the_portals_room(x_pos, y_pos, z_pos, (poor_man ? 6 : 10));
752 			}
753 			else if (file_name[21] == 'o')
754 			{
755 				ec_create_selfmagic_teleport_to_the_portals_room(x_pos, y_pos, z_pos, (poor_man ? 6 : 10));
756 			}
757 			else
758 				ec_create_teleporter(x_pos, y_pos, z_pos, 0.0, 1.0, 1.0, (poor_man ? 6 : 10));
759 		}
760 		else if (!strncmp("fir", file_name + 12, 3))
761 		{
762 			if (!strncmp("big", file_name + 17, 3))
763 				ec_create_campfire(x_pos, y_pos, z_pos, 0.0, 1.0, (poor_man ? 6 : 10), 1.5);
764 			else if (!strncmp("for", file_name + 17, 3))
765 				ec_create_campfire(x_pos, y_pos - 0.2, z_pos, 0.0, 1.0, (poor_man ? 6 : 10), 2.0);
766 			else if (!strncmp("min", file_name + 17, 3))
767 				ec_create_campfire(x_pos, y_pos, z_pos, 0.0, 1.0, (poor_man ? 6 : 10), 0.4);
768 			else if (!strncmp("sma", file_name + 17, 3))
769 				ec_create_campfire(x_pos, y_pos, z_pos, 0.0, 1.0, (poor_man ? 6 : 10), 0.6);
770 			else if (!strncmp("tor", file_name + 17, 3))
771 				ec_create_lamp(x_pos, y_pos, z_pos, 0.0, 1.0, 1.6, (poor_man ? 6 : 10));
772 			else
773 			{
774 				particle_sys_def *def = load_particle_def(file_name);
775 				if (!def) return -1;
776 
777   #ifndef	MAP_EDITOR
778 				return create_particle_sys (def, x_pos, y_pos, z_pos, dynamic);
779   #else
780 				return create_particle_sys (def, x_pos, y_pos, z_pos);
781   #endif
782 			}
783 		}
784 		else if (!strncmp("can", file_name + 12, 3))
785 			ec_create_candle(x_pos, y_pos, z_pos, 0.0, 1.0, 0.7, (poor_man ? 6 : 10));
786 		else
787 		{
788 #endif //!MAP_EDITOR
789 			particle_sys_def *def = load_particle_def(file_name);
790 			if (!def) return -1;
791 
792  #ifndef	MAP_EDITOR
793 			return create_particle_sys (def, x_pos, y_pos, z_pos, dynamic);
794  #else
795 			return create_particle_sys (def, x_pos, y_pos, z_pos);
796  #endif
797 #ifndef MAP_EDITOR
798 		}
799 	}
800 	else
801 	{
802 		particle_sys_def *def = load_particle_def(file_name);
803 		if (!def) return -1;
804 
805  #ifndef	MAP_EDITOR
806 		return create_particle_sys (def, x_pos, y_pos, z_pos, dynamic);
807  #else
808 		return create_particle_sys (def, x_pos, y_pos, z_pos);
809  #endif
810 	}
811 #endif //!MAP_EDITOR
812 
813 	// If we got here, the eye candy system handled this particle
814 	// system. Return an invalid particle ID to signal that nothing
815 	// was added to particles_list, but not -1 since this is not an
816 	// error.
817 	return -2;
818 }
819 
820 #ifndef	MAP_EDITOR
add_particle_sys_at_tile(const char * file_name,int x_tile,int y_tile,unsigned int dynamic)821 int add_particle_sys_at_tile (const char *file_name, int x_tile, int y_tile, unsigned int dynamic)
822 #else
823 int add_particle_sys_at_tile (const char *file_name, int x_tile, int y_tile)
824 #endif
825 {
826 	float z;
827 
828 	z = get_tile_height(x_tile, y_tile);
829 #ifndef	MAP_EDITOR
830 	return add_particle_sys (file_name, (float) x_tile / 2.0 + 0.25f, (float) y_tile / 2.0 + 0.25f, z, dynamic);
831 #else
832 	return add_particle_sys (file_name, (float) x_tile / 2.0 + 0.25f, (float) y_tile / 2.0 + 0.25f, z);
833 #endif
834 }
835 
create_particle(particle_sys * sys,particle * result)836 void create_particle(particle_sys *sys,particle *result)
837 {
838 	particle_sys_def *def=sys->def;
839 	if(def->random_func==0) {
840 		do {
841 			result->x=PARTICLE_RANDOM(def->minx,def->maxx);
842 			result->y=PARTICLE_RANDOM(def->miny,def->maxy);
843 			result->z=PARTICLE_RANDOM(def->minz,def->maxz);
844 		} while(def->constrain_rad_sq>0 && (result->x*result->x+result->y*result->y)>def->constrain_rad_sq);
845 
846 		result->vx=PARTICLE_RANDOM(def->vel_minx,def->vel_maxx);
847 		result->vy=PARTICLE_RANDOM(def->vel_miny,def->vel_maxy);
848 		result->vz=PARTICLE_RANDOM(def->vel_minz,def->vel_maxz);
849 
850 		result->r=PARTICLE_RANDOM(def->minr,def->maxr);
851 		result->g=PARTICLE_RANDOM(def->ming,def->maxg);
852 		result->b=PARTICLE_RANDOM(def->minb,def->maxb);
853 		result->a=PARTICLE_RANDOM(def->mina,def->maxa);
854 	} else {
855 		do {
856 			result->x=PARTICLE_RANDOM2(def->minx,def->maxx);
857 			result->y=PARTICLE_RANDOM2(def->miny,def->maxy);
858 			result->z=PARTICLE_RANDOM2(def->minz,def->maxz);
859 		} while(def->constrain_rad_sq>0 && (result->x*result->x+result->y*result->y)>def->constrain_rad_sq);
860 
861 		result->vx=PARTICLE_RANDOM2(def->vel_minx,def->vel_maxx);
862 		result->vy=PARTICLE_RANDOM2(def->vel_miny,def->vel_maxy);
863 		result->vz=PARTICLE_RANDOM2(def->vel_minz,def->vel_maxz);
864 
865 		result->r=PARTICLE_RANDOM2(def->minr,def->maxr);
866 		result->g=PARTICLE_RANDOM2(def->ming,def->maxg);
867 		result->b=PARTICLE_RANDOM2(def->minb,def->maxb);
868 		result->a=PARTICLE_RANDOM2(def->mina,def->maxa);
869 	}
870 	result->x+=sys->x_pos;
871 	result->y+=sys->y_pos;
872 	result->z+=sys->z_pos;
873 
874 	result->free=0;
875 }
876 
877 #ifndef	MAP_EDITOR
create_particle_sys(particle_sys_def * def,float x,float y,float z,unsigned int dynamic)878 int create_particle_sys (particle_sys_def *def, float x, float y, float z, unsigned int dynamic)
879 #else
880 int create_particle_sys (particle_sys_def *def, float x, float y, float z)
881 #endif
882 {
883 	int	i,psys;
884 	particle_sys *system_id;
885 	particle *p;
886 #ifndef	MAP_EDITOR
887 	AABBOX bbox;
888 	memset(&bbox, '\0', sizeof(bbox));
889 #endif
890 
891 	if(!def)return -1;
892 
893 	//allocate memory for this particle system
894 	system_id=(particle_sys *)calloc(1,sizeof(particle_sys));
895 
896 	LOCK_PARTICLES_LIST();
897 	//now, find a place for this system
898 	for(psys=0;psys<MAX_PARTICLE_SYSTEMS;psys++)
899 		{
900 			if(!particles_list[psys])
901 				{
902 					particles_list[psys]=system_id;
903 					break;
904 				}
905 		}
906 	if(psys==MAX_PARTICLE_SYSTEMS)
907 		{
908 			free(system_id);
909 			UNLOCK_PARTICLES_LIST();
910 			return -1;
911 		}
912 
913 	system_id->x_pos=x;
914 	system_id->y_pos=y;
915 	system_id->z_pos=z;
916 	system_id->def=def;
917 	system_id->particle_count=def->total_particle_no;
918 	system_id->ttl=def->ttl;
919 
920 	if(def->use_light) {
921 #ifndef MAP_EDITOR
922 		system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f, dynamic);
923 #else
924 		system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f,1);
925 #endif
926 	}
927 
928 	for(i=0,p=&system_id->particles[0];i<def->total_particle_no;i++,p++)create_particle(system_id,p);
929 
930 #ifdef CLUSTER_INSIDES
931 	system_id->cluster = get_cluster ((int)(x/0.5f), (int)(y/0.5f));
932 	current_cluster = system_id->cluster;
933 #endif
934 
935 #ifndef	MAP_EDITOR
936 	calc_bounding_box_for_particle_sys(&bbox, system_id);
937 
938 	if ((main_bbox_tree_items != NULL) && (dynamic == 0)) add_particle_sys_to_list(main_bbox_tree_items, psys, bbox, def->sblend, def->dblend);
939 	else add_particle_to_abt(main_bbox_tree, psys, bbox, def->sblend, def->dblend, dynamic);
940 #endif
941 
942 	UNLOCK_PARTICLES_LIST();
943 
944 	return psys;
945 }
946 
947 /**********************************************************************
948  *                      RENDERING FUNCTIONS                           *
949  **********************************************************************/
draw_text_particle_sys(particle_sys * system_id)950 void draw_text_particle_sys(particle_sys *system_id)
951 {
952 	int i;
953 	float z_len=0.065f*system_id->def->part_size;
954 	float x_len=z_len*cos(-rz*M_PI/180.0);
955 	float y_len=z_len*sin(-rz*M_PI/180.0);
956 	particle *p;
957 
958 	LOCK_PARTICLES_LIST();	//lock it to avoid timing issues
959 
960 #ifdef OPENGL_TRACE
961 	CHECK_GL_ERRORS();
962 #endif
963 	bind_texture(particle_textures[system_id->def->part_texture]);
964 
965 	for(i=0,p=&system_id->particles[0];i<system_id->def->total_particle_no;i=i+5,p=p+5)
966 		{
967 			if(!p->free)
968 				{
969 					glPushMatrix();
970 					glTranslatef(p->x,p->y,p->z);
971 					glBegin(GL_TRIANGLE_STRIP);
972 					glColor4f(p->r,p->g,p->b,p->a);
973 
974 					glTexCoord2f(0.0f,1.0f);
975 					glVertex3f(-x_len,-y_len,+z_len);
976 
977 					glTexCoord2f(0.0f,0.0f);
978 					glVertex3f(-x_len,-y_len,-z_len);
979 
980 					glTexCoord2f(1.0f,1.0f);
981 					glVertex3f(x_len,y_len,+z_len);
982 
983 					glTexCoord2f(1.0f,0.0f);
984 					glVertex3f(x_len,y_len,-z_len);
985 
986 					glEnd();
987 					glPopMatrix();
988 				}
989 		}
990 	UNLOCK_PARTICLES_LIST();	// release now that we are done
991 #ifdef OPENGL_TRACE
992 	CHECK_GL_ERRORS();
993 #endif
994 }
995 
draw_point_particle_sys(particle_sys * system_id)996 void draw_point_particle_sys(particle_sys *system_id)
997 {
998 #ifdef ELC
999 	int i;
1000 	particle *p;
1001 
1002 	/* Particle size is scaled according to the zoom level but based on
1003 	 * a previous maximum of 4.0.  When the maximum zoom was increased,
1004 	 * the scaling code broke.  This compromise keeps the particles
1005 	 * visible at the maximum zoom without changing the previous size
1006 	 * at closer zooms. */
1007 	GLfloat local_zoom_level = zoom_level;
1008 	if (local_zoom_level > 4.0)
1009 		local_zoom_level = 4.0;
1010 
1011 #ifdef OPENGL_TRACE
1012 	CHECK_GL_ERRORS();
1013 #endif
1014 	glEnable(GL_POINT_SPRITE_NV);
1015 	glTexEnvf(GL_POINT_SPRITE_NV,GL_COORD_REPLACE_NV,GL_TRUE);
1016 	glPointSize(system_id->def->part_size*(5.5f-local_zoom_level)*4.4f);
1017 	bind_texture(particle_textures[system_id->def->part_texture]);
1018 #if 0
1019 	//#ifdef USE_VERTEX_ARRAYS
1020 	// This might be useful if we allow more particles per system.
1021 	// It does, however, render free particles...
1022 	if(use_vertex_array)
1023 		{
1024 			glEnableClientState(GL_VERTEX_ARRAY);
1025 			glDisableClientState(GL_NORMAL_ARRAY);
1026 			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
1027 			glEnableClientState(GL_COLOR_ARRAY);
1028 			LOCK_PARTICLES_LIST(); //lock it to avoid timing issues
1029 			glVertexPointer(3,GL_FLOAT,sizeof(particle),&(system_id->particles[0].x));
1030 			glColorPointer(4,GL_FLOAT,sizeof(particle),&(system_id->particles[0].r));
1031 			glDrawArrays(GL_POINTS,0,system_id->total_particle_no);
1032 			UNLOCK_PARTICLES_LIST();// release now that we are done
1033 			glDisableClientState(GL_VERTEX_ARRAY);
1034 			glDisableClientState(GL_COLOR_ARRAY);
1035 
1036 		}
1037 	else
1038 #endif
1039  {
1040 	glBegin(GL_POINTS);
1041 	LOCK_PARTICLES_LIST();	//lock it to avoid timing issues
1042 	for(i=0,p=&system_id->particles[0];i<system_id->def->total_particle_no;i++,p++)
1043 	  {
1044 		if(!p->free)
1045 			{
1046 				glColor4f(p->r,p->g,p->b,p->a);
1047 				glVertex3f(p->x,p->y,p->z);
1048 			}
1049 	  }
1050 	UNLOCK_PARTICLES_LIST();	// release now that we are done
1051 	glEnd();
1052  }
1053 	glDisable(GL_POINT_SPRITE_NV);
1054 #ifdef OPENGL_TRACE
1055 	CHECK_GL_ERRORS();
1056 #endif
1057 #endif
1058 }
1059 
1060 #ifndef ELC
1061 int have_point_sprite=0;
1062 #endif
1063 
display_particles()1064 void display_particles()
1065 {
1066 
1067 #ifdef	MAP_EDITOR
1068 	int i;
1069 #endif
1070 #if defined(SIMPLE_LOD) || defined(MAP_EDITOR)
1071 	int x,y;
1072 #endif  //SIMPLE_LOD || MAP_EDITOR
1073 	GLenum sblend=GL_SRC_ALPHA,dblend=GL_ONE;
1074 #ifndef	MAP_EDITOR
1075 	unsigned int i, l, start, stop;
1076 #ifdef CLUSTER_INSIDES_OLD
1077 	short cluster = get_actor_cluster ();
1078 #endif
1079 #endif // !MAP_EDITOR
1080 
1081 	if(!particles_percentage)
1082 	  return;
1083 
1084 #if defined(SIMPLE_LOD) || defined(MAP_EDITOR)
1085 	x=-camera_x;
1086 	y=-camera_y;
1087 #endif  //SIMPLE_LOD || MAP_EDITOR
1088 
1089 #ifdef OPENGL_TRACE
1090 	CHECK_GL_ERRORS();
1091 #endif
1092 	glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT);
1093 	glDepthMask(GL_FALSE);
1094 	glEnable(GL_BLEND);
1095 	glEnable(GL_CULL_FACE);
1096 	glDisable(GL_LIGHTING);
1097 
1098 	glBlendFunc(sblend,dblend);
1099 
1100 	LOCK_PARTICLES_LIST();
1101 	// Perhaps we should have a depth sort here..?
1102 #ifndef	MAP_EDITOR
1103 	get_intersect_start_stop(main_bbox_tree, TYPE_PARTICLE_SYSTEM, &start, &stop);
1104 	for (i = start; i < stop; i++)
1105 	{
1106 		l = get_intersect_item_ID(main_bbox_tree, i);
1107 		if (!particles_list[l])
1108 		{
1109 #ifdef EXTRA_DEBUG
1110 			ERR();
1111 #endif
1112 			continue;
1113 		}
1114 #ifdef CLUSTER_INSIDES_OLD
1115 		if (particles_list[l]->cluster && particles_list[l]->cluster != cluster)
1116 			continue;
1117 #endif
1118 #ifdef  SIMPLE_LOD
1119 		// last final check for a distance limit
1120 		if(((x-particles_list[l]->x_pos)*(x-particles_list[l]->x_pos) + (y-particles_list[l]->y_pos)*(y-particles_list[l]->y_pos)) >= PART_SYS_VISIBLE_DIST_SQ){
1121 			continue;
1122 		}
1123 #endif  //SIMPLE_LOD
1124 		if ((particles_list[l]->def->sblend != sblend) || (particles_list[l]->def->dblend != dblend))
1125 		{
1126 			sblend = particles_list[l]->def->sblend;
1127 			dblend = particles_list[l]->def->dblend;
1128 			glBlendFunc(sblend, dblend);
1129 		}
1130 		if (use_point_particles) draw_point_particle_sys(particles_list[l]);
1131 		else draw_text_particle_sys(particles_list[l]);
1132 	}
1133 #else	//MAP_EDITOR
1134 	for(i=0;i<MAX_PARTICLE_SYSTEMS;i++)
1135 	{
1136 		if(particles_list[i])
1137 		{
1138 			int dist1;
1139 			int dist2;
1140 
1141 			dist1=x-particles_list[i]->x_pos;
1142 			dist2=y-particles_list[i]->y_pos;
1143 			if(dist1*dist1+dist2*dist2<=PART_SYS_VISIBLE_DIST_SQ)
1144 			{
1145 				if(particles_list[i]->def->sblend!=sblend || particles_list[i]->def->dblend!=dblend)
1146 				{
1147 					sblend=particles_list[i]->def->sblend;
1148 					dblend=particles_list[i]->def->dblend;
1149 					glBlendFunc(sblend,dblend);
1150 				}
1151 				if(use_point_particles) {
1152 					draw_point_particle_sys(particles_list[i]);
1153 				} else {
1154 					draw_text_particle_sys(particles_list[i]);
1155 				}
1156 			}
1157 		}
1158 	}
1159 #endif	//MAP_EDITOR
1160 	UNLOCK_PARTICLES_LIST();
1161 	glDisable(GL_CULL_FACE); //Intel fix
1162 	glPopAttrib();
1163 #ifdef OPENGL_TRACE
1164 	CHECK_GL_ERRORS();
1165 #endif
1166 }
1167 
1168 /******************************************************************************
1169  *                           UPDATE FUNCTIONS                                 *
1170  ******************************************************************************/
1171 
get_particles_to_add(int total_particles,int particles_count)1172 static int get_particles_to_add(int total_particles, int particles_count)
1173 {
1174 	return (((float)particles_percentage / 100.0) * total_particles) - particles_count;
1175 }
1176 
update_fountain_sys(particle_sys * system_id)1177 void update_fountain_sys(particle_sys *system_id) {
1178 	int i,j;
1179 	int total_particle_no;
1180 	int particles_to_add=0;
1181 	particle *p;
1182 
1183 	total_particle_no=system_id->def->total_particle_no;
1184 
1185 	//see if we need to add new particles
1186 	LOCK_PARTICLES_LIST();
1187 	if(system_id->ttl)
1188 		particles_to_add = get_particles_to_add(total_particle_no, system_id->particle_count);
1189 
1190 	if(particles_to_add) {
1191 		for(j=i=0;i<particles_to_add;i++)
1192 		{
1193 			//find a free space
1194 			for(;j<total_particle_no;j++) {
1195 				if(system_id->particles[j].free)
1196 				{
1197 					create_particle(system_id,&(system_id->particles[j]));
1198 					system_id->particle_count++;
1199 					break;
1200 				}
1201 			}
1202 		}
1203 	}
1204 
1205 	//excellent, now we have to actually update the particles
1206 	//find used particles
1207 	for(j=0,p=&system_id->particles[0];j<total_particle_no;j++,p++) {
1208 		if(!p->free)
1209 		{
1210 			if(p->a<0.0f)
1211 			{
1212 				//poor particle, it died :(
1213 				p->free=1;
1214 				if(system_id->particle_count)system_id->particle_count--;
1215 				continue;
1216 			}
1217 			if(p->z<0.0f)
1218 			{
1219 				p->z=0.001f;
1220 				p->vz=-p->vz;
1221 			}
1222 			p->x+=p->vx;
1223 			p->y+=p->vy;
1224 			p->z+=p->vz;
1225 			p->vx+=PARTICLE_RANDOM(system_id->def->acc_minx,system_id->def->acc_maxx);
1226 			p->vy+=PARTICLE_RANDOM(system_id->def->acc_miny,system_id->def->acc_maxy);
1227 			p->vz+=PARTICLE_RANDOM(system_id->def->acc_minz,system_id->def->acc_maxz);
1228 			p->r+=PARTICLE_RANDOM(system_id->def->mindr,system_id->def->maxdr);
1229 			p->g+=PARTICLE_RANDOM(system_id->def->mindg,system_id->def->maxdg);
1230 			p->b+=PARTICLE_RANDOM(system_id->def->mindb,system_id->def->maxdb);
1231 			p->a+=PARTICLE_RANDOM(system_id->def->minda,system_id->def->maxda);
1232 		}
1233 	}
1234 	UNLOCK_PARTICLES_LIST();
1235 }
1236 
update_burst_sys(particle_sys * system_id)1237 void update_burst_sys(particle_sys *system_id)
1238 {
1239 	int j;
1240 	int total_particle_no;
1241 	particle *p;
1242 
1243 	total_particle_no=system_id->def->total_particle_no;
1244 
1245 	LOCK_PARTICLES_LIST();
1246 
1247 	//find used particles
1248 	for(j=0,p=&system_id->particles[0];j<total_particle_no;j++,p++) {
1249 		if(!p->free)
1250 		{
1251 			float distx=p->x-system_id->x_pos;
1252 			float disty=p->y-system_id->y_pos;
1253 			float distz=p->z-system_id->z_pos;
1254 			float dist_sq=distx*distx+disty*disty+distz*distz;
1255 			if(dist_sq>system_id->def->constrain_rad_sq*9.0 || dist_sq<0.01)
1256 			{
1257 				//poor particle, it died :(
1258 				p->free=1;
1259 				if(system_id->particle_count)system_id->particle_count--;
1260 				continue;
1261 			}
1262 			if(p->vx>-0.01 && p->vx<0.01 &&
1263 			   p->vy>-0.01 && p->vy<0.01 &&
1264 			   p->vz>-0.01 && p->vz<0.01)
1265 			{
1266 				float len=0.25/sqrt(dist_sq);
1267 				p->vx=distx*len;
1268 				p->vy=disty*len;
1269 				p->vz=distz*len;
1270 			}
1271 			p->x+=p->vx;
1272 			p->y+=p->vy;
1273 			p->z+=p->vz;
1274 
1275 			p->r+=PARTICLE_RANDOM(system_id->def->mindr,system_id->def->maxdr);
1276 			p->g+=PARTICLE_RANDOM(system_id->def->mindg,system_id->def->maxdg);
1277 			p->b+=PARTICLE_RANDOM(system_id->def->mindb,system_id->def->maxdb);
1278 			p->a+=PARTICLE_RANDOM(system_id->def->minda,system_id->def->maxda);
1279 		}
1280 	}
1281 	UNLOCK_PARTICLES_LIST();
1282 }
1283 
update_fire_sys(particle_sys * system_id)1284 void update_fire_sys(particle_sys *system_id)
1285 {
1286 	int i;
1287 	int particles_to_add=0;
1288 	int total_particle_no=system_id->def->total_particle_no;
1289 	particle *p;
1290 	int j;
1291 
1292 	//see if we need to add new particles
1293 	LOCK_PARTICLES_LIST();
1294 
1295 	if(system_id->ttl)
1296 		particles_to_add = get_particles_to_add(total_particle_no, system_id->particle_count);
1297 
1298 	for(j=i=0;i<particles_to_add;i++)
1299 		{
1300 			//find a free space
1301 			for(;j<total_particle_no;j++)
1302 				if(system_id->particles[j].free)
1303 					{
1304 						//finally, we found a spot
1305 						create_particle(system_id,&(system_id->particles[j]));
1306 						//increase the particle count
1307 						system_id->particle_count++;
1308 						j++;
1309 						break;	//done looping
1310 					}
1311 			}
1312 
1313 	//excellent, now we have to actually update the particles
1314 	//find a used particle
1315 	for(j=0,p=&system_id->particles[0];j<total_particle_no;j++,p++)
1316 		if(!p->free)
1317 			{
1318 				if(p->a<0.0f)
1319 					{
1320 						//poor particle, it died :(
1321 						p->free=1;
1322 						if(system_id->particle_count)system_id->particle_count--;
1323 						continue;
1324 					}
1325 
1326 				// Fires don't use acceleration as usual...
1327 				p->x+=p->vx+PARTICLE_RANDOM(system_id->def->acc_minx,system_id->def->acc_maxx);
1328 				p->y+=p->vy+PARTICLE_RANDOM(system_id->def->acc_miny,system_id->def->acc_maxy);
1329 				p->z+=p->vz+PARTICLE_RANDOM(system_id->def->acc_minz,system_id->def->acc_maxz);
1330 
1331 				p->r+=PARTICLE_RANDOM(system_id->def->mindr,system_id->def->maxdr);
1332 				p->g+=PARTICLE_RANDOM(system_id->def->mindg,system_id->def->maxdg);
1333 				p->b+=PARTICLE_RANDOM(system_id->def->mindb,system_id->def->maxdb);
1334 				p->a+=PARTICLE_RANDOM(system_id->def->minda,system_id->def->maxda);
1335 
1336 			}
1337 	UNLOCK_PARTICLES_LIST();
1338 }
1339 
update_teleporter_sys(particle_sys * system_id)1340 void update_teleporter_sys(particle_sys *system_id)
1341 {
1342 	int i;
1343 	int particles_to_add=0;
1344 	int total_particle_no=system_id->def->total_particle_no;
1345 	particle *p;
1346 	int j;
1347 
1348 	//see if we need to add new particles
1349 	LOCK_PARTICLES_LIST();
1350 
1351 	if(system_id->ttl)
1352 		particles_to_add = get_particles_to_add(total_particle_no, system_id->particle_count);
1353 	for(j=i=0;i<particles_to_add;i++)
1354 		{
1355 			//find a free space
1356 			for(;j<total_particle_no;j++)
1357 				if(system_id->particles[j].free)
1358 					{
1359 						//finally, we found a spot
1360 						create_particle(system_id,&(system_id->particles[j]));
1361 						if(system_id->particles[j].z<system_id->z_pos)system_id->particles[j].z=system_id->z_pos;
1362 						//increase the particle count
1363 						system_id->particle_count++;
1364 						break;	//done looping
1365 					}
1366 
1367 		}
1368 
1369 	//excellent, now we have to actually update the particles
1370 	//find used particles
1371 	for(j=0,p=&system_id->particles[0];j<total_particle_no;j++,p++)
1372 		if(!p->free)
1373 			{
1374 				if(p->z>system_id->z_pos+2.0f)
1375 					{
1376 						//poor particle, it died :(
1377 						p->free=1;
1378 						if(system_id->particle_count)system_id->particle_count--;
1379 						continue;
1380 					}
1381 
1382 				// Teleporters don't use acceleration as usual...
1383 				p->x+=p->vx+PARTICLE_RANDOM2(system_id->def->acc_minx,system_id->def->acc_maxx);
1384 				p->y+=p->vy+PARTICLE_RANDOM2(system_id->def->acc_miny,system_id->def->acc_maxy);
1385 				p->z+=p->vz+PARTICLE_RANDOM2(system_id->def->acc_minz,system_id->def->acc_maxz);
1386 
1387 				p->r+=PARTICLE_RANDOM2(system_id->def->mindr,system_id->def->maxdr);
1388 				p->g+=PARTICLE_RANDOM2(system_id->def->mindg,system_id->def->maxdg);
1389 				p->b+=PARTICLE_RANDOM2(system_id->def->mindb,system_id->def->maxdb);
1390 				p->a+=PARTICLE_RANDOM2(system_id->def->minda,system_id->def->maxda);
1391 
1392 			}
1393 	UNLOCK_PARTICLES_LIST();
1394 }
1395 
update_teleport_sys(particle_sys * system_id)1396 void update_teleport_sys(particle_sys *system_id)
1397 {
1398 	int i;
1399 	int total_particle_no=system_id->def->total_particle_no;
1400 	int particles_to_add=0;
1401 	particle *p;
1402 	int j;
1403 
1404 	//see if we need to add new particles
1405 	LOCK_PARTICLES_LIST();
1406 	if(system_id->ttl)
1407 		particles_to_add = get_particles_to_add(total_particle_no, system_id->particle_count);
1408 	for(j=i=0;i<particles_to_add;i++)
1409 		{
1410 			//find a free space
1411 			for(;j<total_particle_no;j++)
1412 				if(system_id->particles[j].free)
1413 					{
1414 						create_particle(system_id,&(system_id->particles[j]));
1415 						system_id->particles[j].x=system_id->x_pos;
1416 						system_id->particles[j].y=system_id->y_pos;
1417 						system_id->particles[j].z=system_id->z_pos;
1418 						system_id->particle_count++;
1419 
1420 						break;
1421 					}
1422 
1423 		}
1424 
1425 	//excellent, now we have to actually update the particles
1426 	//find used particles
1427 	for(j=0,p=&system_id->particles[0];j<total_particle_no;j++,p++)
1428 		if(!p->free)
1429 			{
1430 				if(p->z>system_id->z_pos+2.0f)
1431 					{
1432 						//poor particle, it died :(
1433 						p->free=1;
1434 						if(system_id->particle_count)system_id->particle_count--;
1435 						continue;
1436 					}
1437 
1438 				// Teleports don't use acceleration as usual...
1439 				p->x+=p->vx+PARTICLE_RANDOM2(system_id->def->acc_minx,system_id->def->acc_maxx);
1440 				p->y+=p->vy+PARTICLE_RANDOM2(system_id->def->acc_miny,system_id->def->acc_maxy);
1441 				p->z+=p->vz+PARTICLE_RANDOM2(system_id->def->acc_minz,system_id->def->acc_maxz);
1442 
1443 				p->r+=PARTICLE_RANDOM2(system_id->def->mindr,system_id->def->maxdr);
1444 				p->g+=PARTICLE_RANDOM2(system_id->def->mindg,system_id->def->maxdg);
1445 				p->b+=PARTICLE_RANDOM2(system_id->def->mindb,system_id->def->maxdb);
1446 				p->a+=PARTICLE_RANDOM2(system_id->def->minda,system_id->def->maxda);
1447 
1448 			}
1449 	UNLOCK_PARTICLES_LIST();
1450 }
1451 
update_bag_part_sys(particle_sys * system_id)1452 void update_bag_part_sys(particle_sys *system_id)
1453 {
1454 	int i;
1455 	int total_particle_no=system_id->def->total_particle_no;
1456 	int particles_to_add=0;
1457 	particle *p;
1458 	int j;
1459 
1460 	//see if we need to add new particles
1461 	LOCK_PARTICLES_LIST();
1462 	if(system_id->ttl)
1463 		particles_to_add = get_particles_to_add(total_particle_no, system_id->particle_count);
1464 	for(j=i=0;i<particles_to_add;i++)
1465 		{
1466 			//find a free space
1467 			for(;j<total_particle_no;j++)
1468 				if(system_id->particles[j].free)
1469 					{
1470 						//finally, we found a spot
1471 						create_particle(system_id,&(system_id->particles[j]));
1472 						if(system_id->particles[j].z<system_id->z_pos)system_id->particles[j].z=system_id->z_pos;
1473 						//increase the particle count
1474 						system_id->particle_count++;
1475 						break;	//done looping
1476 					}
1477 		}
1478 
1479 	//excellent, now we have to actually update the particles
1480 	//find used particles
1481 	for(j=0,p=&system_id->particles[0];j<total_particle_no;j++,p++)
1482 		if(!p->free)
1483 			{
1484 				if(p->z>system_id->z_pos+1.0f)
1485 					{
1486 						//poor particle, it died :(
1487 						p->free=1;
1488 						if(system_id->particle_count)system_id->particle_count--;
1489 						continue;
1490 					}
1491 				// Bags don't use acceleration as usual...
1492 				p->x+=p->vx+PARTICLE_RANDOM2(system_id->def->acc_minx,system_id->def->acc_maxx);
1493 				p->y+=p->vy+PARTICLE_RANDOM2(system_id->def->acc_miny,system_id->def->acc_maxy);
1494 				p->z+=p->vz+PARTICLE_RANDOM2(system_id->def->acc_minz,system_id->def->acc_maxz);
1495 
1496 				p->r+=PARTICLE_RANDOM2(system_id->def->mindr,system_id->def->maxdr);
1497 				p->g+=PARTICLE_RANDOM2(system_id->def->mindg,system_id->def->maxdg);
1498 				p->b+=PARTICLE_RANDOM2(system_id->def->mindb,system_id->def->maxdb);
1499 				p->a+=PARTICLE_RANDOM2(system_id->def->minda,system_id->def->maxda);
1500 			}
1501 	UNLOCK_PARTICLES_LIST();
1502 }
1503 
update_particles()1504 void update_particles() {
1505 #ifndef	MAP_EDITOR
1506 	unsigned int i, l, start, stop;
1507 #else
1508 	int i;
1509 #ifdef ELC
1510 	int x = -camera_x, y = -camera_y;
1511 #endif
1512 #endif
1513 
1514 	if(!particles_percentage){
1515 		return;
1516 	}
1517 	LOCK_PARTICLES_LIST();
1518 #ifndef	MAP_EDITOR
1519 	for (i = 0; i < MAX_PARTICLE_SYSTEMS; i++)
1520 	{
1521 		if (particles_list[i])
1522 		{
1523 			// Systems with a TTL need to be updated, even if they are far away
1524 			if (particles_list[i]->ttl < 0) continue;
1525 
1526 			switch (particles_list[i]->def->part_sys_type)
1527 			{
1528 				case TELEPORTER_PARTICLE_SYS:
1529 					update_teleporter_sys(particles_list[i]);
1530 					break;
1531                      		case TELEPORT_PARTICLE_SYS:
1532 					update_teleport_sys(particles_list[i]);
1533 					break;
1534 				case BAG_PARTICLE_SYS:
1535 					update_bag_part_sys(particles_list[i]);
1536 					break;
1537 				case BURST_PARTICLE_SYS:
1538 					update_burst_sys(particles_list[i]);
1539 					break;
1540 				case FIRE_PARTICLE_SYS:
1541 					update_fire_sys(particles_list[i]);
1542 					break;
1543 				case FOUNTAIN_PARTICLE_SYS:
1544 					update_fountain_sys(particles_list[i]);
1545 					break;
1546 			}
1547 			if (particles_list[i]->ttl > 0) particles_list[i]->ttl--;
1548 			//if there are no more particles to add, and the TTL expired, then kill this evil system
1549 			if (!particles_list[i]->ttl && !particles_list[i]->particle_count)
1550 				destroy_partice_sys_without_lock(i);
1551 		}
1552 	}
1553 	get_intersect_start_stop(main_bbox_tree, TYPE_PARTICLE_SYSTEM, &start, &stop);
1554 	for (i = start; i < stop; i++)
1555 	{
1556 		l = get_intersect_item_ID(main_bbox_tree, i);
1557 		if (!particles_list[l])
1558 		{
1559 #ifdef EXTRA_DEBUG
1560 			ERR();
1561 #endif
1562 			continue;
1563 		}
1564 		if (particles_list[l]->ttl > 0) continue;
1565 
1566 		switch (particles_list[l]->def->part_sys_type)
1567 		{
1568 			case TELEPORTER_PARTICLE_SYS:
1569 				update_teleporter_sys(particles_list[l]);
1570 				break;
1571                		case TELEPORT_PARTICLE_SYS:
1572 				update_teleport_sys(particles_list[l]);
1573 				break;
1574 			case BAG_PARTICLE_SYS:
1575 				update_bag_part_sys(particles_list[l]);
1576 				break;
1577 			case BURST_PARTICLE_SYS:
1578 				update_burst_sys(particles_list[l]);
1579 				break;
1580 			case FIRE_PARTICLE_SYS:
1581 				update_fire_sys(particles_list[l]);
1582 				break;
1583 			case FOUNTAIN_PARTICLE_SYS:
1584 				update_fountain_sys(particles_list[l]);
1585 				break;
1586 		}
1587 	}
1588 #else
1589 	for(i=0;i<MAX_PARTICLE_SYSTEMS;i++)
1590 		{
1591 		if(particles_list[i])
1592 			{
1593 #ifdef ELC
1594 			int xdist=x-particles_list[i]->x_pos;
1595 			int ydist=y-particles_list[i]->y_pos;
1596 			// Systems with a TTL need to be updated, even if they are far away
1597 			// Though, if we're using the map editor we always want to update, otherwise the preview int the
1598 			// particles window won't update correctly...
1599 			if(particles_list[i]->ttl<0 && xdist*xdist+ydist*ydist>PART_SYS_VISIBLE_DIST_SQ){
1600 				continue;
1601 			}
1602 #endif
1603 			switch(particles_list[i]->def->part_sys_type)
1604 				{
1605 				case(TELEPORTER_PARTICLE_SYS):
1606 					update_teleporter_sys(particles_list[i]);
1607 					break;
1608                      		case(TELEPORT_PARTICLE_SYS):
1609 					update_teleport_sys(particles_list[i]);
1610 					break;
1611 				case(BAG_PARTICLE_SYS):
1612 					update_bag_part_sys(particles_list[i]);
1613 					break;
1614 				case(BURST_PARTICLE_SYS):
1615 					update_burst_sys(particles_list[i]);
1616 					break;
1617 				case(FIRE_PARTICLE_SYS):
1618 					update_fire_sys(particles_list[i]);
1619 					break;
1620 				case(FOUNTAIN_PARTICLE_SYS):
1621 					update_fountain_sys(particles_list[i]);
1622 					break;
1623 				}
1624 			  if(particles_list[i]->ttl>0)particles_list[i]->ttl--;
1625 			  if(!particles_list[i]->ttl && !particles_list[i]->particle_count)
1626 			  //if there are no more particles to add, and the TTL expired, then kill this evil system
1627 				{
1628 					if(particles_list[i]->def->use_light && lights_list[particles_list[i]->light]) {
1629 						free(lights_list[particles_list[i]->light]);
1630 						lights_list[particles_list[i]->light]=NULL;
1631 					}
1632 					free(particles_list[i]);
1633 					particles_list[i]=0;
1634 				}
1635 
1636 			}
1637 		}
1638 #endif
1639 	UNLOCK_PARTICLES_LIST();
1640 }
1641 
1642 /******************************************************************************
1643  *                        MISC HELPER FUNCTIONS                               *
1644  ******************************************************************************/
1645 #ifdef ELC
add_teleporters_from_list(const Uint8 * teleport_list)1646 void add_teleporters_from_list (const Uint8 *teleport_list)
1647 {
1648 	Uint16 teleporters_no;
1649 	int i;
1650 	int teleport_x,teleport_y,my_offset;
1651 	float x,y,z;
1652 
1653 	teleporters_no=SDL_SwapLE16(*((Uint16 *)(teleport_list)));
1654 	LOCK_PARTICLES_LIST();	//lock it to avoid timing issues
1655 	for(i=0;i<teleporters_no;i++)
1656 		{
1657 			my_offset=i*5+2;
1658 			teleport_x=SDL_SwapLE16(*((Uint16 *)(teleport_list+my_offset)));
1659 			teleport_y=SDL_SwapLE16(*((Uint16 *)(teleport_list+my_offset+2)));
1660 
1661 			//later on, maybe we want to have different visual types
1662 			//now, get the Z position
1663 			if (!get_tile_valid(teleport_x, teleport_y))
1664 			{
1665 				continue;
1666 			}
1667 
1668 			z = get_tile_height(teleport_x, teleport_y);
1669 			//convert from height values to meters
1670 			x=(float)teleport_x/2;
1671 			y=(float)teleport_y/2;
1672 			//center the object
1673 			x=x+0.25f;
1674 			y=y+0.25f;
1675 
1676 #ifndef	MAP_EDITOR
1677 			add_particle_sys ("./particles/teleporter.part", x, y, z, 1);
1678 			add_e3d("./3dobjects/portal1.e3d",x,y,z,0,0,0,1,0,1.0f,1.0f,1.0f, 1);
1679 #else
1680 			add_particle_sys ("./particles/teleporter.part", x, y, z);
1681 			sector_add_3do(add_e3d("./3dobjects/portal1.e3d",x,y,z,0,0,0,1,0,1.0f,1.0f,1.0f));
1682 #endif
1683 
1684 			//mark the teleporter as an unwalkable so that the pathfinder
1685 			//won't try to plot a path through it
1686 #ifdef MAP_EDITOR
1687 #elif defined(MAP_EDITOR2)
1688 #else
1689 			pf_tile_map[teleport_y*tile_map_size_x*6+teleport_x].z = 0;
1690 #endif
1691 		}
1692 	UNLOCK_PARTICLES_LIST();
1693 
1694 }
1695 #endif // ELC
1696 
1697 #ifdef MAP_EDITOR
get_and_set_particle_texture_id(int i)1698 void get_and_set_particle_texture_id (int i)
1699 {
1700 	bind_texture(particle_textures[i]);
1701 }
1702 #endif // MAP_EDITOR
1703