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.
26 extern float viewdistance;
27 extern float fadestart;
28 extern int environment;
29 extern float texscale;
31 extern float multiplier;
33 extern Terrain terrain;
34 extern Objects objects;
36 extern XYZ viewerfacing;
37 extern int bloodtoggle;
38 extern XYZ windvector;
41 Texture Sprite::cloudtexture;
42 Texture Sprite::cloudimpacttexture;
43 Texture Sprite::bloodtexture;
44 Texture Sprite::flametexture;
45 Texture Sprite::bloodflametexture;
46 Texture Sprite::smoketexture;
47 Texture Sprite::snowflaketexture;
48 Texture Sprite::shinetexture;
49 Texture Sprite::splintertexture;
50 Texture Sprite::leaftexture;
51 Texture Sprite::toothtexture;
53 float Sprite::checkdelay = 0;
55 vector<Sprite*> Sprite::sprites = vector<Sprite*>();
63 static float distancemult;
65 static int lastspecial;
66 static int whichpatchx, whichpatchz;
67 static XYZ start, end, colpoint;
70 static float tempmult;
71 static XYZ difference;
72 static float lightcolor[3];
73 static float viewdistsquared = viewdistance * viewdistance;
74 static XYZ tempviewer;
76 tempviewer = viewer + viewerfacing * 6;
79 lightcolor[0] = light.color[0] * .5 + light.ambient[0];
80 lightcolor[1] = light.color[1] * .5 + light.ambient[1];
81 lightcolor[2] = light.color[2] * .5 + light.ambient[2];
83 checkdelay -= multiplier * 10;
85 if (checkdelay <= 0) {
93 glDisable(GL_LIGHTING);
94 glDisable(GL_CULL_FACE);
95 glEnable(GL_TEXTURE_2D);
97 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
99 glAlphaFunc(GL_GREATER, 0.0001);
100 for (i = 0; i < sprites.size(); i++) {
101 if (lasttype != sprites[i]->type) {
102 switch (sprites[i]->type) {
107 glAlphaFunc(GL_GREATER, 0.0001);
108 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
111 case cloudimpactsprite:
112 cloudimpacttexture.bind();
115 glAlphaFunc(GL_GREATER, 0.0001);
116 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
120 cloudimpacttexture.bind();
123 glAlphaFunc(GL_GREATER, 0.0001);
124 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
131 glAlphaFunc(GL_GREATER, 0.0001);
132 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
139 glAlphaFunc(GL_GREATER, 0.0001);
140 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
143 case splintersprite :
144 if (lastspecial != sprites[i]->special) {
145 if (sprites[i]->special == 0)splintertexture.bind();
146 if (sprites[i]->special == 1)leaftexture.bind();
147 if (sprites[i]->special == 2)snowflaketexture.bind();
148 if (sprites[i]->special == 3)toothtexture.bind();
151 glAlphaFunc(GL_GREATER, 0.0001);
152 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
157 snowflaketexture.bind();
160 glAlphaFunc(GL_GREATER, 0.0001);
161 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
164 case weaponshinesprite:
168 glAlphaFunc(GL_GREATER, 0.001);
169 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
173 case weaponflamesprite:
175 if (blend || lasttype == bloodflamesprite) {
177 glAlphaFunc(GL_GREATER, 0.3);
178 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
181 case bloodflamesprite:
182 bloodflametexture.bind();
185 glAlphaFunc(GL_GREATER, 0.3);
186 glBlendFunc(GL_ONE, GL_ZERO);
191 if (sprites[i]->type == snowsprite)
192 distancemult = (144 - (distsq(&tempviewer, &sprites[i]->position) - (144 * fadestart)) * (1 / (1 - fadestart))) / 144;
194 distancemult = (viewdistsquared - (distsq(&viewer, &sprites[i]->position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
195 if (sprites[i]->type == flamesprite) {
196 if (distancemult >= 1) glColor4f(sprites[i]->color[0], sprites[i]->color[1], sprites[i]->color[2], sprites[i]->opacity);
197 else glColor4f(sprites[i]->color[0], sprites[i]->color[1], sprites[i]->color[2], sprites[i]->opacity * distancemult);
199 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);
200 else glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], sprites[i]->opacity * distancemult);
202 lasttype = sprites[i]->type;
203 lastspecial = sprites[i]->special;
204 glMatrixMode(GL_MODELVIEW); // Select The Modelview Matrix
206 glTranslatef(sprites[i]->position.x, sprites[i]->position.y, sprites[i]->position.z);
207 if ((sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite)) {
208 difference = viewer - sprites[i]->position;
209 Normalise(&difference);
210 glTranslatef(difference.x * sprites[i]->size / 4, difference.y * sprites[i]->size / 4, difference.z * sprites[i]->size / 4);
212 if (sprites[i]->type == snowsprite) {
213 glRotatef(sprites[i]->rotation * .2, 0, .3, 1);
214 glTranslatef(1, 0, 0);
216 glGetFloatv(GL_MODELVIEW_MATRIX, M);
221 glTranslatef(point.x, point.y, point.z);
223 glRotatef(sprites[i]->rotation, 0, 0, 1);
225 if ((sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == bloodflamesprite)) {
226 if (sprites[i]->alivetime < .14)glScalef(sprites[i]->alivetime / .14, sprites[i]->alivetime / .14, sprites[i]->alivetime / .14);
228 if (sprites[i]->type == smoketype || sprites[i]->type == snowsprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == breathsprite) {
229 if (sprites[i]->alivetime < .3) {
230 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);
231 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);
234 if (sprites[i]->type == splintersprite && sprites[i]->special > 0 && sprites[i]->special != 3) {
235 if (sprites[i]->alivetime < .2) {
236 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);
237 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);
239 if (distancemult >= 1) glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
240 else glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
243 if (sprites[i]->type == splintersprite && (sprites[i]->special == 0 || sprites[i]->special == 3)) {
244 if (distancemult >= 1) glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
245 else glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
248 glBegin(GL_TRIANGLES);
249 glTexCoord2f(1.0f, 1.0f);
250 glVertex3f( .5 * sprites[i]->size, .5 * sprites[i]->size, 0.0f);
251 glTexCoord2f(0.0f, 1.0f);
252 glVertex3f(-.5 * sprites[i]->size, .5 * sprites[i]->size, 0.0f);
253 glTexCoord2f(1.0f, 0.0f);
254 glVertex3f( .5 * sprites[i]->size, -.5 * sprites[i]->size, 0.0f);
255 glTexCoord2f(0.0f, 0.0f);
256 glVertex3f(-.5 * sprites[i]->size, -.5 * sprites[i]->size, 0.0f);
257 glTexCoord2f(1.0f, 0.0f);
258 glVertex3f( .5 * sprites[i]->size, -.5 * sprites[i]->size, 0.0f);
259 glTexCoord2f(0.0f, 1.0f);
260 glVertex3f(-.5 * sprites[i]->size, .5 * sprites[i]->size, 0.0f);
264 tempmult = multiplier;
265 for (i = sprites.size() - 1; i >= 0; i--) {
266 multiplier = tempmult;
267 if (sprites[i]->type != snowsprite) {
268 sprites[i]->position += sprites[i]->velocity * multiplier;
269 sprites[i]->velocity += windvector * multiplier;
271 if (sprites[i]->type == flamesprite || sprites[i]->type == smoketype)sprites[i]->position += windvector * multiplier / 2;
272 if ((sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == bloodflamesprite))
273 multiplier *= sprites[i]->speed * .7;
274 sprites[i]->alivetime += multiplier;
276 if (sprites[i]->type == cloudsprite || sprites[i]->type == cloudimpactsprite) {
277 sprites[i]->opacity -= multiplier / 2;
278 sprites[i]->size += multiplier / 2;
279 sprites[i]->velocity.y += gravity * multiplier * .25;
281 if (sprites[i]->type == breathsprite) {
282 sprites[i]->opacity -= multiplier / 2;
283 sprites[i]->size += multiplier / 2;
284 if (findLength(&sprites[i]->velocity) <= multiplier)sprites[i]->velocity = 0;
287 slowdown = sprites[i]->velocity * -1;
288 Normalise(&slowdown);
289 slowdown *= multiplier;
290 sprites[i]->velocity += slowdown;
293 if (sprites[i]->type == snowsprite) {
294 sprites[i]->size -= multiplier / 120;
295 sprites[i]->rotation += multiplier * 360;
296 sprites[i]->position.y -= multiplier;
297 sprites[i]->position += windvector * multiplier;
298 if (sprites[i]->position.y < tempviewer.y - 6)sprites[i]->position.y += 12;
299 if (sprites[i]->position.y > tempviewer.y + 6)sprites[i]->position.y -= 12;
300 if (sprites[i]->position.z < tempviewer.z - 6)sprites[i]->position.z += 12;
301 if (sprites[i]->position.z > tempviewer.z + 6)sprites[i]->position.z -= 12;
302 if (sprites[i]->position.x < tempviewer.x - 6)sprites[i]->position.x += 12;
303 if (sprites[i]->position.x > tempviewer.x + 6)sprites[i]->position.x -= 12;
305 if (sprites[i]->type == bloodsprite) {
307 sprites[i]->rotation += multiplier * 100;
308 sprites[i]->velocity.y += gravity * multiplier;
310 XYZ where, startpoint, endpoint, movepoint, footpoint;
314 for (j = 0; j < numplayers; j++) {
315 if (!spritehit && player[j].dead && sprites[i]->alivetime > .1) {
316 where = sprites[i]->oldposition;
317 where -= player[j].coords;
318 if (!player[j].skeleton.free)where = DoRotation(where, 0, -player[j].yaw, 0);
320 where = sprites[i]->position;
321 where -= player[j].coords;
322 if (!player[j].skeleton.free)where = DoRotation(where, 0, -player[j].yaw, 0);
327 whichtri = player[j].skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
328 if (whichtri != -1) {
330 player[j].DoBloodBigWhere(0, 160, sprites[i]->oldposition);
336 whichpatchx = sprites[i]->position.x / (terrain.size / subdivision * terrain.scale);
337 whichpatchz = sprites[i]->position.z / (terrain.size / subdivision * terrain.scale);
338 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision)
339 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) {
341 for (j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
342 k = terrain.patchobjects[whichpatchx][whichpatchz][j];
343 start = sprites[i]->oldposition;
344 end = sprites[i]->position;
346 if (objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]) != -1) {
347 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.yaw[k], 0), sprites[i]->size * 1.6/*+abs((float)(Random()%100))/2400*/, .5, Random() % 360);
354 if (sprites[i]->position.y < terrain.getHeight(sprites[i]->position.x, sprites[i]->position.z)) {
355 terrain.MakeDecal(blooddecalfast, sprites[i]->position, sprites[i]->size * 1.6/*+abs((float)(Random()%100))/2400*/, .6, Random() % 360);
360 if (sprites[i]->type == splintersprite) {
361 sprites[i]->rotation += sprites[i]->rotatespeed * multiplier;
362 sprites[i]->opacity -= multiplier / 2;
363 if (sprites[i]->special == 0 || sprites[i]->special == 2 || sprites[i]->special == 3)sprites[i]->velocity.y += gravity * multiplier;
364 if (sprites[i]->special == 1)sprites[i]->velocity.y += gravity * multiplier * .5;
366 if (sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == bloodflamesprite) {
367 sprites[i]->rotation += multiplier * sprites[i]->rotatespeed;
368 sprites[i]->opacity -= multiplier * 5 / 4;
369 if (sprites[i]->type != weaponshinesprite && sprites[i]->type != bloodflamesprite)
370 if (sprites[i]->opacity < .5 && sprites[i]->opacity + multiplier * 5 / 4 >= .5 && (abs(Random() % 4) == 0 || (sprites[i]->initialsize > 2 && Random() % 2 == 0)))
371 MakeSprite(smoketype, sprites[i]->position, sprites[i]->velocity, .9, .9, .6, sprites[i]->size * 1.2, .4);
372 if (sprites[i]->alivetime > .14 && (sprites[i]->type == flamesprite)) {
373 sprites[i]->velocity = 0;
374 sprites[i]->velocity.y = 1.5;
377 if (sprites[i]->type == smoketype) {
378 sprites[i]->opacity -= multiplier / 3 / sprites[i]->initialsize;
379 sprites[i]->color[0] -= multiplier;
380 sprites[i]->color[1] -= multiplier;
381 sprites[i]->color[2] -= multiplier;
382 if (sprites[i]->color[0] < .6)sprites[i]->color[0] = .6;
383 if (sprites[i]->color[1] < .6)sprites[i]->color[1] = .6;
384 if (sprites[i]->color[2] < .6)sprites[i]->color[2] = .6;
385 sprites[i]->size += multiplier;
386 sprites[i]->velocity = 0;
387 sprites[i]->velocity.y = 1.5;
388 sprites[i]->rotation += multiplier * sprites[i]->rotatespeed / 5;
390 if (sprites[i]->opacity <= 0 || sprites[i]->size <= 0)DeleteSprite(i);
393 for (i = sprites.size() - 1; i >= 0; i--) {
394 sprites[i]->oldposition = sprites[i]->position;
396 glAlphaFunc(GL_GREATER, 0.0001);
397 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
400 void Sprite::DeleteSprite(int i)
402 sprites.erase(sprites.begin() + i);
405 void Sprite::MakeSprite(int atype, XYZ where, XYZ avelocity, float red, float green, float blue, float asize, float aopacity)
407 if (sprites.size() < max_sprites - 1) {
408 sprites.push_back(new Sprite());
409 if ((atype != bloodsprite && atype != bloodflamesprite) || bloodtoggle) {
410 sprites.back()->special = 0;
411 sprites.back()->type = atype;
412 sprites.back()->position = where;
413 sprites.back()->oldposition = where;
414 sprites.back()->velocity = avelocity;
415 sprites.back()->alivetime = 0;
416 sprites.back()->opacity = aopacity;
417 sprites.back()->size = asize;
418 sprites.back()->initialsize = asize;
419 sprites.back()->color[0] = red;
420 sprites.back()->color[1] = green;
421 sprites.back()->color[2] = blue;
422 sprites.back()->rotatespeed = abs(Random() % 720) - 360;
423 sprites.back()->speed = float(abs(Random() % 100)) / 200 + 1.5;
437 memset(color, 0, sizeof(color));
445 void Sprite::clearTextures()
447 toothtexture.destroy();
448 cloudtexture.destroy();
449 cloudimpacttexture.destroy();
450 bloodtexture.destroy();
451 flametexture.destroy();
452 bloodflametexture.destroy();
453 smoketexture.destroy();
454 snowflaketexture.destroy();
455 shinetexture.destroy();
456 splintertexture.destroy();
457 leaftexture.destroy();