2 Copyright (C) 2003, 2010 - Wolfire Games
4 This file is part of Lugaru.
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.
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.
15 See the GNU General Public License for more details.
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.
25 extern float viewdistance;
26 extern float fadestart;
27 extern int environment;
28 extern float texscale;
30 extern float multiplier;
32 extern Terrain terrain;
33 extern Objects objects;
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];
43 GLuint Sprite::cloudtexture = 0;
44 GLuint Sprite::cloudimpacttexture = 0;
45 GLuint Sprite::bloodtexture = 0;
46 GLuint Sprite::flametexture = 0;
47 GLuint Sprite::bloodflametexture = 0;
48 GLuint Sprite::smoketexture = 0;
49 GLuint Sprite::snowflaketexture = 0;
50 GLuint Sprite::shinetexture = 0;
51 GLuint Sprite::splintertexture = 0;
52 GLuint Sprite::leaftexture = 0;
53 GLuint Sprite::toothtexture = 0;
55 float Sprite::checkdelay = 0;
57 vector<Sprite*> Sprite::sprites = vector<Sprite*>();
65 static float distancemult;
67 static int lastspecial;
68 static int whichpatchx,whichpatchz;
69 static XYZ start,end,colpoint;
72 static float tempmult;
73 static XYZ difference;
74 static float lightcolor[3];
75 static float viewdistsquared=viewdistance*viewdistance;
76 static XYZ tempviewer;
78 tempviewer=viewer+viewerfacing*6;
81 lightcolor[0]=light.color[0]*.5+light.ambient[0];
82 lightcolor[1]=light.color[1]*.5+light.ambient[1];
83 lightcolor[2]=light.color[2]*.5+light.ambient[2];
85 checkdelay-=multiplier*10;
95 glDisable(GL_LIGHTING);
96 glDisable(GL_CULL_FACE);
97 glEnable(GL_TEXTURE_2D);
99 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
101 glAlphaFunc(GL_GREATER, 0.0001);
102 for(i=0;i<sprites.size();i++){
103 if(lasttype!=sprites[i]->type) {
104 switch(sprites[i]->type) {
106 glBindTexture( GL_TEXTURE_2D, cloudtexture);
109 glAlphaFunc(GL_GREATER, 0.0001);
110 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
113 case cloudimpactsprite:
114 glBindTexture( GL_TEXTURE_2D, cloudimpacttexture);
117 glAlphaFunc(GL_GREATER, 0.0001);
118 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
122 glBindTexture( GL_TEXTURE_2D, cloudimpacttexture);
125 glAlphaFunc(GL_GREATER, 0.0001);
126 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
130 glBindTexture( GL_TEXTURE_2D, smoketexture);
133 glAlphaFunc(GL_GREATER, 0.0001);
134 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
138 glBindTexture( GL_TEXTURE_2D, bloodtexture);
141 glAlphaFunc(GL_GREATER, 0.0001);
142 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
145 case splintersprite :
146 if(lastspecial!=sprites[i]->special) {
147 if(sprites[i]->special==0)glBindTexture( GL_TEXTURE_2D, splintertexture);
148 if(sprites[i]->special==1)glBindTexture( GL_TEXTURE_2D, leaftexture);
149 if(sprites[i]->special==2)glBindTexture( GL_TEXTURE_2D, snowflaketexture);
150 if(sprites[i]->special==3)glBindTexture( GL_TEXTURE_2D, toothtexture);
153 glAlphaFunc(GL_GREATER, 0.0001);
154 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
159 glBindTexture( GL_TEXTURE_2D, snowflaketexture);
162 glAlphaFunc(GL_GREATER, 0.0001);
163 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
166 case weaponshinesprite:
167 glBindTexture( GL_TEXTURE_2D, shinetexture);
170 glAlphaFunc(GL_GREATER, 0.001);
171 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
175 case weaponflamesprite:
176 glBindTexture( GL_TEXTURE_2D, flametexture);
177 if(blend||lasttype==bloodflamesprite){
179 glAlphaFunc(GL_GREATER, 0.3);
180 glBlendFunc(GL_SRC_ALPHA,GL_ONE);
183 case bloodflamesprite:
184 glBindTexture( GL_TEXTURE_2D, bloodflametexture);
187 glAlphaFunc(GL_GREATER, 0.3);
188 glBlendFunc(GL_ONE,GL_ZERO);
193 if(sprites[i]->type==snowsprite)
194 distancemult=(144-(findDistancefast(&tempviewer,&sprites[i]->position)-(144*fadestart))*(1/(1-fadestart)))/144;
196 distancemult=(viewdistsquared-(findDistancefast(&viewer,&sprites[i]->position)-(viewdistsquared*fadestart))*(1/(1-fadestart)))/viewdistsquared;
197 if(sprites[i]->type==flamesprite){
198 if(distancemult>=1) glColor4f(sprites[i]->color[0],sprites[i]->color[1],sprites[i]->color[2],sprites[i]->opacity);
199 else glColor4f(sprites[i]->color[0],sprites[i]->color[1],sprites[i]->color[2],sprites[i]->opacity*distancemult);
201 if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity);
202 else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity*distancemult);
204 lasttype=sprites[i]->type;
205 lastspecial=sprites[i]->special;
206 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
208 glTranslatef(sprites[i]->position.x,sprites[i]->position.y,sprites[i]->position.z);
209 if((sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite)){
210 difference=viewer-sprites[i]->position;
211 Normalise(&difference);
212 glTranslatef(difference.x*sprites[i]->size/4, difference.y*sprites[i]->size/4, difference.z*sprites[i]->size/4);
214 if(sprites[i]->type==snowsprite){
215 glRotatef(sprites[i]->rotation*.2,0,.3,1);
218 glGetFloatv(GL_MODELVIEW_MATRIX,M);
223 glTranslatef(point.x, point.y, point.z);
225 glRotatef(sprites[i]->rotation,0,0,1);
227 if((sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==bloodflamesprite)){
228 if(sprites[i]->alivetime<.14)glScalef(sprites[i]->alivetime/.14,sprites[i]->alivetime/.14,sprites[i]->alivetime/.14);
230 if(sprites[i]->type==smoketype||sprites[i]->type==snowsprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==breathsprite){
231 if(sprites[i]->alivetime<.3){
232 if(distancemult>=1)glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity*sprites[i]->alivetime/.3);
233 if(distancemult<1)glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->opacity*distancemult*sprites[i]->alivetime/.3);
236 if(sprites[i]->type==splintersprite&&sprites[i]->special>0&&sprites[i]->special!=3){
237 if(sprites[i]->alivetime<.2){
238 if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],sprites[i]->alivetime/.2);
239 else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],distancemult*sprites[i]->alivetime/.2);
242 if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
243 else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
246 if(sprites[i]->type==splintersprite&&(sprites[i]->special==0||sprites[i]->special==3)){
247 if(distancemult>=1) glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
248 else glColor4f(sprites[i]->color[0]*lightcolor[0],sprites[i]->color[1]*lightcolor[1],sprites[i]->color[2]*lightcolor[2],1);
251 glBegin(GL_TRIANGLES);
252 glTexCoord2f(1.0f, 1.0f); glVertex3f( .5*sprites[i]->size, .5*sprites[i]->size, 0.0f);
253 glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*sprites[i]->size, .5*sprites[i]->size, 0.0f);
254 glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*sprites[i]->size,-.5*sprites[i]->size, 0.0f);
255 glTexCoord2f(0.0f, 0.0f); glVertex3f(-.5*sprites[i]->size,-.5*sprites[i]->size, 0.0f);
256 glTexCoord2f(1.0f, 0.0f); glVertex3f( .5*sprites[i]->size, -.5*sprites[i]->size, 0.0f);
257 glTexCoord2f(0.0f, 1.0f); glVertex3f(-.5*sprites[i]->size, .5*sprites[i]->size, 0.0f);
262 for(i=sprites.size()-1;i>=0;i--){
264 if(sprites[i]->type!=snowsprite) {
265 sprites[i]->position+=sprites[i]->velocity*multiplier;
266 sprites[i]->velocity+=windvector*multiplier;
268 if(sprites[i]->type==flamesprite||sprites[i]->type==smoketype)sprites[i]->position+=windvector*multiplier/2;
269 if((sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==bloodflamesprite))
270 multiplier*=sprites[i]->speed*.7;
271 sprites[i]->alivetime+=multiplier;
273 if(sprites[i]->type==cloudsprite||sprites[i]->type==cloudimpactsprite){
274 sprites[i]->opacity-=multiplier/2;
275 sprites[i]->size+=multiplier/2;
276 sprites[i]->velocity.y+=gravity*multiplier*.25;
278 if(sprites[i]->type==breathsprite){
279 sprites[i]->opacity-=multiplier/2;
280 sprites[i]->size+=multiplier/2;
281 if(findLength(&sprites[i]->velocity)<=multiplier)sprites[i]->velocity=0;
284 slowdown=sprites[i]->velocity*-1;
285 Normalise(&slowdown);
286 slowdown*=multiplier;
287 sprites[i]->velocity+=slowdown;
290 if(sprites[i]->type==snowsprite){
291 sprites[i]->size-=multiplier/120;
292 sprites[i]->rotation+=multiplier*360;
293 sprites[i]->position.y-=multiplier;
294 sprites[i]->position+=windvector*multiplier;
295 if(sprites[i]->position.y<tempviewer.y-6)sprites[i]->position.y+=12;
296 if(sprites[i]->position.y>tempviewer.y+6)sprites[i]->position.y-=12;
297 if(sprites[i]->position.z<tempviewer.z-6)sprites[i]->position.z+=12;
298 if(sprites[i]->position.z>tempviewer.z+6)sprites[i]->position.z-=12;
299 if(sprites[i]->position.x<tempviewer.x-6)sprites[i]->position.x+=12;
300 if(sprites[i]->position.x>tempviewer.x+6)sprites[i]->position.x-=12;
302 if(sprites[i]->type==bloodsprite){
304 sprites[i]->rotation+=multiplier*100;
305 sprites[i]->velocity.y+=gravity*multiplier;
307 XYZ where,startpoint,endpoint,movepoint,footpoint;
311 for(j=0;j<numplayers;j++){
312 if(!spritehit&&player[j].dead&&sprites[i]->alivetime>.1){
313 where=sprites[i]->oldposition;
314 where-=player[j].coords;
315 if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].rotation,0);
317 where=sprites[i]->position;
318 where-=player[j].coords;
319 if(!player[j].skeleton.free)where=DoRotation(where,0,-player[j].rotation,0);
324 whichtri=player[j].skeleton.drawmodel.LineCheck(&startpoint,&endpoint, &footpoint, &movepoint, &rotationpoint);
327 player[j].DoBloodBigWhere(0,160,sprites[i]->oldposition);
333 whichpatchx=sprites[i]->position.x/(terrain.size/subdivision*terrain.scale*terraindetail);
334 whichpatchz=sprites[i]->position.z/(terrain.size/subdivision*terrain.scale*terraindetail);
335 if(whichpatchx>0&&whichpatchz>0&&whichpatchx<subdivision&&whichpatchz<subdivision)
336 if(terrain.patchobjectnum[whichpatchx][whichpatchz]){
338 for(j=0;j<terrain.patchobjectnum[whichpatchx][whichpatchz];j++){
339 k=terrain.patchobjects[whichpatchx][whichpatchz][j];
340 start=sprites[i]->oldposition;
341 end=sprites[i]->position;
343 if(objects.model[k].LineCheck(&start,&end,&colpoint,&objects.position[k],&objects.rotation[k])!=-1){
344 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),sprites[i]->size*1.6/*+abs((float)(Random()%100))/2400*/,.5,Random()%360);
351 if(sprites[i]->position.y<terrain.getHeight(sprites[i]->position.x,sprites[i]->position.z)){
352 terrain.MakeDecal(blooddecalfast,sprites[i]->position,sprites[i]->size*1.6/*+abs((float)(Random()%100))/2400*/,.6,Random()%360);
357 if(sprites[i]->type==splintersprite){
358 sprites[i]->rotation+=sprites[i]->rotatespeed*multiplier;
359 sprites[i]->opacity-=multiplier/2;
360 if(sprites[i]->special==0||sprites[i]->special==2||sprites[i]->special==3)sprites[i]->velocity.y+=gravity*multiplier;
361 if(sprites[i]->special==1)sprites[i]->velocity.y+=gravity*multiplier*.5;
363 if(sprites[i]->type==flamesprite||sprites[i]->type==weaponflamesprite||sprites[i]->type==weaponshinesprite||sprites[i]->type==bloodflamesprite){
364 sprites[i]->rotation+=multiplier*sprites[i]->rotatespeed;
365 sprites[i]->opacity-=multiplier*5/4;
366 if(sprites[i]->type!=weaponshinesprite&&sprites[i]->type!=bloodflamesprite)
367 if(sprites[i]->opacity<.5&&sprites[i]->opacity+multiplier*5/4>=.5&&(abs(Random()%4)==0||(sprites[i]->initialsize>2&&Random()%2==0)))
368 MakeSprite(smoketype, sprites[i]->position,sprites[i]->velocity, .9,.9,.6, sprites[i]->size*1.2, .4);
369 if(sprites[i]->alivetime>.14&&(sprites[i]->type==flamesprite)){
370 sprites[i]->velocity=0;
371 sprites[i]->velocity.y=1.5;
374 if(sprites[i]->type==smoketype){
375 sprites[i]->opacity-=multiplier/3/sprites[i]->initialsize;
376 sprites[i]->color[0]-=multiplier;
377 sprites[i]->color[1]-=multiplier;
378 sprites[i]->color[2]-=multiplier;
379 if(sprites[i]->color[0]<.6)sprites[i]->color[0]=.6;
380 if(sprites[i]->color[1]<.6)sprites[i]->color[1]=.6;
381 if(sprites[i]->color[2]<.6)sprites[i]->color[2]=.6;
382 sprites[i]->size+=multiplier;
383 sprites[i]->velocity=0;
384 sprites[i]->velocity.y=1.5;
385 sprites[i]->rotation+=multiplier*sprites[i]->rotatespeed/5;
387 if(sprites[i]->opacity<=0||sprites[i]->size<=0)DeleteSprite(i);
390 for(i=sprites.size()-1;i>=0;i--){
391 sprites[i]->oldposition=sprites[i]->position;
393 glAlphaFunc(GL_GREATER, 0.0001);
394 glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
397 void Sprite::DeleteSprite(int i)
399 sprites.erase(sprites.begin()+i);
402 void Sprite::MakeSprite(int atype, XYZ where, XYZ avelocity, float red, float green, float blue, float asize, float aopacity){
403 if(sprites.size()<max_sprites-1){
404 sprites.push_back(new Sprite());
405 if((atype!=bloodsprite&&atype!=bloodflamesprite)||bloodtoggle){
406 sprites.back()->special=0;
407 sprites.back()->type=atype;
408 sprites.back()->position=where;
409 sprites.back()->oldposition=where;
410 sprites.back()->velocity=avelocity;
411 sprites.back()->alivetime=0;
412 sprites.back()->opacity=aopacity;
413 sprites.back()->size=asize;
414 sprites.back()->initialsize=asize;
415 sprites.back()->color[0]=red;
416 sprites.back()->color[1]=green;
417 sprites.back()->color[2]=blue;
418 sprites.back()->rotatespeed=abs(Random()%720)-360;
419 sprites.back()->speed=float(abs(Random()%100))/200+1.5;
433 memset(color,0,sizeof(color));
441 void Sprite::clearTextures()
443 if (toothtexture) glDeleteTextures( 1, &toothtexture );
444 if (cloudtexture) glDeleteTextures( 1, &cloudtexture );
445 if (cloudimpacttexture) glDeleteTextures( 1, &cloudimpacttexture );
446 if (bloodtexture) glDeleteTextures( 1, &bloodtexture );
447 if (flametexture) glDeleteTextures( 1, &flametexture );
448 if (bloodflametexture) glDeleteTextures( 1, &bloodflametexture );
449 if (smoketexture) glDeleteTextures( 1, &smoketexture );
450 if (snowflaketexture) glDeleteTextures( 1, &snowflaketexture );
451 if (shinetexture) glDeleteTextures( 1, &shinetexture );
452 if (splintertexture) glDeleteTextures( 1, &splintertexture );
453 if (leaftexture) glDeleteTextures( 1, &leaftexture );