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