#include #include #ifndef WINDOWS #include #endif #ifdef MAP_EDITOR2 #include "../map_editor2/global.h" #else //MAP_EDITOR2 #ifdef MAP_EDITOR #include "../map_editor/global.h" #else //MAP_EDITOR #include "global.h" #endif //MAP_EDITOR #endif //MAP_EDITOR2 #include "string.h" #ifdef EYE_CANDY #include "eye_candy_wrapper.h" #endif //EYE_CANDY /* NOTE: This file contains implementations of the following, currently unused, and commented functions: * Look at the end of the file. * * void dump_part_sys_info(); */ #define TELEPORTER_PARTICLE_SYS 0 #define TELEPORT_PARTICLE_SYS 1 #define BAG_PARTICLE_SYS 2 #define BURST_PARTICLE_SYS 3 #define FIRE_PARTICLE_SYS 4 #define FOUNTAIN_PARTICLE_SYS 5 #define PARTICLE_RANDOM(min,max) (min+(max-min)*(rand()/(float)RAND_MAX)) #define PARTICLE_RANDOM2(min,max) (min+0.5*(max-min)+0.5*(max-min)/(float)((rand()%200)-100+0.5)) #define PART_SYS_VISIBLE_DIST_SQ 20*20 #ifdef ELC int use_point_particles = 1; #else int use_point_particles = 0; #endif int particles_percentage=100; int enable_blood = 0; SDL_mutex *particles_list_mutex; //used for locking between the timer and main threads int particle_textures[MAX_PARTICLE_TEXTURES]; particle_sys *particles_list[MAX_PARTICLE_SYSTEMS]; /****************************************************** * PARTICLE SYSTEM DEFINITIONS * ******************************************************/ #define MAX_PARTICLE_DEFS 500 particle_sys_def *defs_list[MAX_PARTICLE_DEFS]; void destroy_all_particle_defs(); int part_strcmp(char * s1, char *s2) { while(*s1 && *s2) { if(*s1!=*s2 && (*s1!='/' && *s1!='\\' && *s2!='/' && *s2!='\\' )) return 1; s1++;s2++; } return *s1!=*s2; } // Grum: perhaps the addition of a sound definition to the files would warrant // a version number update (from 2 to 3), but it'll still work with v. 2 system // (without sound, of course), so I'll leave it #define PARTICLE_DEF_VERSION 2 particle_sys_def *load_particle_def(const char *filename) { int version=0,i; char cleanpath[128]; FILE *f=NULL; particle_sys_def *def=NULL; clean_file_name(cleanpath,filename,128); //Check if it's already loaded for(i=0;ifile_name)) return defs_list[i]; //Check if we have a free slot for it for(i=0;isound_nr = -1; fscanf(f,"%i\n",&version); if(version!=PARTICLE_DEF_VERSION) { LOG_ERROR(particles_filever_wrong,filename,version,PARTICLE_DEF_VERSION); fclose(f); return NULL; } #ifndef WINDOWS setlocale(LC_NUMERIC,"en_US"); #endif // System info safe_snprintf(def->file_name, sizeof(def->file_name), "%s", filename); fscanf(f,"%i\n",&def->part_sys_type); fscanf(f,"%x,%x\n",&def->sblend,&def->dblend); fscanf(f,"%i\n",&def->total_particle_no); def->total_particle_no*=(float)particles_percentage/100.0; fscanf(f,"%i\n",&def->ttl); fscanf(f,"%i\n",&def->part_texture); fscanf(f,"%f\n",&def->part_size); fscanf(f,"%i\n",&def->random_func); // Particle creation info fscanf(f,"%f,%f,%f\n",&def->minx,&def->miny,&def->minz); fscanf(f,"%f,%f,%f\n",&def->maxx,&def->maxy,&def->maxz); fscanf(f,"%f\n",&def->constrain_rad_sq); fscanf(f,"%f,%f,%f\n",&def->vel_minx,&def->vel_miny,&def->vel_minz); fscanf(f,"%f,%f,%f\n",&def->vel_maxx,&def->vel_maxy,&def->vel_maxz); fscanf(f,"%f,%f,%f,%f\n",&def->minr,&def->ming,&def->minb,&def->mina); fscanf(f,"%f,%f,%f,%f\n",&def->maxr,&def->maxg,&def->maxb,&def->maxa); // Particle update info fscanf(f,"%f,%f,%f\n",&def->acc_minx,&def->acc_miny,&def->acc_minz); fscanf(f,"%f,%f,%f\n",&def->acc_maxx,&def->acc_maxy,&def->acc_maxz); fscanf(f,"%f,%f,%f,%f\n", &def->mindr,&def->mindg,&def->mindb,&def->minda); fscanf(f,"%f,%f,%f,%f\n", &def->maxdr,&def->maxdg,&def->maxdb,&def->maxda); fscanf(f,"%i\n",&def->use_light); fscanf(f,"%f,%f,%f\n",&def->lightx,&def->lighty,&def->lightz); fscanf(f,"%f,%f,%f\n",&def->lightr,&def->lightg,&def->lightb); #ifdef NEW_SOUND fscanf (f, "%d\n", &def->sound_nr); #else fscanf (f, "%d,%d,%d\n", &def->sound_nr, &def->positional, &def->loop); #endif //NEW_SOUND if(def->total_particle_no>MAX_PARTICLES) { LOG_ERROR(particle_system_overrun,filename,def->total_particle_no,MAX_PARTICLES); def->total_particle_no=MAX_PARTICLES; } if(def->constrain_rad_sq>0.0) { float rad=sqrt(def->constrain_rad_sq); int fixed=def->minx>rad || def->maxx<-rad || def->miny>rad || def->maxy<-rad; if(def->minx>rad)def->minx=rad-0.1; if(def->maxx<-rad)def->maxx=-rad+0.1; if(def->miny>rad)def->miny=rad-0.1; if(def->maxy<-rad)def->maxy=-rad+0.1; if(def->minx*def->maxx>0.0 || def->miny*def->maxy>0.0) { float dist=def->minx*def->minx+def->miny*def->miny; if(dist>def->constrain_rad_sq) { def->minx*=sqrt(def->constrain_rad_sq/dist)-0.1; def->miny*=sqrt(def->constrain_rad_sq/dist)-0.1; fixed=1; } dist=def->minx*def->minx+def->maxy*def->maxy; if(dist>def->constrain_rad_sq) { def->minx*=sqrt(def->constrain_rad_sq/dist)-0.1; def->maxy*=sqrt(def->constrain_rad_sq/dist)-0.1; fixed=1; } dist=def->maxx*def->maxx+def->maxy*def->maxy; if(dist>def->constrain_rad_sq) { def->maxx*=sqrt(def->constrain_rad_sq/dist)-0.1; def->maxy*=sqrt(def->constrain_rad_sq/dist)-0.1; fixed=1; } dist=def->maxx*def->maxx+def->miny*def->miny; if(dist>def->constrain_rad_sq) { def->maxx*=sqrt(def->constrain_rad_sq/dist)-0.1; def->miny*=sqrt(def->constrain_rad_sq/dist)-0.1; fixed=1; } } if(fixed) { LOG_ERROR(particle_strange_pos,filename); } } fclose(f); return def; } #ifdef NEW_FRUSTUM static __inline__ void calc_particle_random_min_max(float f1, float f2, float* v_min, float* v_max) { if (f1 < f2) { *v_min = f1; *v_max = f2; } else { *v_min = f2; *v_max = f1; } } static __inline__ void calc_particle_random2_min_max(float f1, float f2, float* v_min, float* v_max) { *v_min = (f1+f2)*0.5f-abs(f2-f1); *v_max = (f1+f2)*0.5f+abs(f2-f1); } static __inline__ void calc_bounding_box_for_particle_sys(AABBOX* bbox, particle_sys *system_id) { unsigned int count; float p_max, p_min, p_step, sq; VECTOR3 pv_min, pv_max, pv_v_min, pv_v_max, pv_acc_min, pv_acc_max; sq = sqrt(system_id->def->constrain_rad_sq); if (system_id->def->random_func == 0) { calc_particle_random_min_max(system_id->def->vel_minx, system_id->def->vel_maxx, &p_min, &p_max); pv_v_min[X] = p_min; pv_v_max[X] = p_max; calc_particle_random_min_max(system_id->def->vel_miny, system_id->def->vel_maxy, &p_min, &p_max); pv_v_min[Y] = p_min; pv_v_max[Y] = p_max; calc_particle_random_min_max(system_id->def->vel_minz, system_id->def->vel_maxz, &p_min, &p_max); pv_v_min[Z] = p_min; pv_v_max[Z] = p_max; if (system_id->def->constrain_rad_sq > 0.0f) { pv_min[X] = -sq; pv_min[Y] = -sq; pv_max[X] = sq; pv_max[Y] = sq; } else { calc_particle_random_min_max(system_id->def->minx, system_id->def->maxx, &p_min, &p_max); pv_min[X] = p_min; pv_max[X] = p_max; calc_particle_random_min_max(system_id->def->miny, system_id->def->maxy, &p_min, &p_max); pv_min[Y] = p_min; pv_max[Y] = p_max; } calc_particle_random_min_max(system_id->def->minz, system_id->def->maxz, &p_min, &p_max); pv_min[Z] = p_min; pv_max[Z] = p_max; } else { calc_particle_random2_min_max(system_id->def->vel_minx, system_id->def->vel_maxx, &p_min, &p_max); pv_v_min[X] = p_min; pv_v_max[X] = p_max; calc_particle_random2_min_max(system_id->def->vel_miny, system_id->def->vel_maxy, &p_min, &p_max); pv_v_min[Y] = p_min; pv_v_max[Y] = p_max; calc_particle_random2_min_max(system_id->def->vel_minz, system_id->def->vel_maxz, &p_min, &p_max); pv_v_min[Z] = p_min; pv_v_max[Z] = p_max; if (system_id->def->constrain_rad_sq > 0.0f) { pv_min[X] = -sq; pv_min[Y] = -sq; pv_max[X] = sq; pv_max[Y] = sq; } else { calc_particle_random2_min_max(system_id->def->minx, system_id->def->maxx, &p_min, &p_max); pv_min[X] = p_min; pv_max[X] = p_max; calc_particle_random2_min_max(system_id->def->miny, system_id->def->maxy, &p_min, &p_max); pv_min[Y] = p_min; pv_max[Y] = p_max; } calc_particle_random2_min_max(system_id->def->minz, system_id->def->maxz, &p_min, &p_max); pv_min[Z] = p_min; pv_max[Z] = p_max; } switch (system_id->def->part_sys_type) { case(TELEPORTER_PARTICLE_SYS): case(TELEPORT_PARTICLE_SYS): calc_particle_random2_min_max(system_id->def->acc_minx, system_id->def->acc_maxx, &p_min, &p_max); pv_acc_min[X] = p_min; pv_acc_max[X] = p_max; calc_particle_random2_min_max(system_id->def->acc_miny, system_id->def->acc_maxy, &p_min, &p_max); pv_acc_min[Y] = p_min; pv_acc_max[Y] = p_max; calc_particle_random2_min_max(system_id->def->acc_minz, system_id->def->acc_maxz, &p_min, &p_max); pv_acc_min[Z] = p_min; pv_acc_max[Z] = p_max; p_step = pv_acc_min[Z]+pv_v_min[Z]; count = ceil(2.0f/p_step); bbox->bbmin[X] = min2f(pv_min[X], pv_min[X]+count*(pv_v_min[X]+pv_acc_min[X])); bbox->bbmin[Y] = min2f(pv_min[Y], pv_min[Y]+count*(pv_v_min[Y]+pv_acc_max[X])); bbox->bbmin[Z] = min2f(pv_min[Z], pv_min[Z]+count*(pv_v_min[Z]+pv_acc_min[Y])); bbox->bbmax[X] = max2f(pv_max[X], pv_max[X]+count*(pv_v_max[X]+pv_acc_max[Y])); bbox->bbmax[Y] = max2f(pv_max[Y], pv_max[Y]+count*(pv_v_max[Y]+pv_acc_min[Z])); bbox->bbmax[Z] = max2f(pv_max[Z], pv_max[Z]+count*(pv_v_max[Z]+pv_acc_min[Z])); break; case(BAG_PARTICLE_SYS): calc_particle_random2_min_max(system_id->def->acc_minx, system_id->def->acc_maxx, &p_min, &p_max); pv_acc_min[X] = p_min; pv_acc_max[X] = p_max; calc_particle_random2_min_max(system_id->def->acc_miny, system_id->def->acc_maxy, &p_min, &p_max); pv_acc_min[Y] = p_min; pv_acc_max[Y] = p_max; calc_particle_random2_min_max(system_id->def->acc_minz, system_id->def->acc_maxz, &p_min, &p_max); pv_acc_min[Z] = p_min; pv_acc_max[Z] = p_max; p_step = pv_acc_min[Z]+pv_v_min[Z]; count = ceil(1.0f/p_step); bbox->bbmin[X] = min2f(pv_min[X], pv_min[X]+count*(pv_v_min[X]+pv_acc_min[X])); bbox->bbmin[Y] = min2f(pv_min[Y], pv_min[Y]+count*(pv_v_min[Y]+pv_acc_max[X])); bbox->bbmin[Z] = min2f(pv_min[Z], pv_min[Z]+count*(pv_v_min[Z]+pv_acc_min[Y])); bbox->bbmax[X] = max2f(pv_max[X], pv_max[X]+count*(pv_v_max[X]+pv_acc_max[Y])); bbox->bbmax[Y] = max2f(pv_max[Y], pv_max[Y]+count*(pv_v_max[Y]+pv_acc_min[Z])); bbox->bbmax[Z] = max2f(pv_max[Z], pv_max[Z]+count*(pv_v_max[Z]+pv_acc_min[Z])); break; case(BURST_PARTICLE_SYS): sq *= 3; bbox->bbmin[X] = -sq; bbox->bbmin[Y] = -sq; bbox->bbmin[Z] = -sq; bbox->bbmax[X] = sq; bbox->bbmax[Y] = sq; bbox->bbmax[Z] = sq; break; case(FIRE_PARTICLE_SYS): case(FOUNTAIN_PARTICLE_SYS): calc_particle_random_min_max(system_id->def->acc_minx, system_id->def->acc_maxx, &p_min, &p_max); pv_acc_min[X] = p_min; pv_acc_max[X] = p_max; calc_particle_random_min_max(system_id->def->acc_miny, system_id->def->acc_maxy, &p_min, &p_max); pv_acc_min[Y] = p_min; pv_acc_max[Y] = p_max; calc_particle_random_min_max(system_id->def->acc_minz, system_id->def->acc_maxz, &p_min, &p_max); pv_acc_min[Z] = p_min; pv_acc_max[Z] = p_max; if (system_id->def->random_func == 0) calc_particle_random_min_max(system_id->def->mina, system_id->def->maxa, &p_min, &p_max); else calc_particle_random2_min_max(system_id->def->mina, system_id->def->maxa, &p_min, &p_max); p_step = p_min; calc_particle_random_min_max(system_id->def->minda, system_id->def->maxda, &p_min, &p_max); count = ceil(p_max/(-p_step)); bbox->bbmin[X] = min2f(pv_min[X], pv_min[X]+count*pv_v_min[X]+count*(count+1)*0.5f*pv_acc_min[X]); bbox->bbmin[Y] = min2f(pv_min[Y], pv_min[Y]+count*pv_v_min[Y]+count*(count+1)*0.5f*pv_acc_max[X]); bbox->bbmin[Z] = min2f(pv_min[Z], pv_min[Z]+count*pv_v_min[Z]+count*(count+1)*0.5f*pv_acc_min[Y]); bbox->bbmax[X] = max2f(pv_max[X], pv_max[X]+count*pv_v_max[X]+count*(count+1)*0.5f*pv_acc_max[Y]); bbox->bbmax[Y] = max2f(pv_max[Y], pv_max[Y]+count*pv_v_max[Y]+count*(count+1)*0.5f*pv_acc_min[Z]); bbox->bbmax[Z] = max2f(pv_max[Z], pv_max[Z]+count*pv_v_max[Z]+count*(count+1)*0.5f*pv_acc_min[Z]); break; } bbox->bbmin[X] += system_id->x_pos; bbox->bbmin[Y] += system_id->y_pos; bbox->bbmin[Z] += system_id->z_pos; bbox->bbmax[X] += system_id->x_pos; bbox->bbmax[Y] += system_id->y_pos; bbox->bbmax[Z] += system_id->z_pos; } static __inline__ void destroy_partice_sys_without_lock(int i) { if ((i < 0) || (i >= MAX_PARTICLE_SYSTEMS)) return; if (particles_list[i] == NULL) return; if(particles_list[i]->def && particles_list[i]->def->use_light && lights_list[particles_list[i]->light]) destroy_light(particles_list[i]->light); delete_particle_from_abt(main_bbox_tree, i); free(particles_list[i]); particles_list[i] = NULL; } //void destroy_particle_sys(int i) //{ // LOCK_PARTICLES_LIST(); // destroy_partice_sys_without_lock(i); // UNLOCK_PARTICLES_LIST(); //} #endif #ifdef MAP_EDITOR2 #define MAP_EDITOR #endif #ifdef MAP_EDITOR int save_particle_def(particle_sys_def *def) { char cleanpath[128]; FILE *f=NULL; clean_file_name ( cleanpath, def->file_name, sizeof (cleanpath) ); f=my_fopen(cleanpath,"w"); if(!f) return 0; fprintf(f,"%i\n",PARTICLE_DEF_VERSION); // System info fprintf(f,"%i\n",def->part_sys_type); fprintf(f,"%x,%x\n",def->sblend,def->dblend); fprintf(f,"%i\n",def->total_particle_no); fprintf(f,"%i\n",def->ttl); fprintf(f,"%i\n",def->part_texture); fprintf(f,"%f\n",def->part_size); fprintf(f,"%i\n",def->random_func); // Particle creation info fprintf(f,"%f,%f,%f\n",def->minx,def->miny,def->minz); fprintf(f,"%f,%f,%f\n",def->maxx,def->maxy,def->maxz); fprintf(f,"%f\n",def->constrain_rad_sq); fprintf(f,"%f,%f,%f\n",def->vel_minx,def->vel_miny,def->vel_minz); fprintf(f,"%f,%f,%f\n",def->vel_maxx,def->vel_maxy,def->vel_maxz); fprintf(f,"%f,%f,%f,%f\n",def->minr,def->ming,def->minb,def->mina); fprintf(f,"%f,%f,%f,%f\n",def->maxr,def->maxg,def->maxb,def->maxa); // Particle update info fprintf(f,"%f,%f,%f\n",def->acc_minx,def->acc_miny,def->acc_minz); fprintf(f,"%f,%f,%f\n",def->acc_maxx,def->acc_maxy,def->acc_maxz); fprintf(f,"%f,%f,%f,%f\n",def->mindr,def->mindg,def->mindb,def->minda); fprintf(f,"%f,%f,%f,%f\n",def->maxdr,def->maxdg,def->maxdb,def->maxda); // Particle light info fprintf(f,"%i\n",def->use_light); fprintf(f,"%f,%f,%f\n",def->lightx,def->lighty,def->lightz); fprintf(f,"%f,%f,%f\n",def->lightr,def->lightg,def->lightb); fprintf (f, "%d,%d,%d\n", def->sound_nr, def->positional, def->loop); fclose(f); return 1; } #endif #ifdef MAP_EDITOR2 #undef MAP_EDITOR #endif /******************************************************************* * INITIALIZATION AND CLEANUP FUNCTIONS * *******************************************************************/ //Threading support for particles_list void init_particles_list() { int i; particles_list_mutex=SDL_CreateMutex(); LOCK_PARTICLES_LIST(); //lock it to avoid timing issues for(i=0;idef && particles_list[i]->def->use_light && lights_list[particles_list[i]->light]) { free(lights_list[particles_list[i]->light]); lights_list[particles_list[i]->light]=NULL; } free(particles_list[i]); particles_list[i]=0; #endif } UNLOCK_PARTICLES_LIST(); } void add_fire_at_tile (int kind, Uint16 x_tile, Uint16 y_tile) { float x = 0.5f * x_tile + 0.25f; float y = 0.5f * y_tile + 0.25f; float z = 0.0; switch (kind) { case 2: #ifdef EYE_CANDY ec_create_campfire(x, y, z, (poor_man ? 6 : 10), 3.1); #else // EYE_CANDY #ifdef SFX #ifdef NEW_FRUSTUM add_particle_sys ("./particles/fire_big.part", x, y, z, 1); #else add_particle_sys ("./particles/fire_big.part", x, y, z); #endif // NEW_FRUSTRUM #endif // SFX #endif // EYE_CANDY break; case 1: default: #ifdef EYE_CANDY ec_create_campfire(x, y, z, (poor_man ? 6 : 10), 2.4); #else // EYE_CANDY #ifdef SFX #ifdef NEW_FRUSTUM add_particle_sys ("./particles/fire_small.part", x, y, z, 1); #else add_particle_sys ("./particles/fire_small.part", x, y, z); #endif // NEW_FRUSTRUM #endif // SFX #endif // EYE_CANDY break; } } void remove_fire_at_tile (Uint16 x_tile, Uint16 y_tile) { float x = 0.5f * x_tile + 0.25f; float y = 0.5f * y_tile + 0.25f; #if ! defined SFX || ! defined EYE_CANDY int i; particle_sys *sys; #endif // SFX && EYE_CANDY #ifdef EYE_CANDY ec_delete_effect_loc_type(x, y, EC_CAMPFIRE); #else // EYE_CANDY #ifdef SFX LOCK_PARTICLES_LIST(); for (i = 0; i < MAX_PARTICLE_SYSTEMS; i++) { sys = particles_list[i]; if (particles_list[i] && strncmp (sys->def->file_name, "./particles/fire_", 17) == 0 && sys->x_pos == x && sys->y_pos == y) { #ifdef NEW_FRUSTUM destroy_partice_sys_without_lock(i); #else if (sys->def->use_light && lights_list[sys->light]) { free (lights_list[sys->light]); lights_list[sys->light] = NULL; } #ifndef MAP_EDITOR if (sys->sound != 0) stop_sound (sys->sound); #endif // MAP_EDITOR free (sys); particles_list[i] = NULL; #endif // NEW_FRUSTUM } } UNLOCK_PARTICLES_LIST(); #endif // SFX #endif // EYE_CANDY return; } /********************************************************************* * CREATION OF NEW PARTICLES AND SYSTEMS * *********************************************************************/ #ifdef NEW_FRUSTUM int add_particle_sys (char *file_name, float x_pos, float y_pos, float z_pos, unsigned int dynamic) #else int add_particle_sys (char *file_name, float x_pos, float y_pos, float z_pos) #endif { #if defined EYE_CANDY && ! defined MAP_EDITOR if (use_eye_candy) { if (!strncmp("fou", file_name + 12, 3)) ec_create_fountain(x_pos, y_pos, z_pos + 0.15, (z_pos >= 0.8 ? z_pos - 0.8 : 0.0), 0, 1.0, (poor_man ? 6 : 10)); else if ((use_fancy_smoke) && (!strncmp("smo", file_name + 12, 3))) { if (file_name[17] == '1') ec_create_smoke(x_pos, y_pos, z_pos, 0.3, (poor_man ? 6 : 10)); else if (file_name[17] == '2') ec_create_smoke(x_pos, y_pos, z_pos, 0.45, (poor_man ? 6 : 10)); else if (file_name[17] == '3') ec_create_smoke(x_pos, y_pos, z_pos, 1.6, (poor_man ? 6 : 10)); else if (file_name[17] == '_') ec_create_smoke(x_pos, y_pos, z_pos, 1.1, (poor_man ? 6 : 10)); else ec_create_smoke(x_pos, y_pos, z_pos, 0.5, (poor_man ? 6 : 10)); } else if (!strncmp("tel", file_name + 12, 3)) { if (file_name[21] == 'i') { ec_create_selfmagic_teleport_to_the_portals_room(x_pos, y_pos, z_pos, (poor_man ? 6 : 10)); } else if (file_name[21] == 'o') { ec_create_selfmagic_teleport_to_the_portals_room(x_pos, y_pos, z_pos, (poor_man ? 6 : 10)); } else ec_create_teleporter(x_pos, y_pos, z_pos, (poor_man ? 6 : 10)); } else if (!strncmp("fir", file_name + 12, 3)) { if (!strncmp("big", file_name + 17, 3)) ec_create_campfire(x_pos, y_pos, z_pos, (poor_man ? 6 : 10), 1.5); else if (!strncmp("for", file_name + 17, 3)) ec_create_campfire(x_pos, y_pos - 0.2, z_pos, (poor_man ? 6 : 10), 2.0); else if (!strncmp("min", file_name + 17, 3)) ec_create_campfire(x_pos, y_pos, z_pos, (poor_man ? 6 : 10), 0.4); else if (!strncmp("sma", file_name + 17, 3)) ec_create_campfire(x_pos, y_pos, z_pos, (poor_man ? 6 : 10), 0.6); else if (!strncmp("tor", file_name + 17, 3)) ec_create_lamp(x_pos, y_pos, z_pos, 1.6, (poor_man ? 6 : 10)); else { #ifdef SFX particle_sys_def *def = load_particle_def(file_name); if (!def) return -1; #ifdef NEW_FRUSTUM return create_particle_sys (def, x_pos, y_pos, z_pos, dynamic); #else return create_particle_sys (def, x_pos, y_pos, z_pos); #endif #endif /* SFX */ } } else if (!strncmp("can", file_name + 12, 3)) ec_create_candle(x_pos, y_pos, z_pos, 0.7, (poor_man ? 6 : 10)); else { #endif /* EYE_CANDY */ #ifdef SFX particle_sys_def *def = load_particle_def(file_name); if (!def) return -1; #ifdef NEW_FRUSTUM return create_particle_sys (def, x_pos, y_pos, z_pos, dynamic); #else return create_particle_sys (def, x_pos, y_pos, z_pos); #endif #endif #if defined EYE_CANDY && ! defined MAP_EDITOR } } else { #ifdef SFX particle_sys_def *def = load_particle_def(file_name); if (!def) return -1; #ifdef NEW_FRUSTUM return create_particle_sys (def, x_pos, y_pos, z_pos, dynamic); #else return create_particle_sys (def, x_pos, y_pos, z_pos); #endif #endif } #endif // Lachesis: Quick hack in order to remove compile warning. // // This is not the proper way to hook-in eye candy, because // this function expects to return a particle system id. Additionally, // eye candy is already hooked-in at some of the proper spots -- e.g. // add_fire_at_tile(). Will contact Rei about this. return 0; } #ifdef NEW_FRUSTUM int add_particle_sys_at_tile (char *file_name, int x_tile, int y_tile, unsigned int dynamic) #else int add_particle_sys_at_tile (char *file_name, int x_tile, int y_tile) #endif { int height; //watch for unwalkable tiles getting particles if( (height_map[y_tile*tile_map_size_x*6+x_tile]&0x3F) > 0){ height= height_map[y_tile*tile_map_size_x*6+x_tile]; } else { int count= 0; int x, y; // this is an unwalkable tile, make a guess by averaging nearby heights height= 0; for(x= x_tile-1; x <= x_tile+1; x++){ if(x >= 0 && x < tile_map_size_x*6) for(y= y_tile-1; y <= y_tile+1; y++){ if(y >= 0 && y < tile_map_size_y*6 && (height_map[y*tile_map_size_x*6+x]&0x3F) > 0){ height+= height_map[y*tile_map_size_x*6+x]&0x3F; count++; } } } if(count > 0){ height/= count; } // if that didn't work, lets use a default height if(height <= 0){ height= 8; } } #ifdef NEW_FRUSTUM return add_particle_sys (file_name, (float) x_tile / 2.0 + 0.25f, (float) y_tile / 2.0 + 0.25f, -2.2f + height * 0.2f, dynamic); #else return add_particle_sys (file_name, (float) x_tile / 2.0 + 0.25f, (float) y_tile / 2.0 + 0.25f, -2.2f + height * 0.2f); #endif } void create_particle(particle_sys *sys,particle *result) { particle_sys_def *def=sys->def; if(def->random_func==0) { do { result->x=PARTICLE_RANDOM(def->minx,def->maxx); result->y=PARTICLE_RANDOM(def->miny,def->maxy); result->z=PARTICLE_RANDOM(def->minz,def->maxz); } while(def->constrain_rad_sq>0 && (result->x*result->x+result->y*result->y)>def->constrain_rad_sq); result->vx=PARTICLE_RANDOM(def->vel_minx,def->vel_maxx); result->vy=PARTICLE_RANDOM(def->vel_miny,def->vel_maxy); result->vz=PARTICLE_RANDOM(def->vel_minz,def->vel_maxz); result->r=PARTICLE_RANDOM(def->minr,def->maxr); result->g=PARTICLE_RANDOM(def->ming,def->maxg); result->b=PARTICLE_RANDOM(def->minb,def->maxb); result->a=PARTICLE_RANDOM(def->mina,def->maxa); } else { do { result->x=PARTICLE_RANDOM2(def->minx,def->maxx); result->y=PARTICLE_RANDOM2(def->miny,def->maxy); result->z=PARTICLE_RANDOM2(def->minz,def->maxz); } while(def->constrain_rad_sq>0 && (result->x*result->x+result->y*result->y)>def->constrain_rad_sq); result->vx=PARTICLE_RANDOM2(def->vel_minx,def->vel_maxx); result->vy=PARTICLE_RANDOM2(def->vel_miny,def->vel_maxy); result->vz=PARTICLE_RANDOM2(def->vel_minz,def->vel_maxz); result->r=PARTICLE_RANDOM2(def->minr,def->maxr); result->g=PARTICLE_RANDOM2(def->ming,def->maxg); result->b=PARTICLE_RANDOM2(def->minb,def->maxb); result->a=PARTICLE_RANDOM2(def->mina,def->maxa); } result->x+=sys->x_pos; result->y+=sys->y_pos; result->z+=sys->z_pos; result->free=0; } #ifdef NEW_FRUSTUM int create_particle_sys (particle_sys_def *def, float x, float y, float z, unsigned int dynamic) #else int create_particle_sys (particle_sys_def *def, float x, float y, float z) #endif { int i,psys; particle_sys *system_id; particle *p; #ifdef NEW_FRUSTUM AABBOX bbox; #endif if(!def)return -1; //allocate memory for this particle system system_id=(particle_sys *)calloc(1,sizeof(particle_sys)); LOCK_PARTICLES_LIST(); //now, find a place for this system for(psys=0;psysx_pos=x; system_id->y_pos=y; system_id->z_pos=z; system_id->def=def; system_id->particle_count=def->total_particle_no; system_id->ttl=def->ttl; if(def->use_light) { #ifdef NEW_FRUSTUM #ifdef MAP_EDITOR system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f,1, dynamic); #elif defined(MAP_EDITOR2) system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f,1, dynamic); #else system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f, dynamic); #endif #else #ifdef MAP_EDITOR system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f,1); #elif defined(MAP_EDITOR2) system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f,1); #else system_id->light=add_light(def->lightx+x, def->lighty+y, def->lightz+z, def->lightr, def->lightg, def->lightb,1.0f); #endif #endif } for(i=0,p=&system_id->particles[0];itotal_particle_no;i++,p++)create_particle(system_id,p); #ifndef MAP_EDITOR if (def->sound_nr < 0 || !sound_on) system_id->sound = 0; else #ifdef NEW_SOUND system_id->sound = add_sound_object (def->sound_nr, (int)(x+x-0.5), (int)(y+y-0.5)); #else system_id->sound = add_sound_object (def->sound_nr, (int)(x+x-0.5), (int)(y+y-0.5), def->positional, def->loop); #endif #endif #ifdef NEW_FRUSTUM calc_bounding_box_for_particle_sys(&bbox, system_id); if ((main_bbox_tree_items != NULL) && (dynamic == 0)) add_particle_sys_to_list(main_bbox_tree_items, psys, bbox, def->sblend, def->dblend); else add_particle_to_abt(main_bbox_tree, psys, bbox, def->sblend, def->dblend, dynamic); #endif UNLOCK_PARTICLES_LIST(); return psys; } /********************************************************************** * RENDERING FUNCTIONS * **********************************************************************/ void draw_text_particle_sys(particle_sys *system_id) { float x_pos,y_pos,z_pos; int i; float z_len=0.065f*system_id->def->part_size; float x_len=z_len*cos(-rz*M_PI/180.0); float y_len=z_len*sin(-rz*M_PI/180.0); particle *p; LOCK_PARTICLES_LIST(); //lock it to avoid timing issues x_pos=system_id->x_pos; y_pos=system_id->y_pos; z_pos=system_id->z_pos; CHECK_GL_ERRORS(); get_and_set_texture_id(particle_textures[system_id->def->part_texture]); for(i=0,p=&system_id->particles[0];idef->total_particle_no;i=i+5,p=p+5) { if(!p->free) { glPushMatrix(); glTranslatef(p->x,p->y,p->z); glBegin(GL_TRIANGLE_STRIP); glColor4f(p->r,p->g,p->b,p->a); glTexCoord2f(0.0f,1.0f); glVertex3f(-x_len,-y_len,+z_len); glTexCoord2f(0.0f,0.0f); glVertex3f(-x_len,-y_len,-z_len); glTexCoord2f(1.0f,1.0f); glVertex3f(x_len,y_len,+z_len); glTexCoord2f(1.0f,0.0f); glVertex3f(x_len,y_len,-z_len); glEnd(); glPopMatrix(); } } UNLOCK_PARTICLES_LIST(); // release now that we are done CHECK_GL_ERRORS(); } void draw_point_particle_sys(particle_sys *system_id) { #ifdef ELC int i; particle *p; CHECK_GL_ERRORS(); glEnable(GL_POINT_SPRITE_NV); glTexEnvf(GL_POINT_SPRITE_NV,GL_COORD_REPLACE_NV,GL_TRUE); glPointSize(system_id->def->part_size*(5.5f-zoom_level)*4.4f); get_and_set_texture_id(particle_textures[system_id->def->part_texture]); #if 0 //#ifdef USE_VERTEX_ARRAYS // This might be useful if we allow more particles per system. // It does, however, render free particles... if(use_vertex_array) { glEnableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_COLOR_ARRAY); LOCK_PARTICLES_LIST(); //lock it to avoid timing issues glVertexPointer(3,GL_FLOAT,sizeof(particle),&(system_id->particles[0].x)); glColorPointer(4,GL_FLOAT,sizeof(particle),&(system_id->particles[0].r)); glDrawArrays(GL_POINTS,0,system_id->total_particle_no); UNLOCK_PARTICLES_LIST();// release now that we are done glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); } else #endif { glBegin(GL_POINTS); LOCK_PARTICLES_LIST(); //lock it to avoid timing issues for(i=0,p=&system_id->particles[0];idef->total_particle_no;i++,p++) { if(!p->free) { glColor4f(p->r,p->g,p->b,p->a); glVertex3f(p->x,p->y,p->z); } } UNLOCK_PARTICLES_LIST(); // release now that we are done glEnd(); } glDisable(GL_POINT_SPRITE_NV); CHECK_GL_ERRORS(); #endif } #ifndef ELC int have_point_sprite=0; #endif void display_particles() { #ifndef NEW_FRUSTUM int i; #endif int x,y; GLenum sblend=GL_SRC_ALPHA,dblend=GL_ONE; #ifdef NEW_FRUSTUM unsigned int i, l, start, stop; #endif if(!particles_percentage) return; x=-camera_x; y=-camera_y; CHECK_GL_ERRORS(); glPushAttrib(GL_ENABLE_BIT|GL_DEPTH_BUFFER_BIT); glDepthMask(GL_FALSE); glEnable(GL_BLEND); glEnable(GL_CULL_FACE); glDisable(GL_LIGHTING); glBlendFunc(sblend,dblend); LOCK_PARTICLES_LIST(); // Perhaps we should have a depth sort here..? #ifdef NEW_FRUSTUM get_intersect_start_stop(main_bbox_tree, TYPE_PARTICLE_SYSTEM, &start, &stop); for (i = start; i < stop; i++) { l = get_intersect_item_ID(main_bbox_tree, i); if (!particles_list[l]) { #ifdef EXTRA_DEBUG ERR(); #endif continue; } #ifdef SIMPLE_LOD // last final check for a distance limit 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){ continue; } #endif //SIMPLE_LOD if ((particles_list[l]->def->sblend != sblend) || (particles_list[l]->def->dblend != dblend)) { sblend = particles_list[l]->def->sblend; dblend = particles_list[l]->def->dblend; glBlendFunc(sblend, dblend); } if (use_point_particles) draw_point_particle_sys(particles_list[l]); else draw_text_particle_sys(particles_list[l]); } #else //NEW_FRUSTUM for(i=0;ix_pos; dist2=y-particles_list[i]->y_pos; if(dist1*dist1+dist2*dist2<=PART_SYS_VISIBLE_DIST_SQ) { if(particles_list[i]->def->sblend!=sblend || particles_list[i]->def->dblend!=dblend) { sblend=particles_list[i]->def->sblend; dblend=particles_list[i]->def->dblend; glBlendFunc(sblend,dblend); } if(use_point_particles) { draw_point_particle_sys(particles_list[i]); } else { draw_text_particle_sys(particles_list[i]); } } } } #endif //NEW_FRUSTUM UNLOCK_PARTICLES_LIST(); glDisable(GL_CULL_FACE); //Intel fix glPopAttrib(); CHECK_GL_ERRORS(); } /****************************************************************************** * UPDATE FUNCTIONS * ******************************************************************************/ void update_fountain_sys(particle_sys *system_id) { int i,j; int total_particle_no; int particles_to_add=0; particle *p; total_particle_no=system_id->def->total_particle_no; //see if we need to add new particles LOCK_PARTICLES_LIST(); if(system_id->ttl) particles_to_add=total_particle_no-system_id->particle_count; if(particles_to_add) { for(j=i=0;iparticles[j].free) { create_particle(system_id,&(system_id->particles[j])); system_id->particle_count++; break; } } } } //excellent, now we have to actually update the particles //find used particles for(j=0,p=&system_id->particles[0];jfree) { if(p->a<0.0f) { //poor particle, it died :( p->free=1; if(system_id->particle_count)system_id->particle_count--; continue; } if(p->z<0.0f) { p->z=0.001f; p->vz=-p->vz; } p->x+=p->vx; p->y+=p->vy; p->z+=p->vz; p->vx+=PARTICLE_RANDOM(system_id->def->acc_minx,system_id->def->acc_maxx); p->vy+=PARTICLE_RANDOM(system_id->def->acc_miny,system_id->def->acc_maxy); p->vz+=PARTICLE_RANDOM(system_id->def->acc_minz,system_id->def->acc_maxz); p->r+=PARTICLE_RANDOM(system_id->def->mindr,system_id->def->maxdr); p->g+=PARTICLE_RANDOM(system_id->def->mindg,system_id->def->maxdg); p->b+=PARTICLE_RANDOM(system_id->def->mindb,system_id->def->maxdb); p->a+=PARTICLE_RANDOM(system_id->def->minda,system_id->def->maxda); } } UNLOCK_PARTICLES_LIST(); } void update_burst_sys(particle_sys *system_id) { int j; int total_particle_no; particle *p; total_particle_no=system_id->def->total_particle_no; LOCK_PARTICLES_LIST(); //find used particles for(j=0,p=&system_id->particles[0];jfree) { float distx=p->x-system_id->x_pos; float disty=p->y-system_id->y_pos; float distz=p->z-system_id->z_pos; float dist_sq=distx*distx+disty*disty+distz*distz; if(dist_sq>system_id->def->constrain_rad_sq*9.0 || dist_sq<0.01) { //poor particle, it died :( p->free=1; if(system_id->particle_count)system_id->particle_count--; continue; } if(p->vx>-0.01 && p->vx<0.01 && p->vy>-0.01 && p->vy<0.01 && p->vz>-0.01 && p->vz<0.01) { float len=0.25/sqrt(dist_sq); p->vx=distx*len; p->vy=disty*len; p->vz=distz*len; } p->x+=p->vx; p->y+=p->vy; p->z+=p->vz; p->r+=PARTICLE_RANDOM(system_id->def->mindr,system_id->def->maxdr); p->g+=PARTICLE_RANDOM(system_id->def->mindg,system_id->def->maxdg); p->b+=PARTICLE_RANDOM(system_id->def->mindb,system_id->def->maxdb); p->a+=PARTICLE_RANDOM(system_id->def->minda,system_id->def->maxda); } } UNLOCK_PARTICLES_LIST(); } void update_fire_sys(particle_sys *system_id) { int i; int particles_to_add=0; int total_particle_no=system_id->def->total_particle_no; particle *p; int j; //see if we need to add new particles LOCK_PARTICLES_LIST(); if(system_id->ttl) particles_to_add=total_particle_no-system_id->particle_count; for(j=i=0;iparticles[j].free) { //finally, we found a spot create_particle(system_id,&(system_id->particles[j])); //increase the particle count system_id->particle_count++; j++; break; //done looping } } //excellent, now we have to actually update the particles //find a used particle for(j=0,p=&system_id->particles[0];jfree) { if(p->a<0.0f) { //poor particle, it died :( p->free=1; if(system_id->particle_count)system_id->particle_count--; continue; } // Fires don't use acceleration as usual... p->x+=p->vx+PARTICLE_RANDOM(system_id->def->acc_minx,system_id->def->acc_maxx); p->y+=p->vy+PARTICLE_RANDOM(system_id->def->acc_miny,system_id->def->acc_maxy); p->z+=p->vz+PARTICLE_RANDOM(system_id->def->acc_minz,system_id->def->acc_maxz); p->r+=PARTICLE_RANDOM(system_id->def->mindr,system_id->def->maxdr); p->g+=PARTICLE_RANDOM(system_id->def->mindg,system_id->def->maxdg); p->b+=PARTICLE_RANDOM(system_id->def->mindb,system_id->def->maxdb); p->a+=PARTICLE_RANDOM(system_id->def->minda,system_id->def->maxda); } UNLOCK_PARTICLES_LIST(); } void update_teleporter_sys(particle_sys *system_id) { int i; int particles_to_add=0; int total_particle_no=system_id->def->total_particle_no; particle *p; int j; //see if we need to add new particles LOCK_PARTICLES_LIST(); if(system_id->ttl) particles_to_add=total_particle_no-system_id->particle_count; for(j=i=0;iparticles[j].free) { //finally, we found a spot create_particle(system_id,&(system_id->particles[j])); if(system_id->particles[j].zz_pos)system_id->particles[j].z=system_id->z_pos; //increase the particle count system_id->particle_count++; break; //done looping } } //excellent, now we have to actually update the particles //find used particles for(j=0,p=&system_id->particles[0];jfree) { if(p->z>system_id->z_pos+2.0f) { //poor particle, it died :( p->free=1; if(system_id->particle_count)system_id->particle_count--; continue; } // Teleporters don't use acceleration as usual... p->x+=p->vx+PARTICLE_RANDOM2(system_id->def->acc_minx,system_id->def->acc_maxx); p->y+=p->vy+PARTICLE_RANDOM2(system_id->def->acc_miny,system_id->def->acc_maxy); p->z+=p->vz+PARTICLE_RANDOM2(system_id->def->acc_minz,system_id->def->acc_maxz); p->r+=PARTICLE_RANDOM2(system_id->def->mindr,system_id->def->maxdr); p->g+=PARTICLE_RANDOM2(system_id->def->mindg,system_id->def->maxdg); p->b+=PARTICLE_RANDOM2(system_id->def->mindb,system_id->def->maxdb); p->a+=PARTICLE_RANDOM2(system_id->def->minda,system_id->def->maxda); } UNLOCK_PARTICLES_LIST(); } void update_teleport_sys(particle_sys *system_id) { int i; int total_particle_no=system_id->def->total_particle_no; int particles_to_add=0; particle *p; int j; //see if we need to add new particles LOCK_PARTICLES_LIST(); if(system_id->ttl) particles_to_add=total_particle_no-system_id->particle_count; for(j=i=0;iparticles[j].free) { create_particle(system_id,&(system_id->particles[j])); system_id->particles[j].x=system_id->x_pos; system_id->particles[j].y=system_id->y_pos; system_id->particles[j].z=system_id->z_pos; system_id->particle_count++; break; } } //excellent, now we have to actually update the particles //find used particles for(j=0,p=&system_id->particles[0];jfree) { if(p->z>system_id->z_pos+2.0f) { //poor particle, it died :( p->free=1; if(system_id->particle_count)system_id->particle_count--; continue; } // Teleports don't use acceleration as usual... p->x+=p->vx+PARTICLE_RANDOM2(system_id->def->acc_minx,system_id->def->acc_maxx); p->y+=p->vy+PARTICLE_RANDOM2(system_id->def->acc_miny,system_id->def->acc_maxy); p->z+=p->vz+PARTICLE_RANDOM2(system_id->def->acc_minz,system_id->def->acc_maxz); p->r+=PARTICLE_RANDOM2(system_id->def->mindr,system_id->def->maxdr); p->g+=PARTICLE_RANDOM2(system_id->def->mindg,system_id->def->maxdg); p->b+=PARTICLE_RANDOM2(system_id->def->mindb,system_id->def->maxdb); p->a+=PARTICLE_RANDOM2(system_id->def->minda,system_id->def->maxda); } UNLOCK_PARTICLES_LIST(); } void update_bag_part_sys(particle_sys *system_id) { int i; int total_particle_no=system_id->def->total_particle_no; int particles_to_add=0; particle *p; int j; //see if we need to add new particles LOCK_PARTICLES_LIST(); if(system_id->ttl) particles_to_add=total_particle_no-system_id->particle_count; for(j=i=0;iparticles[j].free) { //finally, we found a spot create_particle(system_id,&(system_id->particles[j])); if(system_id->particles[j].zz_pos)system_id->particles[j].z=system_id->z_pos; //increase the particle count system_id->particle_count++; break; //done looping } } //excellent, now we have to actually update the particles //find used particles for(j=0,p=&system_id->particles[0];jfree) { if(p->z>system_id->z_pos+1.0f) { //poor particle, it died :( p->free=1; if(system_id->particle_count)system_id->particle_count--; continue; } // Bags don't use acceleration as usual... p->x+=p->vx+PARTICLE_RANDOM2(system_id->def->acc_minx,system_id->def->acc_maxx); p->y+=p->vy+PARTICLE_RANDOM2(system_id->def->acc_miny,system_id->def->acc_maxy); p->z+=p->vz+PARTICLE_RANDOM2(system_id->def->acc_minz,system_id->def->acc_maxz); p->r+=PARTICLE_RANDOM2(system_id->def->mindr,system_id->def->maxdr); p->g+=PARTICLE_RANDOM2(system_id->def->mindg,system_id->def->maxdg); p->b+=PARTICLE_RANDOM2(system_id->def->mindb,system_id->def->maxdb); p->a+=PARTICLE_RANDOM2(system_id->def->minda,system_id->def->maxda); } UNLOCK_PARTICLES_LIST(); } void update_particles() { #ifdef NEW_FRUSTUM unsigned int i, l, start, stop; #else int i; #ifdef ELC int x = -camera_x, y = -camera_y; #endif #endif if(!particles_percentage){ return; } LOCK_PARTICLES_LIST(); #ifdef NEW_FRUSTUM for (i = 0; i < MAX_PARTICLE_SYSTEMS; i++) { if (particles_list[i]) { // Systems with a TTL need to be updated, even if they are far away if (particles_list[i]->ttl < 0) continue; switch (particles_list[i]->def->part_sys_type) { case TELEPORTER_PARTICLE_SYS: update_teleporter_sys(particles_list[i]); break; case TELEPORT_PARTICLE_SYS: update_teleport_sys(particles_list[i]); break; case BAG_PARTICLE_SYS: update_bag_part_sys(particles_list[i]); break; case BURST_PARTICLE_SYS: update_burst_sys(particles_list[i]); break; case FIRE_PARTICLE_SYS: update_fire_sys(particles_list[i]); break; case FOUNTAIN_PARTICLE_SYS: update_fountain_sys(particles_list[i]); break; } if (particles_list[i]->ttl > 0) particles_list[i]->ttl--; //if there are no more particles to add, and the TTL expired, then kill this evil system if (!particles_list[i]->ttl && !particles_list[i]->particle_count) destroy_partice_sys_without_lock(i); } } get_intersect_start_stop(main_bbox_tree, TYPE_PARTICLE_SYSTEM, &start, &stop); for (i = start; i < stop; i++) { l = get_intersect_item_ID(main_bbox_tree, i); if (!particles_list[l]) { #ifdef EXTRA_DEBUG ERR(); #endif continue; } if (particles_list[l]->ttl > 0) continue; switch (particles_list[l]->def->part_sys_type) { case TELEPORTER_PARTICLE_SYS: update_teleporter_sys(particles_list[l]); break; case TELEPORT_PARTICLE_SYS: update_teleport_sys(particles_list[l]); break; case BAG_PARTICLE_SYS: update_bag_part_sys(particles_list[l]); break; case BURST_PARTICLE_SYS: update_burst_sys(particles_list[l]); break; case FIRE_PARTICLE_SYS: update_fire_sys(particles_list[l]); break; case FOUNTAIN_PARTICLE_SYS: update_fountain_sys(particles_list[l]); break; } } #else for(i=0;ix_pos; int ydist=y-particles_list[i]->y_pos; // Systems with a TTL need to be updated, even if they are far away // Though, if we're using the map editor we always want to update, otherwise the preview int the // particles window won't update correctly... if(particles_list[i]->ttl<0 && xdist*xdist+ydist*ydist>PART_SYS_VISIBLE_DIST_SQ){ continue; } #endif switch(particles_list[i]->def->part_sys_type) { case(TELEPORTER_PARTICLE_SYS): update_teleporter_sys(particles_list[i]); break; case(TELEPORT_PARTICLE_SYS): update_teleport_sys(particles_list[i]); break; case(BAG_PARTICLE_SYS): update_bag_part_sys(particles_list[i]); break; case(BURST_PARTICLE_SYS): update_burst_sys(particles_list[i]); break; case(FIRE_PARTICLE_SYS): update_fire_sys(particles_list[i]); break; case(FOUNTAIN_PARTICLE_SYS): update_fountain_sys(particles_list[i]); break; } if(particles_list[i]->ttl>0)particles_list[i]->ttl--; if(!particles_list[i]->ttl && !particles_list[i]->particle_count) //if there are no more particles to add, and the TTL expired, then kill this evil system { if(particles_list[i]->def->use_light && lights_list[particles_list[i]->light]) { free(lights_list[particles_list[i]->light]); lights_list[particles_list[i]->light]=NULL; } free(particles_list[i]); particles_list[i]=0; } } } #endif UNLOCK_PARTICLES_LIST(); } /****************************************************************************** * MISC HELPER FUNCTIONS * ******************************************************************************/ #ifdef ELC void add_teleporters_from_list (const Uint8 *teleport_list) { Uint16 teleporters_no; int i; int teleport_x,teleport_y,teleport_type,my_offset; float x,y,z; teleporters_no=SDL_SwapLE16(*((Uint16 *)(teleport_list))); LOCK_PARTICLES_LIST(); //lock it to avoid timing issues for(i=0;ifile_name); } safe_snprintf(str, sizeof(str), "#%s: %i",my_tolower(definitions_str),partdefs); LOG_TO_CONSOLE(c_grey1,str); for(i=0;i