home *** CD-ROM | disk | FTP | other *** search
- // particle.c
-
- // Egoboo, Copyright (C) 2000 Aaron Bishop
-
- #include "egoboo.h"
-
- //--------------------------------------------------------------------------------------------
- void make_prtlist(void)
- {
- // ZZ> This function figures out which particles are visible, and it sets up dynamic
- // lighting
- int cnt, tnc, disx, disy, distance, slot;
-
-
- // Don't really make a list, just set to visible or not
- numdynalight = 0;
- dynadistancetobeat = MAXDYNADIST;
- cnt = 0;
- while(cnt < MAXPRT)
- {
- prtinview[cnt] = FALSE;
- if(prton[cnt])
- {
- prtinview[cnt] = meshinrenderlist[prtonwhichfan[cnt]];
- // Set up the lights we need
- if(prtdynalighton[cnt])
- {
- disx = prtxpos[cnt]-camtrackx;
- disx = ABS(disx);
- disy = prtypos[cnt]-camtracky;
- disy = ABS(disy);
- distance = disx+disy;
- if(distance < dynadistancetobeat)
- {
- if(numdynalight < MAXDYNA)
- {
- // Just add the light
- slot = numdynalight;
- dynadistance[slot] = distance;
- numdynalight++;
- }
- else
- {
- // Overwrite the worst one
- slot = 0;
- tnc = 1;
- dynadistancetobeat = dynadistance[0];
- while(tnc < MAXDYNA)
- {
- if(dynadistance[tnc] > dynadistancetobeat)
- {
- slot = tnc;
- }
- tnc++;
- }
- dynadistance[slot] = distance;
-
-
- // Find the new distance to beat
- tnc = 1;
- dynadistancetobeat = dynadistance[0];
- while(tnc < MAXDYNA)
- {
- if(dynadistance[tnc] > dynadistancetobeat)
- {
- dynadistancetobeat = dynadistance[tnc];
- }
- tnc++;
- }
- }
- dynalightlistx[slot] = prtxpos[cnt];
- dynalightlisty[slot] = prtypos[cnt];
- dynalightlevel[slot] = prtdynalightlevel[cnt];
- dynalightfalloff[slot] = prtdynalightfalloff[cnt];
- }
- }
- }
- cnt++;
- }
- }
-
- //--------------------------------------------------------------------------------------------
- void free_one_particle_no_sound(int particle)
- {
- // ZZ> This function sticks a particle back on the free particle stack
- freeprtlist[numfreeprt]=particle;
- numfreeprt++;
- prton[particle]=FALSE;
- }
-
- //--------------------------------------------------------------------------------------------
- void play_particle_sound(int particle, signed char sound)
- {
- // ZZ> This function plays a sound effect for a particle
- int distance, volume, frequency;
-
- frequency = FRQRANDOM;
- if(sound!=-1)
- {
- distance = ABS(camtrackx-prtxpos[particle])+ABS(camtracky-prtypos[particle]);
- volume = -distance;
- volume = volume<<VOLSHIFT;
- if(volume > VOLMIN)
- {
- if(prtmodel[particle]!=MAXMODEL)
- {
- // Local sound
-
- play_sound_pvf(capwaveindex[prtmodel[particle]][sound], PANMID, volume, frequency);
-
- }
- else
- {
- // Global sound ( for coins )
-
- play_sound_pvf(sound, PANMID, volume, frequency);
- }
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------
- void free_one_particle(int particle)
- {
- // ZZ> This function sticks a particle back on the free particle stack and
- // plays the sound associated with the particle
- int child;
- if(prtspawncharacterstate[particle] != SPAWNNOCHARACTER)
- {
- child = spawn_one_character(prtxpos[particle], prtypos[particle], prtzpos[particle],
- prtmodel[particle], prtteam[particle], 0, prtfacing[particle],
- NULL, MAXCHR);
- if(child != MAXCHR)
- {
- chraistate[child] = prtspawncharacterstate[particle];
- chraiowner[child] = prtchr[particle];
- }
- }
- play_particle_sound(particle, pipsoundend[prtpip[particle]]);
- freeprtlist[numfreeprt]=particle;
- numfreeprt++;
- prton[particle]=FALSE;
- }
-
- //--------------------------------------------------------------------------------------------
- int get_free_particle(int force)
- {
- // ZZ> This function gets an unused particle. If all particles are in use
- // and force is set, it grabs the first unimportant one. The particle
- // index is the return value
- int particle;
-
-
- // Return MAXPRT if we can't find one
- particle = MAXPRT;
- if(numfreeprt==0)
- {
- if(force)
- {
- // Gotta find one, so go through the list
- particle = 0;
- while(particle<MAXPRT)
- {
- if(prtbumpsize[particle]==0)
- {
- // Found one
- return particle;
- }
- particle++;
- }
- }
- }
- else
- {
- if(force || numfreeprt > (MAXPRT/4))
- {
- // Just grab the next one
- numfreeprt--;
- particle=freeprtlist[numfreeprt];
- }
- }
- return particle;
- }
-
- //--------------------------------------------------------------------------------------------
- unsigned short spawn_one_particle(float x, float y, float z,
- unsigned short facing, unsigned short model, unsigned short pip,
- unsigned short characterattach, unsigned short grip, unsigned char team,
- unsigned short characterorigin, unsigned short multispawn, unsigned short oldtarget)
- {
- // ZZ> This function spawns a new particle, and returns the number of that particle
- int cnt, velocity;
- float xvel, yvel, zvel, tvel;
- int offsetfacing, newrand;
-
-
- // Convert from local pip to global pip
- if(model<MAXMODEL)
- pip = madprtpip[model][pip];
-
-
- cnt = get_free_particle(pipforce[pip]);
- if(cnt != MAXPRT)
- {
- // Necessary data for any part
- prton[cnt] = TRUE;
- prtpip[cnt] = pip;
- prtmodel[cnt] = model;
- prtinview[cnt] = FALSE;
- prtlevel[cnt] = 0;
- prtteam[cnt] = team;
- prtchr[cnt] = characterorigin;
- prtdamagetype[cnt] = pipdamagetype[pip];
- prtspawncharacterstate[cnt] = SPAWNNOCHARACTER;
-
-
- // Lighting and sound
- prtdynalighton[cnt] = FALSE;
- if(multispawn == 0)
- {
- prtdynalighton[cnt] = pipdynalightmode[pip];
- if(pipdynalightmode[pip]==DYNALOCAL)
- {
- prtdynalighton[cnt] = FALSE;
- if(chrteam[characterorigin] == rtslocalteam)
- {
- prtdynalighton[cnt] = TRUE;
- }
- }
- }
- prtdynalightlevel[cnt] = pipdynalevel[pip];
- prtdynalightfalloff[cnt] = pipdynafalloff[pip];
-
-
-
- // Set character attachments ( characterattach==MAXCHR means none )
- prtattachedtocharacter[cnt] = characterattach;
- prtgrip[cnt] = grip;
-
-
-
- // Correct facing
- facing += pipfacingbase[pip];
-
-
- // Targeting...
- zvel = 0;
- newrand = RANDIE;
- z = z+pipzspacingbase[pip]+(newrand&pipzspacingrand[pip])-(pipzspacingrand[pip]>>1);
- newrand = RANDIE;
- velocity = (pipxyvelbase[pip]+(newrand&pipxyvelrand[pip]));
- prttarget[cnt] = oldtarget;
- if(pipnewtargetonspawn[pip])
- {
- if(piptargetcaster[pip])
- {
- // Set the target to the caster
- prttarget[cnt] = characterorigin;
- }
- else
- {
- // Find a target
- prttarget[cnt] = find_target(x, y, facing, piptargetangle[pip], piponlydamagefriendly[pip], FALSE, team, characterorigin, oldtarget);
- if(prttarget[cnt] != MAXCHR && piphoming[pip] == FALSE)
- {
- facing = facing-glouseangle;
- }
- // Correct facing for dexterity...
- offsetfacing = 0;
- if(chrdexterity[characterorigin]<PERFECTSTAT)
- {
- // Correct facing for randomness
- offsetfacing = RANDIE;
- offsetfacing = offsetfacing & pipfacingrand[pip];
- offsetfacing -= (pipfacingrand[pip]>>1);
- offsetfacing = (offsetfacing*(PERFECTSTAT-chrdexterity[characterorigin]))>>13; // Divided by PERFECTSTAT
- }
- if(prttarget[cnt] != MAXCHR && pipzaimspd[pip]!=0)
- {
- // These aren't velocities... This is to do aiming on the Z axis
- if(velocity > 0)
- {
- xvel = chrxpos[prttarget[cnt]]-x;
- yvel = chrypos[prttarget[cnt]]-y;
- tvel = sqrt(xvel*xvel+yvel*yvel)/velocity; // This is the number of steps...
- if(tvel > 0)
- {
- zvel = (chrzpos[prttarget[cnt]]+(chrbumpsize[prttarget[cnt]]>>1)-z)/tvel; // This is the zvel alteration
- if(zvel < -(pipzaimspd[pip]>>1)) zvel = -(pipzaimspd[pip]>>1);
- if(zvel > pipzaimspd[pip]) zvel = pipzaimspd[pip];
- }
- }
- }
- }
- // Does it go away?
- if(prttarget[cnt]==MAXCHR && pipneedtarget[pip])
- {
- free_one_particle(cnt);
- return MAXPRT;
- }
- // Start on top of target
- if(prttarget[cnt]!=MAXCHR && pipstartontarget[pip])
- {
- x = chrxpos[prttarget[cnt]];
- y = chrypos[prttarget[cnt]];
- }
- }
- else
- {
- // Correct facing for randomness
- offsetfacing = RANDIE;
- offsetfacing = offsetfacing & pipfacingrand[pip];
- offsetfacing -= (pipfacingrand[pip]>>1);
- }
- facing+=offsetfacing;
- prtfacing[cnt] = facing;
- facing = facing>>2;
-
-
- // Location data from arguments
- newrand = RANDIE;
- x = x+turntosin[(facing+12288)&16383]*(pipxyspacingbase[pip]+(newrand&pipxyspacingrand[pip]));
- y = y+turntosin[(facing+8192)&16383]*(pipxyspacingbase[pip]+(newrand&pipxyspacingrand[pip]));
- if(x < 0) x = 0;
- if(x > meshedgex-2) x = meshedgex - 2;
- if(y < 0) y = 0;
- if(y > meshedgey-2) y = meshedgey - 2;
- prtxpos[cnt] = x;
- prtypos[cnt] = y;
- prtzpos[cnt] = z;
-
-
- // Velocity data
- xvel = turntosin[(facing+12288)&16383]*velocity;
- yvel = turntosin[(facing+8192)&16383]*velocity;
- newrand = RANDIE;
- zvel += pipzvelbase[pip]+(newrand&pipzvelrand[pip])-(pipzvelrand[pip]>>1);
- prtxvel[cnt] = xvel;
- prtyvel[cnt] = yvel;
- prtzvel[cnt] = zvel;
-
-
- // Template values
- prtbumpsize[cnt] = pipbumpsize[pip];
- prtbumpsizebig[cnt] = prtbumpsize[cnt]+(prtbumpsize[cnt]>>1);
- prtbumpheight[cnt] = pipbumpheight[pip];
- prttype[cnt] = piptype[pip];
-
-
- // Image data
- newrand = RANDIE;
- prtrotate[cnt] = (newrand&piprotaterand[pip])+piprotatebase[pip];
- prtrotateadd[cnt] = piprotateadd[pip];
- prtsize[cnt] = pipsizebase[pip];
- prtsizeadd[cnt] = pipsizeadd[pip];
- prtimage[cnt] = 0;
- newrand = RANDIE;
- prtimageadd[cnt] = pipimageadd[pip]+(newrand&pipimageaddrand[pip]);
- prtimagestt[cnt] = pipimagebase[pip]<<8;
- prtimagemax[cnt] = pipnumframes[pip]<<8;
- prttime[cnt] = piptime[pip];
- if(pipendlastframe[pip] && prtimageadd[cnt]!=0)
- {
- if(prttime[cnt]==0)
- {
- // Part time is set to 1 cycle
- prttime[cnt] = (prtimagemax[cnt]/prtimageadd[cnt])-1;
- }
- else
- {
- // Part time is used to give number of cycles
- prttime[cnt] = prttime[cnt]*((prtimagemax[cnt]/prtimageadd[cnt])-1);
- }
- }
-
-
- // Set onwhichfan...
- prtonwhichfan[cnt] = OFFEDGE;
- if(prtxpos[cnt] > 0 && prtxpos[cnt] < meshedgex && prtypos[cnt] > 0 && prtypos[cnt] < meshedgey)
- {
- prtonwhichfan[cnt] = meshfanstart[((int)prtypos[cnt])>>7] + (((int)prtxpos[cnt])>>7);
- }
-
-
- // Damage stuff
- prtdamagebase[cnt] = pipdamagebase[pip];
- prtdamagerand[cnt] = pipdamagerand[pip];
-
-
-
- // Spawning data
- prtspawntime[cnt] = pipcontspawntime[pip];
- if(prtspawntime[cnt]!=0)
- {
- prtspawntime[cnt] = 1;
- if(prtattachedtocharacter[cnt] != MAXCHR)
- {
- prtspawntime[cnt]++; // Because attachment takes an update before it happens
- }
- }
-
-
- // Sound effect
- play_particle_sound(cnt, pipsoundspawn[pip]);
- }
- return cnt;
- }
-
- //--------------------------------------------------------------------------------------------
- unsigned char __prthitawall(int particle)
- {
- // ZZ> This function returns nonzero if the particle hit a wall
- int x, y;
-
- y = prtypos[particle]; x = prtxpos[particle];
- // !!!BAD!!! Should really do bound checking...
- if(pipbumpmoney[prtpip[particle]])
- {
- return ((meshfx[meshfanstart[y>>7]+(x>>7)])&(MESHFXIMPASS|MESHFXWALL));
- }
- else
- {
- return ((meshfx[meshfanstart[y>>7]+(x>>7)])&(MESHFXIMPASS));
- }
- }
-
- //--------------------------------------------------------------------------------------------
- void disaffirm_attached_particles(unsigned short character)
- {
- // ZZ> This function makes sure a character has no attached particles
- unsigned short particle;
-
- particle = 0;
- while(particle < MAXPRT)
- {
- if(prton[particle] && prtattachedtocharacter[particle]==character)
- {
- free_one_particle(particle);
- }
- particle++;
- }
-
- // Set the alert for disaffirmation ( wet torch )
- chralert[character]|=ALERTIFDISAFFIRMED;
- }
-
- //--------------------------------------------------------------------------------------------
- unsigned short number_of_attached_particles(unsigned short character)
- {
- // ZZ> This function returns the number of particles attached to the given character
- unsigned short cnt, particle;
-
- cnt = 0;
- particle = 0;
- while(particle < MAXPRT)
- {
- if(prton[particle] && prtattachedtocharacter[particle]==character)
- {
- cnt++;
- }
- particle++;
- }
-
- return cnt;
- }
-
- //--------------------------------------------------------------------------------------------
- void reaffirm_attached_particles(unsigned short character)
- {
- // ZZ> This function makes sure a character has all of it's particles
- unsigned short numberattached;
- unsigned short particle;
-
- numberattached = number_of_attached_particles(character);
- while(numberattached < capattachedprtamount[chrmodel[character]])
- {
- particle = spawn_one_particle(chrxpos[character], chrypos[character], chrzpos[character], 0, chrmodel[character], capattachedprttype[chrmodel[character]], character, SPAWNLAST+numberattached, chrteam[character], character, numberattached, MAXCHR);
- if(particle != MAXPRT)
- {
- attach_particle_to_character(particle, character, prtgrip[particle]);
- }
- numberattached++;
- }
-
- // Set the alert for reaffirmation ( for exploding barrels with fire )
- chralert[character] = chralert[character]|ALERTIFREAFFIRMED;
- }
-
-
- //--------------------------------------------------------------------------------------------
- void move_particles(void)
- {
- // ZZ> This is the particle physics function
- int cnt, tnc, x, y, fan;
- unsigned short facing, pip, particle;
- float level;
-
- cnt = 0;
- while(cnt < MAXPRT)
- {
- if(prton[cnt])
- {
- prtonwhichfan[cnt] = OFFEDGE;
- prtlevel[cnt] = 0;
- if(prtxpos[cnt] > 0 && prtxpos[cnt] < meshedgex && prtypos[cnt] > 0 && prtypos[cnt] < meshedgey)
- {
- x = prtxpos[cnt];
- y = prtypos[cnt];
- x = x>>7;
- y = y>>7;
- fan = meshfanstart[y]+x;
- prtonwhichfan[cnt] = fan;
- prtlevel[cnt] = get_level(prtxpos[cnt], prtypos[cnt], fan, FALSE);
- }
-
-
- // To make it easier
- pip = prtpip[cnt];
-
- // Animate particle
- prtimage[cnt] = (prtimage[cnt]+prtimageadd[cnt]);
- if(prtimage[cnt] >= prtimagemax[cnt])
- prtimage[cnt]=0;
- prtrotate[cnt]+=prtrotateadd[cnt];
- prtsize[cnt]+=prtsizeadd[cnt];
-
-
- // Change dyna light values
- prtdynalightlevel[cnt] += pipdynalightleveladd[pip];
- prtdynalightfalloff[cnt] += pipdynalightfalloffadd[pip];
-
-
- // Make it sit on the floor... Shift is there to correct for sprite size
- level = prtlevel[cnt]+(prtsize[cnt]>>9);
-
-
- // Check floor collision and do iterative physics
- if((prtzpos[cnt] < level && prtzvel[cnt] < 0.1) || (prtzpos[cnt] < level - PRTLEVELFIX))
- {
- prtzpos[cnt] = level;
- prtxvel[cnt] = prtxvel[cnt]*noslipfriction;
- prtyvel[cnt] = prtyvel[cnt]*noslipfriction;
- if(pipendground[pip]) prttime[cnt] = 1;
- if(prtzvel[cnt] < 0)
- {
- if(prtzvel[cnt] > -STOPBOUNCINGPART)
- {
- // Make it not bounce
- prtzpos[cnt]-=.0001;
- }
- else
- {
- // Make it bounce
- prtzvel[cnt] = -prtzvel[cnt]*pipdampen[pip];
- // Play the sound for hitting the floor [FSND]
- play_particle_sound(cnt, pipsoundfloor[pip]);
- }
- }
- }
- else
- {
- if(prtattachedtocharacter[cnt] == MAXCHR)
- {
- prtxpos[cnt]+=prtxvel[cnt];
- if(__prthitawall(cnt))
- {
- // Play the sound for hitting a wall [WSND]
- play_particle_sound(cnt, pipsoundwall[pip]);
- prtxpos[cnt]-=prtxvel[cnt];
- prtxvel[cnt]=(-prtxvel[cnt]*pipdampen[pip]);
- if(pipendwall[pip])
- {
- prttime[cnt] = 1;
- }
- else
- {
- // Change facing
- facing = prtfacing[cnt];
- if(facing < 32768)
- {
- facing-=NORTH;
- facing = ~facing;
- facing+=NORTH;
- }
- else
- {
- facing-=SOUTH;
- facing = ~facing;
- facing+=SOUTH;
- }
- prtfacing[cnt] = facing;
- }
- }
- prtypos[cnt]+=prtyvel[cnt];
- if(__prthitawall(cnt))
- {
- prtypos[cnt]-=prtyvel[cnt];
- prtyvel[cnt]=(-prtyvel[cnt]*pipdampen[pip]);
- if(pipendwall[pip])
- {
- prttime[cnt] = 1;
- }
- else
- {
- // Change facing
- facing = prtfacing[cnt];
- if(facing < 16384 || facing > 49152)
- {
- facing = ~facing;
- }
- else
- {
- facing-=EAST;
- facing = ~facing;
- facing+=EAST;
- }
- prtfacing[cnt] = facing;
- }
- }
- prtzpos[cnt]+=prtzvel[cnt];
- prtzvel[cnt]+=gravity;
- }
- }
- // Do homing
- if(piphoming[pip] && prttarget[cnt]!=MAXCHR)
- {
- if(chralive[prttarget[cnt]]==FALSE)
- {
- prttime[cnt] = 1;
- }
- else
- {
- if(prtattachedtocharacter[cnt]==MAXCHR)
- {
- prtxvel[cnt]=(prtxvel[cnt]+((chrxpos[prttarget[cnt]]-prtxpos[cnt])*piphomingaccel[pip]))*piphomingfriction[pip];
- prtyvel[cnt]=(prtyvel[cnt]+((chrypos[prttarget[cnt]]-prtypos[cnt])*piphomingaccel[pip]))*piphomingfriction[pip];
- prtzvel[cnt]=(prtzvel[cnt]+((chrzpos[prttarget[cnt]]+(chrbumpheight[prttarget[cnt]]>>1)-prtzpos[cnt])*piphomingaccel[pip]));
-
- }
- if(piprotatetoface[pip])
- {
- // Turn to face target
- facing = atan2(chrypos[prttarget[cnt]]-prtypos[cnt], chrxpos[prttarget[cnt]]-prtxpos[cnt])*65535/(2*PI);
- facing+=32768;
- prtfacing[cnt] = facing;
- }
- }
- }
- // Do speed limit on Z
- if(prtzvel[cnt] < -pipspdlimit[pip]) prtzvel[cnt]=-pipspdlimit[pip];
-
-
-
- // Spawn new particles if continually spawning
- if(pipcontspawnamount[pip]>0)
- {
- prtspawntime[cnt]--;
- if(prtspawntime[cnt] == 0)
- {
- prtspawntime[cnt] = pipcontspawntime[pip];
- facing = prtfacing[cnt];
- tnc = 0;
- while(tnc < pipcontspawnamount[pip])
- {
- particle = spawn_one_particle(prtxpos[cnt], prtypos[cnt], prtzpos[cnt],
- facing, prtmodel[cnt], pipcontspawnpip[pip],
- MAXCHR, SPAWNLAST, prtteam[cnt], prtchr[cnt], tnc, prttarget[cnt]);
- if(pipfacingadd[prtpip[cnt]]!=0 && particle < MAXPRT)
- {
- // Hack to fix velocity
- prtxvel[particle]+=prtxvel[cnt];
- prtyvel[particle]+=prtyvel[cnt];
- }
- facing+=pipcontspawnfacingadd[pip];
- tnc++;
- }
- }
- }
-
-
- // Check underwater
- if(prtzpos[cnt] < waterdouselevel && (meshfx[prtonwhichfan[cnt]]&MESHFXWATER) && pipendwater[pip])
- {
- // Splash for particles is just a ripple
- spawn_one_particle(prtxpos[cnt], prtypos[cnt], watersurfacelevel,
- 0, MAXMODEL, RIPPLE, MAXCHR, SPAWNLAST, NULLTEAM, MAXCHR, 0, MAXCHR);
-
-
- // Check for disaffirming character
- if(prtattachedtocharacter[cnt]!=MAXCHR && prtchr[cnt]==prtattachedtocharacter[cnt])
- {
- // Disaffirm the whole character
- disaffirm_attached_particles(prtattachedtocharacter[cnt]);
- }
- else
- {
- // Just destroy the particle
- // free_one_particle(cnt);
- prttime[cnt] = 1;
- }
- }
- // else
- // {
- // Spawn new particles if time for old one is up
- if(prttime[cnt]!=0)
- {
- prttime[cnt]--;
- if(prttime[cnt] == 0)
- {
- facing = prtfacing[cnt];
- tnc = 0;
- while(tnc < pipendspawnamount[pip])
- {
- spawn_one_particle(prtxpos[cnt]-prtxvel[cnt], prtypos[cnt]-prtyvel[cnt], prtzpos[cnt],
- facing, prtmodel[cnt], pipendspawnpip[pip],
- MAXCHR, SPAWNLAST, prtteam[cnt], prtchr[cnt], tnc, prttarget[cnt]);
- facing+=pipendspawnfacingadd[pip];
- tnc++;
- }
- free_one_particle(cnt);
- }
- }
- // }
- prtfacing[cnt]+=pipfacingadd[pip];
- }
- cnt++;
- }
- }
-
- //--------------------------------------------------------------------------------------------
- void attach_particles()
- {
- // ZZ> This function attaches particles to their characters so everything gets
- // drawn right
- int cnt;
-
- cnt = 0;
- while(cnt < MAXPRT)
- {
- if(prton[cnt] && prtattachedtocharacter[cnt]!=MAXCHR)
- {
- attach_particle_to_character(cnt, prtattachedtocharacter[cnt], prtgrip[cnt]);
- // Correct facing so swords knock characters in the right direction...
- if(pipdamfx[prtpip[cnt]]&DAMFXTURN)
- prtfacing[cnt] = chrturnleftright[prtattachedtocharacter[cnt]];
- }
- cnt++;
- }
- }
-
- //--------------------------------------------------------------------------------------------
- void free_all_particles()
- {
- // ZZ> This function resets the particle allocation lists
- numfreeprt = 0;
- while(numfreeprt<MAXPRT)
- {
- prton[numfreeprt] = 0;
- freeprtlist[numfreeprt] = numfreeprt;
- numfreeprt++;
- }
- }
-
- //--------------------------------------------------------------------------------------------
- void setup_particles()
- {
- // ZZ> This function sets up particle data
- int cnt;
- double x, y;
-
- particletexture = 0;
-
- // Image coordinates on the big particle bitmap
- for (cnt = 0; cnt < MAXPARTICLEIMAGE; cnt++)
- {
- x = cnt&15;
- y = cnt>>4;
- particleimageu[cnt][0] = (float) ((.05+x)/16.0);
- particleimageu[cnt][1] = (float) ((.95+x)/16.0);
- particleimagev[cnt][0] = (float) ((.05+y)/16.0);
- particleimagev[cnt][1] = (float) ((.95+y)/16.0);
- }
-
- // Reset the allocation table
- free_all_particles();
- }
-
- //--------------------------------------------------------------------------------------------
- unsigned short terp_dir(unsigned short majordir, unsigned short minordir)
- {
- // ZZ> This function returns a direction between the major and minor ones, closer
- // to the major.
- unsigned short temp;
-
- // Align major direction with 0
- minordir-=majordir;
- if(minordir > 32768)
- {
- temp = 65535;
- minordir = (minordir+(temp<<3)-temp)>>3;
- minordir+=majordir;
- return minordir;
- }
- temp = 0;
- minordir = (minordir+(temp<<3)-temp)>>3;
- minordir+=majordir;
- return minordir;
- }
-
- //--------------------------------------------------------------------------------------------
- unsigned short terp_dir_fast(unsigned short majordir, unsigned short minordir)
- {
- // ZZ> This function returns a direction between the major and minor ones, closer
- // to the major, but not by much. Makes turning faster.
- unsigned short temp;
-
- // Align major direction with 0
- minordir-=majordir;
- if(minordir > 32768)
- {
- temp = 65535;
- minordir = (minordir+(temp<<1)-temp)>>1;
- minordir+=majordir;
- return minordir;
- }
- temp = 0;
- minordir = (minordir+(temp<<1)-temp)>>1;
- minordir+=majordir;
- return minordir;
- }
-
- //--------------------------------------------------------------------------------------------
- void spawn_bump_particles(unsigned short character, unsigned short particle)
- {
- // ZZ> This function is for catching characters on fire and such
- int cnt;
- signed short x, y, z;
- int distance, bestdistance;
- unsigned short frame;
- unsigned short facing, bestvertex;
- unsigned short amount;
- unsigned short pip;
- unsigned short vertices;
- unsigned short direction, left, right, model;
- float fsin, fcos;
-
-
- pip = prtpip[particle];
- amount = pipbumpspawnamount[pip];
-
-
- if(amount != 0 || pipspawnenchant[pip])
- {
- // Only damage if hitting from proper direction
- model = chrmodel[character];
- vertices = madvertices[model];
- direction = (atan2(prtyvel[particle], prtxvel[particle])+PI)*65535/(2*PI);
- direction = chrturnleftright[character]-direction+32768;
- if(madframefx[chrframe[character]]&MADFXINVICTUS)
- {
- // I Frame
- if(pipdamfx[pip]&DAMFXBLOC)
- {
- left = 65535;
- right = 0;
- }
- else
- {
- direction -= capiframefacing[model];
- left = (~capiframeangle[model]);
- right = capiframeangle[model];
- }
- }
- else
- {
- // N Frame
- direction -= capnframefacing[model];
- left = (~capnframeangle[model]);
- right = capnframeangle[model];
- }
- // Check that direction
- if(direction <= left && direction >= right)
- {
- // Spawn new enchantments
- if(pipspawnenchant[pip])
- {
- spawn_enchant(prtchr[particle], character, MAXCHR, MAXENCHANT, prtmodel[particle]);
- }
- // Spawn particles
- if(amount != 0 && capresistbumpspawn[chrmodel[character]]==FALSE && chrinvictus[character]==FALSE && vertices != 0 && (chrdamagemodifier[character][prtdamagetype[particle]]&DAMAGESHIFT)<3)
- {
- if(amount == 1)
- {
- // A single particle ( arrow? ) has been stuck in the character...
- // Find best vertex to attach to
- bestvertex = 0;
- bestdistance = 9999999;
- z = -chrzpos[character] + prtzpos[particle] + RAISE;
- facing = prtfacing[particle]-chrturnleftright[character]-16384;
- facing = facing>>2;
- fsin = turntosin[facing];
- fcos = turntosin[(facing+4096)&16383];
- y = 8192;
- x = -y*fsin;
- y = y*fcos;
- z = z<<10;///chrscale[character];
- frame = madframestart[chrmodel[character]];
- cnt = 0;
- while(cnt < vertices)
- {
- distance = ABS(x-madvrtx[frame][vertices-cnt-1])+ABS(y-madvrty[frame][vertices-cnt-1])+(ABS(z-madvrtz[frame][vertices-cnt-1]));
- if(distance < bestdistance)
- {
- bestdistance = distance;
- bestvertex = cnt;
- }
- cnt++;
- }
- spawn_one_particle(chrxpos[character], chrypos[character], chrzpos[character], 0, prtmodel[particle], pipbumpspawnpip[pip],
- character, bestvertex+1, prtteam[particle], prtchr[particle], cnt, character);
- }
- else
- {
- amount = (amount*vertices)>>5; // Correct amount for size of character
- cnt = 0;
- while(cnt < amount)
- {
- spawn_one_particle(chrxpos[character], chrypos[character], chrzpos[character], 0, prtmodel[particle], pipbumpspawnpip[pip],
- character, rand()%vertices, prtteam[particle], prtchr[particle], cnt, character);
- cnt++;
- }
- }
- }
- }
- }
- }
-
- //--------------------------------------------------------------------------------------------
- int prt_is_over_water(int cnt)
- {
- // This function returns TRUE if the particle is over a water tile
- int x, y, fan;
-
-
- if(cnt < MAXPRT)
- {
- if(prtxpos[cnt] > 0 && prtxpos[cnt] < meshedgex && prtypos[cnt] > 0 && prtypos[cnt] < meshedgey)
- {
- x = prtxpos[cnt];
- y = prtypos[cnt];
- x = x>>7;
- y = y>>7;
- fan = meshfanstart[y]+x;
- if(meshfx[fan]&MESHFXWATER) return TRUE;
- }
- }
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------
- void do_weather_spawn()
- {
- // ZZ> This function drops snowflakes or rain or whatever, also swings the camera
- int particle, cnt;
- float x, y, z;
- unsigned char foundone;
-
-
- if(weathertime>0)
- {
- weathertime--;
- if(weathertime==0)
- {
- weathertime=weathertimereset;
-
-
- // Find a valid player
- foundone = FALSE;
- cnt = 0;
- while(cnt < MAXPLAYER)
- {
- weatherplayer = (weatherplayer+1)&(MAXPLAYER-1);
- if(plavalid[weatherplayer])
- {
- foundone = TRUE;
- cnt = MAXPLAYER;
- }
- cnt++;
- }
-
-
- // Did we find one?
- if(foundone)
- {
- // Yes, but is the character valid?
- cnt = plaindex[weatherplayer];
- if(chron[cnt] && chrinpack[cnt]==FALSE)
- {
- // Yes, so spawn over that character
- x = chrxpos[cnt];
- y = chrypos[cnt];
- z = chrzpos[cnt];
- particle = spawn_one_particle(x, y, z, 0, MAXMODEL, WEATHER4, MAXCHR, SPAWNLAST, NULLTEAM, MAXCHR, 0, MAXCHR);
- if(weatheroverwater && particle != MAXPRT)
- {
- if(!prt_is_over_water(particle))
- {
- free_one_particle_no_sound(particle);
- }
- }
-
- }
- }
- }
- }
- camswing = (camswing + camswingrate) & 16383;
- }
-
- //--------------------------------------------------------------------------------------------
- int load_one_particle(char *szLoadName, int object, int pip)
- {
- // ZZ> This function loads a particle template, returning FALSE if the file wasn't
- // found
- FILE* fileread;
- int test, idsz;
- int iTmp;
- float fTmp;
- char cTmp;
-
-
- fileread = fopen(FILENAME(szLoadName), "r");
- if(fileread)
- {
- // General data
- globalname = szLoadName;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipforce[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') pipforce[numpip] = TRUE;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- if(cTmp=='L' || cTmp=='l') piptype[numpip] = PRTLIGHTSPRITE;
- if(cTmp=='S' || cTmp=='s') piptype[numpip] = PRTSOLIDSPRITE;
- if(cTmp=='T' || cTmp=='t') piptype[numpip] = PRTALPHASPRITE;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipimagebase[numpip]=iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipnumframes[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipimageadd[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipimageaddrand[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); piprotatebase[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); piprotaterand[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); piprotateadd[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipsizebase[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipsizeadd[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%f", &fTmp); pipspdlimit[numpip] = fTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipfacingadd[numpip] = iTmp;
-
-
- // Ending conditions
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipendwater[numpip] = TRUE;
- if(cTmp=='F' || cTmp=='f') pipendwater[numpip] = FALSE;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipendbump[numpip] = TRUE;
- if(cTmp=='F' || cTmp=='f') pipendbump[numpip] = FALSE;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipendground[numpip] = TRUE;
- if(cTmp=='F' || cTmp=='f') pipendground[numpip] = FALSE;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipendlastframe[numpip] = TRUE;
- if(cTmp=='F' || cTmp=='f') pipendlastframe[numpip] = FALSE;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); piptime[numpip] = iTmp;
-
-
- // Collision data
- goto_colon(fileread); fscanf(fileread, "%f", &fTmp); pipdampen[numpip] = fTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipbumpmoney[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipbumpsize[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipbumpheight[numpip] = iTmp;
- goto_colon(fileread); read_pair(fileread);
- pipdamagebase[numpip] = pairbase;
- pipdamagerand[numpip] = pairrand;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- if(cTmp=='S' || cTmp=='s') pipdamagetype[numpip] = DAMAGESLASH;
- if(cTmp=='C' || cTmp=='c') pipdamagetype[numpip] = DAMAGECRUSH;
- if(cTmp=='P' || cTmp=='p') pipdamagetype[numpip] = DAMAGEPOKE;
- if(cTmp=='H' || cTmp=='h') pipdamagetype[numpip] = DAMAGEHOLY;
- if(cTmp=='E' || cTmp=='e') pipdamagetype[numpip] = DAMAGEEVIL;
- if(cTmp=='F' || cTmp=='f') pipdamagetype[numpip] = DAMAGEFIRE;
- if(cTmp=='I' || cTmp=='i') pipdamagetype[numpip] = DAMAGEICE;
- if(cTmp=='Z' || cTmp=='z') pipdamagetype[numpip] = DAMAGEZAP;
-
-
- // Lighting data
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipdynalightmode[numpip] = DYNAOFF;
- if(cTmp=='T' || cTmp=='t') pipdynalightmode[numpip] = DYNAON;
- if(cTmp=='L' || cTmp=='l') pipdynalightmode[numpip] = DYNALOCAL;
- goto_colon(fileread); fscanf(fileread, "%f", &fTmp); pipdynalevel[numpip] = fTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipdynafalloff[numpip] = iTmp;
- if(pipdynafalloff[numpip] > MAXFALLOFF && rtscontrol) pipdynafalloff[numpip] = MAXFALLOFF;
-
-
-
- // Initial spawning of this particle
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipfacingbase[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipfacingrand[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipxyspacingbase[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipxyspacingrand[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipzspacingbase[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipzspacingrand[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipxyvelbase[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipxyvelrand[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipzvelbase[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipzvelrand[numpip] = iTmp;
-
-
- // Continuous spawning of other particles
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipcontspawntime[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipcontspawnamount[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipcontspawnfacingadd[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipcontspawnpip[numpip] = iTmp;
-
-
- // End spawning of other particles
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipendspawnamount[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipendspawnfacingadd[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipendspawnpip[numpip] = iTmp;
-
-
- // Bump spawning of attached particles
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipbumpspawnamount[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipbumpspawnpip[numpip] = iTmp;
-
-
- // Random stuff !!!BAD!!! Not complete
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipdazetime[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); pipgrogtime[numpip] = iTmp;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipspawnenchant[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') pipspawnenchant[numpip] = TRUE;
- goto_colon(fileread); // !!Cause roll
- goto_colon(fileread); // !!Cause pancake
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipneedtarget[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') pipneedtarget[numpip] = TRUE;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- piptargetcaster[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') piptargetcaster[numpip] = TRUE;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipstartontarget[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') pipstartontarget[numpip] = TRUE;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- piponlydamagefriendly[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') piponlydamagefriendly[numpip] = TRUE;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp);
- if(iTmp < -1) iTmp = -1;
- if(iTmp > MAXWAVE-1) iTmp = MAXWAVE-1;
- pipsoundspawn[numpip] = iTmp;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp);
- if(iTmp < -1) iTmp = -1;
- if(iTmp > MAXWAVE-1) iTmp = MAXWAVE-1;
- pipsoundend[numpip] = iTmp;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipfriendlyfire[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') pipfriendlyfire[numpip] = TRUE;
- goto_colon(fileread); // !!Hate group only
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- pipnewtargetonspawn[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') pipnewtargetonspawn[numpip] = TRUE;
- goto_colon(fileread); fscanf(fileread, "%d", &iTmp); piptargetangle[numpip] = iTmp>>1;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- piphoming[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') piphoming[numpip] = TRUE;
- goto_colon(fileread); fscanf(fileread, "%f", &fTmp); piphomingfriction[numpip] = fTmp;
- goto_colon(fileread); fscanf(fileread, "%f", &fTmp); piphomingaccel[numpip] = fTmp;
- goto_colon(fileread); cTmp = get_first_letter(fileread);
- piprotatetoface[numpip] = FALSE;
- if(cTmp=='T' || cTmp=='t') piprotatetoface[numpip] = TRUE;
-
- // Clear expansions...
- pipzaimspd[numpip] = 0;
- pipsoundfloor[numpip] = -1;
- pipsoundwall[numpip] = -1;
- pipendwall[numpip] = pipendground[numpip];
- pipdamfx[numpip] = DAMFXTURN;
- if(piphoming[numpip]) pipdamfx[numpip] = DAMFXNONE;
- pipallowpush[numpip] = TRUE;
- pipdynalightfalloffadd[numpip] = 0;
- pipdynalightleveladd[numpip] = 0;
- // Read expansions
- while(goto_colon_yesno(fileread))
- {
- idsz = get_idsz(fileread);
- fscanf(fileread, "%c%d", &cTmp, &iTmp);
- test = ('T'-'A'<<15)|('U'-'A'<<10)|('R'-'A'<<5)|('N'-'A'); // [TURN]
- if(idsz == test) pipdamfx[numpip] = DAMFXNONE;
- test = ('Z'-'A'<<15)|('S'-'A'<<10)|('P'-'A'<<5)|('D'-'A'); // [ZSPD]
- if(idsz == test) pipzaimspd[numpip] = iTmp;
- test = ('F'-'A'<<15)|('S'-'A'<<10)|('N'-'A'<<5)|('D'-'A'); // [FSND]
- if(idsz == test) pipsoundfloor[numpip] = iTmp;
- test = ('W'-'A'<<15)|('S'-'A'<<10)|('N'-'A'<<5)|('D'-'A'); // [WSND]
- if(idsz == test) pipsoundwall[numpip] = iTmp;
- test = ('W'-'A'<<15)|('E'-'A'<<10)|('N'-'A'<<5)|('D'-'A'); // [WEND]
- if(idsz == test) pipendwall[numpip] = iTmp;
- test = ('A'-'A'<<15)|('R'-'A'<<10)|('M'-'A'<<5)|('O'-'A'); // [ARMO]
- if(idsz == test) pipdamfx[numpip] |= DAMFXARMO;
- test = ('B'-'A'<<15)|('L'-'A'<<10)|('O'-'A'<<5)|('C'-'A'); // [BLOC]
- if(idsz == test) pipdamfx[numpip] |= DAMFXBLOC;
- test = ('A'-'A'<<15)|('R'-'A'<<10)|('R'-'A'<<5)|('O'-'A'); // [ARRO]
- if(idsz == test) pipdamfx[numpip] |= DAMFXARRO;
- test = ('T'-'A'<<15)|('I'-'A'<<10)|('M'-'A'<<5)|('E'-'A'); // [TIME]
- if(idsz == test) pipdamfx[numpip] |= DAMFXTIME;
- test = ('P'-'A'<<15)|('U'-'A'<<10)|('S'-'A'<<5)|('H'-'A'); // [PUSH]
- if(idsz == test) pipallowpush[numpip] = iTmp;
- test = ('D'-'A'<<15)|('L'-'A'<<10)|('E'-'A'<<5)|('V'-'A'); // [DLEV]
- if(idsz == test) pipdynalightleveladd[numpip] = iTmp/1000.0;
- test = ('D'-'A'<<15)|('R'-'A'<<10)|('A'-'A'<<5)|('D'-'A'); // [DRAD]
- if(idsz == test) pipdynalightfalloffadd[numpip] = iTmp/1000.0;
- }
-
-
- // Make sure it's referenced properly
- madprtpip[object][pip]=numpip;
- numpip++;
-
-
- fclose(fileread);
- return TRUE;
- }
- return FALSE;
- }
-
- //--------------------------------------------------------------------------------------------
- void reset_particles(char* modname)
- {
- // ZZ> This resets all particle data and reads in the coin and water particles
- int cnt, object;
- char newloadname[256];
-
- // PORT: make_newloadname should work
- // PORT: load_one_particle should work too
-
- // Load in the standard particles ( the coins )
- numpip = 0;
- make_newloadname(modname, "gamedat/1money.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "1MONEY.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/5money.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "5MONEY.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/25money.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "25MONEY.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/100money.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "100MONEY.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/weather4.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "WEATHER4.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/weather5.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "WEATHER5.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/splash.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "SPLASH.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/ripple.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "RIPPLE.TXT NOT FOUND");
- }
- make_newloadname(modname, "gamedat/defend.txt", newloadname);
- if(load_one_particle(newloadname, 0, 0)==FALSE)
- {
- general_error(0, 0, "DEFEND.TXT NOT FOUND");
- }
-
- // Now clear out the local pips
- object = 0;
- while(object < MAXMODEL)
- {
- cnt = 0;
- while(cnt < MAXPRTPIPPEROBJECT)
- {
- madprtpip[object][cnt] = 0;
- cnt++;
- }
- object++;
- }
- }
-
-