]> git.jsancho.org Git - lugaru.git/blob - Source/Sprites.cpp
Added GPL license and headers.
[lugaru.git] / Source / Sprites.cpp
1 /*
2 Copyright (C) 2003, 2010 - Wolfire Games
3
4 This file is part of Lugaru.
5
6 Lugaru is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
14
15 See the GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */
21
22 #include "Sprites.h"
23 #include "Person.h"
24 extern XYZ viewer;
25 extern float viewdistance;
26 extern float fadestart;
27 extern int environment;
28 extern float texscale;
29 extern Light light;
30 extern float multiplier;
31 extern float gravity;
32 extern Terrain terrain;
33 extern Objects objects;
34 extern int detail;
35 extern XYZ viewerfacing;
36 extern float terraindetail;
37 extern int bloodtoggle;
38 extern XYZ windvector;
39 extern int numplayers;
40 extern Person player[maxplayers];
41 //Functions
42
43 void Sprites::Draw()
44 {
45         static int i,j,k;
46         static float M[16];
47         static XYZ point;
48         static float distancemult;
49         static int lasttype;
50         static int lastspecial;
51         static int whichpatchx,whichpatchz;
52         static XYZ start,end,colpoint;
53         static bool check;
54         static bool blend;
55         static float tempmult;
56         static XYZ difference;
57         static float lightcolor[3];
58         static float viewdistsquared=viewdistance*viewdistance;
59         static XYZ tempviewer;
60
61         tempviewer=viewer+viewerfacing*6;
62         check=0;
63
64         lightcolor[0]=light.color[0]*.5+light.ambient[0];
65         lightcolor[1]=light.color[1]*.5+light.ambient[1];
66         lightcolor[2]=light.color[2]*.5+light.ambient[2];
67
68         checkdelay-=multiplier*10;
69
70         if(checkdelay<=0){
71                 check=1;
72                 checkdelay=1;
73         }
74
75         lasttype=-1;
76         lastspecial=-1;
77         glEnable(GL_BLEND);
78         glDisable(GL_LIGHTING);
79         glDisable(GL_CULL_FACE);
80         glEnable(GL_TEXTURE_2D);
81         blend = 1;
82         glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
83         glDepthMask(0);
84         glAlphaFunc(GL_GREATER, 0.0001);
85         for(i=0;i<numsprites;i++){
86                 if(type[i]==cloudsprite&&lasttype!=type[i]){
87                         glBindTexture( GL_TEXTURE_2D, cloudtexture);
88                         if(!blend){
89                                 blend=1;
90                                 glAlphaFunc(GL_GREATER, 0.0001);
91                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
92                         }
93                 }
94                 if(type[i]==cloudimpactsprite&&lasttype!=type[i]){
95                         glBindTexture( GL_TEXTURE_2D, cloudimpacttexture);
96                         if(!blend){
97                                 blend=1;
98                                 glAlphaFunc(GL_GREATER, 0.0001);
99                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
100                         }
101                 }
102                 if(type[i]==breathsprite&&lasttype!=type[i]){
103                         glBindTexture( GL_TEXTURE_2D, cloudimpacttexture);
104                         if(!blend){
105                                 blend=1;
106                                 glAlphaFunc(GL_GREATER, 0.0001);
107                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
108                         }
109                 }
110                 if(type[i]==smoketype&&lasttype!=type[i]){
111                         glBindTexture( GL_TEXTURE_2D, smoketexture);
112                         if(!blend){
113                                 blend=1;
114                                 glAlphaFunc(GL_GREATER, 0.0001);
115                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
116                         }
117                 }
118                 if(type[i]==bloodsprite&&lasttype!=type[i]){
119                         glBindTexture( GL_TEXTURE_2D, bloodtexture);
120                         if(!blend){
121                                 blend=1;
122                                 glAlphaFunc(GL_GREATER, 0.0001);
123                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
124                         }
125                 }
126                 if(type[i]==splintersprite&&(lasttype!=type[i]||lastspecial!=special[i])){
127                         if(special[i]==0)glBindTexture( GL_TEXTURE_2D, splintertexture);
128                         if(special[i]==1)glBindTexture( GL_TEXTURE_2D, leaftexture);
129                         if(special[i]==2)glBindTexture( GL_TEXTURE_2D, snowflaketexture);
130                         if(special[i]==3)glBindTexture( GL_TEXTURE_2D, toothtexture);
131                         if(!blend){
132                                 blend=1;
133                                 glAlphaFunc(GL_GREATER, 0.0001);
134                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
135                         }
136                 }
137                 if(type[i]==snowsprite&&lasttype!=type[i]){
138                         glBindTexture( GL_TEXTURE_2D, snowflaketexture);
139                         if(!blend){
140                                 blend=1;
141                                 glAlphaFunc(GL_GREATER, 0.0001);
142                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
143                         }
144                 }
145                 if(type[i]==weaponshinesprite&&lasttype!=type[i]){
146                         glBindTexture( GL_TEXTURE_2D, shinetexture);
147                         if(blend){
148                                 blend=0;
149                                 glAlphaFunc(GL_GREATER, 0.001);
150                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
151                         }
152                 }
153                 if((type[i]==flamesprite||type[i]==weaponflamesprite)&&lasttype!=type[i]){
154                         glBindTexture( GL_TEXTURE_2D, flametexture);
155                         if(blend||lasttype==bloodflamesprite){
156                                 blend=0;
157                                 glAlphaFunc(GL_GREATER, 0.3);
158                                 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
159                         }
160                 }
161                 if((type[i]==bloodflamesprite)&&lasttype!=type[i]){
162                         glBindTexture( GL_TEXTURE_2D, bloodflametexture);
163                         if(blend){
164                                 blend=0;
165                                 glAlphaFunc(GL_GREATER, 0.3);
166                                 glBlendFunc(GL_ONE,GL_ZERO);
167                                 //glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
168                         }
169                 }
170                 if(type[i]!=snowsprite)distancemult=(viewdistsquared-(findDistancefast(&viewer,&position[i])-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
171                 if(type[i]==snowsprite)distancemult=(144-(findDistancefast(&tempviewer,&position[i])-(144*fadestart))*(1/(1-fadestart)))/144;
172                 if(type[i]!=flamesprite){
173                         if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]);
174                         if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]*distancemult);
175                 }
176                 if(type[i]==flamesprite){
177                         if(distancemult>=1)glColor4f(color[i][0],color[i][1],color[i][2],opacity[i]);
178                         if(distancemult<1)glColor4f(color[i][0],color[i][1],color[i][2],opacity[i]*distancemult);
179                 }
180                 lasttype=type[i];
181                 lastspecial=special[i];
182                 glMatrixMode(GL_MODELVIEW);                                                     // Select The Modelview Matrix
183                 glPushMatrix();
184                         glTranslatef(position[i].x,position[i].y,position[i].z);
185                         if((type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite)){
186                                 difference=viewer-position[i];
187                                 Normalise(&difference);
188                                 glTranslatef(difference.x*size[i]/4, difference.y*size[i]/4, difference.z*size[i]/4);
189                         }
190                         if(type[i]==snowsprite){
191                                 glRotatef(rotation[i]*.2,0,.3,1);
192                                 glTranslatef(1,0,0);
193                         }
194                         glGetFloatv(GL_MODELVIEW_MATRIX,M);
195                         point.x=M[12];
196                         point.y=M[13];
197                         point.z=M[14];
198                         glLoadIdentity();
199                         glTranslatef(point.x, point.y, point.z);
200
201                         glRotatef(rotation[i],0,0,1);
202
203                         if((type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite||type[i]==bloodflamesprite)){
204                                 if(alivetime[i]<.14)glScalef(alivetime[i]/.14,alivetime[i]/.14,alivetime[i]/.14);
205                         }
206                         if(type[i]==smoketype||type[i]==snowsprite||type[i]==weaponshinesprite||type[i]==breathsprite){
207                                 if(alivetime[i]<.3){
208                                         if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]*alivetime[i]/.3);
209                                         if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],opacity[i]*distancemult*alivetime[i]/.3);
210                                 }
211                         }
212                         if(type[i]==splintersprite&&special[i]>0&&special[i]!=3){
213                                 if(alivetime[i]<.2){
214                                         if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],alivetime[i]/.2);
215                                         if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],distancemult*alivetime[i]/.2);
216                                 }
217                                 else{
218                                         if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
219                                         if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
220                                 }
221                         }
222                         if(type[i]==splintersprite&&(special[i]==0||special[i]==3)){
223                                 if(distancemult>=1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
224                                 if(distancemult<1)glColor4f(color[i][0]*lightcolor[0],color[i][1]*lightcolor[1],color[i][2]*lightcolor[2],1);
225                         }
226                         /*
227                         if(type[i]==snowsprite){
228                         glRotatef(rotation[i],0,0,1);
229                         glTranslatef(1,0,0);
230                         }*/
231
232                         glBegin(GL_TRIANGLES);
233                         glTexCoord2f(1.0f, 1.0f); glVertex3f( .5*size[i], .5*size[i], 0.0f);
234                         glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*size[i], .5*size[i], 0.0f);
235                         glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*size[i],-.5*size[i], 0.0f);
236                         glTexCoord2f(0.0f, 0.0f); glVertex3f(-.5*size[i],-.5*size[i], 0.0f);
237                         glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*size[i], -.5*size[i], 0.0f);
238                         glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*size[i], .5*size[i], 0.0f);
239                         glEnd();
240                 glPopMatrix();
241         }
242         tempmult=multiplier;
243         for(i=numsprites-1;i>=0;i--){
244                 multiplier=tempmult;
245                 if(type[i]!=snowsprite)position[i]+=velocity[i]*multiplier;
246                 if(type[i]!=snowsprite)velocity[i]+=windvector*multiplier;
247                 if(type[i]==flamesprite||type[i]==smoketype)position[i]+=windvector*multiplier/2;
248                 if((type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite||type[i]==bloodflamesprite))multiplier*=speed[i]*.7;
249                 alivetime[i]+=multiplier;
250
251                 if(type[i]==cloudsprite||type[i]==cloudimpactsprite){
252                         opacity[i]-=multiplier/2;
253                         size[i]+=multiplier/2;
254                         velocity[i].y+=gravity*multiplier*.25;
255                 }
256                 if(type[i]==breathsprite){
257                         opacity[i]-=multiplier/2;
258                         size[i]+=multiplier/2;
259                         if(findLength(&velocity[i])<=multiplier)velocity[i]=0;
260                         else{
261                                 XYZ slowdown;
262                                 slowdown=velocity[i]*-1;
263                                 Normalise(&slowdown);
264                                 slowdown*=multiplier;
265                                 velocity[i]+=slowdown;
266                         }
267                 }
268                 if(type[i]==snowsprite){
269                         size[i]-=multiplier/120;
270                         rotation[i]+=multiplier*360;
271                         position[i].y-=multiplier;
272                         position[i]+=windvector*multiplier;
273                         if(position[i].y<tempviewer.y-6)position[i].y+=12;
274                         if(position[i].y>tempviewer.y+6)position[i].y-=12;
275                         if(position[i].z<tempviewer.z-6)position[i].z+=12;
276                         if(position[i].z>tempviewer.z+6)position[i].z-=12;
277                         if(position[i].x<tempviewer.x-6)position[i].x+=12;
278                         if(position[i].x>tempviewer.x+6)position[i].x-=12;
279                 }
280                 if(type[i]==bloodsprite){
281                         bool spritehit=0;
282                         rotation[i]+=multiplier*100;
283                         velocity[i].y+=gravity*multiplier;
284                         if(check){
285                                 XYZ where,startpoint,endpoint,movepoint,footpoint;
286                                 float rotationpoint;
287                                 int whichtri;
288
289                                 for(j=0;j<numplayers;j++){
290                                         if(!spritehit&&player[j].dead&&alivetime[i]>.1){
291                                                 where=oldposition[i];
292                                                 where-=player[j].coords;
293                                                 if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].rotation,0);
294                                                 startpoint=where;
295                                                 where=position[i];
296                                                 where-=player[j].coords;
297                                                 if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].rotation,0);
298                                                 endpoint=where;
299
300                                                 movepoint=0;
301                                                 rotationpoint=0;
302                                                 whichtri=player[j].skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &footpoint, &movepoint, &rotationpoint);
303                                                 if(whichtri!=-1){
304                                                         spritehit=1;
305                                                         player[j].DoBloodBigWhere(0,160,oldposition[i]);
306                                                         DeleteSprite(i);
307                                                 }
308                                         }
309                                 }
310
311                                 whichpatchx=position[i].x/(terrain.size/subdivision*terrain.scale*terraindetail);
312                                 whichpatchz=position[i].z/(terrain.size/subdivision*terrain.scale*terraindetail);
313                                 if(whichpatchx>0&&whichpatchz>0&&whichpatchx<subdivision&&whichpatchz<subdivision)
314                                         if(terrain.patchobjectnum[whichpatchx][whichpatchz]){
315                                                 if(!spritehit)
316                                                         for(j=0;j<terrain.patchobjectnum[whichpatchx][whichpatchz];j++){
317                                                                 k=terrain.patchobjects[whichpatchx][whichpatchz][j];
318                                                                 start=oldposition[i];
319                                                                 end=position[i];
320                                                                 if(!spritehit)
321                                                                         if(objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k])!=-1){
322                                                                                 if(detail==2||(detail==1&&abs(Random()%4)==0)||(detail==0&&abs(Random()%8)==0))objects.model[k].MakeDecal(blooddecalfast,DoRotation(colpoint-objects.position[k],0,-objects.rotation[k],0),size[i]*1.6/*+abs((float)(Random()%100))/2400*/,.5,Random()%360);
323                                                                                 DeleteSprite(i);
324                                                                                 spritehit=1;
325                                                                         }       
326                                                         }
327                                         }
328                                         if(!spritehit)
329                                                 if(position[i].y<terrain.getHeight(position[i].x,position[i].z)){
330                                                         terrain.MakeDecal(blooddecalfast,position[i],size[i]*1.6/*+abs((float)(Random()%100))/2400*/,.6,Random()%360);
331                                                         DeleteSprite(i);
332                                                 }
333                         }
334                 }
335                 if(type[i]==splintersprite){
336                         rotation[i]+=rotatespeed[i]*multiplier;
337                         opacity[i]-=multiplier/2;
338                         if(special[i]==0||special[i]==2||special[i]==3)velocity[i].y+=gravity*multiplier;
339                         if(special[i]==1)velocity[i].y+=gravity*multiplier*.5;
340                 }
341                 if(type[i]==flamesprite||type[i]==weaponflamesprite||type[i]==weaponshinesprite||type[i]==bloodflamesprite){
342                         rotation[i]+=multiplier*rotatespeed[i];
343                         opacity[i]-=multiplier*5/4;
344                         if(type[i]!=weaponshinesprite&&type[i]!=bloodflamesprite)
345                                 if(opacity[i]<.5&&opacity[i]+multiplier*5/4>=.5&&(abs(Random()%4)==0||(initialsize[i]>2&&Random()%2==0)))MakeSprite(smoketype, position[i],velocity[i], .9,.9,.6, size[i]*1.2, .4);
346                         if(alivetime[i]>.14&&(type[i]==flamesprite)){
347                                 velocity[i]=0;
348                                 velocity[i].y=1.5;
349                         }
350                 }
351                 /*if(type[i]==smoketype){
352                 opacity[i]-=multiplier/3/initialsize[i];
353                 size[i]+=multiplier;
354                 velocity[i]=0;
355                 velocity[i].y=1.5;
356                 rotation[i]+=multiplier*rotatespeed[i]/5;
357                 }*/
358                 if(type[i]==smoketype){
359                         opacity[i]-=multiplier/3/initialsize[i];
360                         color[i][0]-=multiplier;
361                         color[i][1]-=multiplier;
362                         color[i][2]-=multiplier;
363                         if(color[i][0]<.6)color[i][0]=.6;
364                         if(color[i][1]<.6)color[i][1]=.6;
365                         if(color[i][2]<.6)color[i][2]=.6;
366                         size[i]+=multiplier;
367                         velocity[i]=0;
368                         velocity[i].y=1.5;
369                         rotation[i]+=multiplier*rotatespeed[i]/5;
370                 }
371                 if(opacity[i]<=0||size[i]<=0)DeleteSprite(i);
372         }
373         if(check)
374                 for(i=numsprites-1;i>=0;i--){
375                         oldposition[i]=position[i];
376                 }
377                 glAlphaFunc(GL_GREATER, 0.0001);
378                 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
379 }
380
381 void Sprites::DeleteSprite(int which)
382 {
383         type[which]=type[numsprites-1];
384         rotation[which]=rotation[numsprites-1];
385         alivetime[which]=alivetime[numsprites-1];
386         opacity[which]=opacity[numsprites-1];
387         position[which]=position[numsprites-1];
388         velocity[which]=velocity[numsprites-1];
389         size[which]=size[numsprites-1];
390         speed[which]=speed[numsprites-1];
391         special[which]=special[numsprites-1];
392         color[which][0]=color[numsprites-1][0];
393         color[which][1]=color[numsprites-1][1];
394         color[which][2]=color[numsprites-1][2];
395         numsprites--;
396 }
397
398 void Sprites::MakeSprite(int atype, XYZ where, XYZ avelocity, float red, float green, float blue, float asize, float aopacity){
399         if(numsprites<max_sprites-1){
400                 if((atype!=bloodsprite&&atype!=bloodflamesprite)||bloodtoggle){
401                         special[numsprites]=0;
402                         type[numsprites]=atype;
403                         position[numsprites]=where;
404                         oldposition[numsprites]=where;
405                         velocity[numsprites]=avelocity;
406                         alivetime[numsprites]=0;
407                         opacity[numsprites]=aopacity;
408                         size[numsprites]=asize;
409                         initialsize[numsprites]=asize;
410                         color[numsprites][0]=red;
411                         color[numsprites][1]=green;
412                         color[numsprites][2]=blue;
413                         rotatespeed[numsprites]=abs(Random()%720)-360;
414                         speed[numsprites]=float(abs(Random()%100))/200+1.5;
415                 }               
416                 numsprites++;
417         }
418 }
419
420 Sprites::Sprites()
421 {
422         cloudtexture = 0;
423         cloudimpacttexture = 0;
424         bloodtexture = 0;
425         flametexture = 0;
426         bloodflametexture = 0;
427         smoketexture = 0;
428         snowflaketexture = 0;
429         shinetexture = 0;
430         splintertexture = 0;
431         leaftexture = 0;
432         toothtexture = 0;
433
434         memset(oldposition, 0, sizeof(oldposition));
435         memset(position, 0, sizeof(position));
436         memset(velocity, 0, sizeof(velocity));
437         memset(size, 0, sizeof(size));
438         memset(initialsize, 0, sizeof(initialsize));
439         memset(type, 0, sizeof(type));
440         memset(special, 0, sizeof(special));
441         memset(color, 0, sizeof(color));
442         memset(opacity, 0, sizeof(opacity));
443         memset(rotation, 0, sizeof(rotation));
444         memset(alivetime, 0, sizeof(alivetime));
445         memset(speed, 0, sizeof(speed));
446         memset(rotatespeed, 0, sizeof(rotatespeed));
447
448         checkdelay = 0;
449         numsprites = 0;
450 }
451 Sprites::~Sprites()
452 {
453         if (toothtexture) glDeleteTextures( 1, &toothtexture );
454         if (cloudtexture) glDeleteTextures( 1, &cloudtexture );
455         if (cloudimpacttexture) glDeleteTextures( 1, &cloudimpacttexture );
456         if (bloodtexture) glDeleteTextures( 1, &bloodtexture );
457         if (flametexture) glDeleteTextures( 1, &flametexture );
458         if (bloodflametexture) glDeleteTextures( 1, &bloodflametexture );
459         if (smoketexture) glDeleteTextures( 1, &smoketexture );
460         if (snowflaketexture) glDeleteTextures( 1, &snowflaketexture );
461         if (shinetexture) glDeleteTextures( 1, &shinetexture );
462         if (splintertexture) glDeleteTextures( 1, &splintertexture );
463         if (leaftexture) glDeleteTextures( 1, &leaftexture );
464 }
465