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 modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 Lugaru 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. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Lugaru. If not, see <http://www.gnu.org/licenses/>.
24 extern float viewdistance;
25 extern float fadestart;
26 extern int environment;
27 extern float texscale;
29 extern float multiplier;
31 extern Terrain terrain;
32 extern Objects objects;
34 extern XYZ viewerfacing;
35 extern int bloodtoggle;
36 extern XYZ windvector;
39 Texture Sprite::cloudtexture;
40 Texture Sprite::cloudimpacttexture;
41 Texture Sprite::bloodtexture;
42 Texture Sprite::flametexture;
43 Texture Sprite::bloodflametexture;
44 Texture Sprite::smoketexture;
45 Texture Sprite::snowflaketexture;
46 Texture Sprite::shinetexture;
47 Texture Sprite::splintertexture;
48 Texture Sprite::leaftexture;
49 Texture Sprite::toothtexture;
51 float Sprite::checkdelay = 0;
53 vector<Sprite*> Sprite::sprites = vector<Sprite*>();
61 static float distancemult;
63 static int lastspecial;
64 static int whichpatchx, whichpatchz;
65 static XYZ start, end, colpoint;
68 static float tempmult;
69 static XYZ difference;
70 static float lightcolor[3];
71 static float viewdistsquared = viewdistance * viewdistance;
72 static XYZ tempviewer;
74 tempviewer = viewer + viewerfacing * 6;
77 lightcolor[0] = light.color[0] * .5 + light.ambient[0];
78 lightcolor[1] = light.color[1] * .5 + light.ambient[1];
79 lightcolor[2] = light.color[2] * .5 + light.ambient[2];
81 checkdelay -= multiplier * 10;
83 if (checkdelay <= 0) {
91 glDisable(GL_LIGHTING);
92 glDisable(GL_CULL_FACE);
93 glEnable(GL_TEXTURE_2D);
95 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
97 glAlphaFunc(GL_GREATER, 0.0001);
98 for (unsigned i = 0; i < sprites.size(); i++) {
99 if (lasttype != sprites[i]->type) {
100 switch (sprites[i]->type) {
105 glAlphaFunc(GL_GREATER, 0.0001);
106 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
109 case cloudimpactsprite:
110 cloudimpacttexture.bind();
113 glAlphaFunc(GL_GREATER, 0.0001);
114 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
118 cloudimpacttexture.bind();
121 glAlphaFunc(GL_GREATER, 0.0001);
122 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
129 glAlphaFunc(GL_GREATER, 0.0001);
130 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
137 glAlphaFunc(GL_GREATER, 0.0001);
138 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
141 case splintersprite :
142 if (lastspecial != sprites[i]->special) {
143 if (sprites[i]->special == 0)
144 splintertexture.bind();
145 if (sprites[i]->special == 1)
147 if (sprites[i]->special == 2)
148 snowflaketexture.bind();
149 if (sprites[i]->special == 3)
153 glAlphaFunc(GL_GREATER, 0.0001);
154 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
159 snowflaketexture.bind();
162 glAlphaFunc(GL_GREATER, 0.0001);
163 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
166 case weaponshinesprite:
170 glAlphaFunc(GL_GREATER, 0.001);
171 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
175 case weaponflamesprite:
177 if (blend || lasttype == bloodflamesprite) {
179 glAlphaFunc(GL_GREATER, 0.3);
180 glBlendFunc(GL_SRC_ALPHA, GL_ONE);
183 case bloodflamesprite:
184 bloodflametexture.bind();
187 glAlphaFunc(GL_GREATER, 0.3);
188 glBlendFunc(GL_ONE, GL_ZERO);
193 if (sprites[i]->type == snowsprite)
194 distancemult = (144 - (distsq(&tempviewer, &sprites[i]->position) - (144 * fadestart)) * (1 / (1 - fadestart))) / 144;
196 distancemult = (viewdistsquared - (distsq(&viewer, &sprites[i]->position) - (viewdistsquared * fadestart)) * (1 / (1 - fadestart))) / viewdistsquared;
197 if (sprites[i]->type == flamesprite) {
198 if (distancemult >= 1)
199 glColor4f(sprites[i]->color[0], sprites[i]->color[1], sprites[i]->color[2], sprites[i]->opacity);
201 glColor4f(sprites[i]->color[0], sprites[i]->color[1], sprites[i]->color[2], sprites[i]->opacity * distancemult);
203 if (distancemult >= 1)
204 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], sprites[i]->opacity);
206 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], sprites[i]->opacity * distancemult);
208 lasttype = sprites[i]->type;
209 lastspecial = sprites[i]->special;
210 glMatrixMode(GL_MODELVIEW);
212 glTranslatef(sprites[i]->position.x, sprites[i]->position.y, sprites[i]->position.z);
213 if ((sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite)) {
214 difference = viewer - sprites[i]->position;
215 Normalise(&difference);
216 glTranslatef(difference.x * sprites[i]->size / 4, difference.y * sprites[i]->size / 4, difference.z * sprites[i]->size / 4);
218 if (sprites[i]->type == snowsprite) {
219 glRotatef(sprites[i]->rotation * .2, 0, .3, 1);
220 glTranslatef(1, 0, 0);
222 glGetFloatv(GL_MODELVIEW_MATRIX, M);
227 glTranslatef(point.x, point.y, point.z);
229 glRotatef(sprites[i]->rotation, 0, 0, 1);
231 if ((sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == bloodflamesprite)) {
232 if (sprites[i]->alivetime < .14)
233 glScalef(sprites[i]->alivetime / .14, sprites[i]->alivetime / .14, sprites[i]->alivetime / .14);
235 if (sprites[i]->type == smoketype || sprites[i]->type == snowsprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == breathsprite) {
236 if (sprites[i]->alivetime < .3) {
237 if (distancemult >= 1)
238 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);
239 if (distancemult < 1)
240 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);
243 if (sprites[i]->type == splintersprite && sprites[i]->special > 0 && sprites[i]->special != 3) {
244 if (sprites[i]->alivetime < .2) {
245 if (distancemult >= 1)
246 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], sprites[i]->alivetime / .2);
248 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], distancemult * sprites[i]->alivetime / .2);
250 if (distancemult >= 1)
251 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
253 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
256 if (sprites[i]->type == splintersprite && (sprites[i]->special == 0 || sprites[i]->special == 3)) {
257 if (distancemult >= 1)
258 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
260 glColor4f(sprites[i]->color[0]*lightcolor[0], sprites[i]->color[1]*lightcolor[1], sprites[i]->color[2]*lightcolor[2], 1);
263 glBegin(GL_TRIANGLES);
264 glTexCoord2f(1.0f, 1.0f);
265 glVertex3f( .5 * sprites[i]->size, .5 * sprites[i]->size, 0.0f);
266 glTexCoord2f(0.0f, 1.0f);
267 glVertex3f(-.5 * sprites[i]->size, .5 * sprites[i]->size, 0.0f);
268 glTexCoord2f(1.0f, 0.0f);
269 glVertex3f( .5 * sprites[i]->size, -.5 * sprites[i]->size, 0.0f);
270 glTexCoord2f(0.0f, 0.0f);
271 glVertex3f(-.5 * sprites[i]->size, -.5 * sprites[i]->size, 0.0f);
272 glTexCoord2f(1.0f, 0.0f);
273 glVertex3f( .5 * sprites[i]->size, -.5 * sprites[i]->size, 0.0f);
274 glTexCoord2f(0.0f, 1.0f);
275 glVertex3f(-.5 * sprites[i]->size, .5 * sprites[i]->size, 0.0f);
279 tempmult = multiplier;
280 for (int i = sprites.size() - 1; i >= 0; i--) {
281 multiplier = tempmult;
282 if (sprites[i]->type != snowsprite) {
283 sprites[i]->position += sprites[i]->velocity * multiplier;
284 sprites[i]->velocity += windvector * multiplier;
286 if (sprites[i]->type == flamesprite || sprites[i]->type == smoketype)
287 sprites[i]->position += windvector * multiplier / 2;
288 if ((sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == bloodflamesprite))
289 multiplier *= sprites[i]->speed * .7;
290 sprites[i]->alivetime += multiplier;
292 if (sprites[i]->type == cloudsprite || sprites[i]->type == cloudimpactsprite) {
293 sprites[i]->opacity -= multiplier / 2;
294 sprites[i]->size += multiplier / 2;
295 sprites[i]->velocity.y += gravity * multiplier * .25;
297 if (sprites[i]->type == breathsprite) {
298 sprites[i]->opacity -= multiplier / 2;
299 sprites[i]->size += multiplier / 2;
300 if (findLength(&sprites[i]->velocity) <= multiplier) {
301 sprites[i]->velocity = 0;
304 slowdown = sprites[i]->velocity * -1;
305 Normalise(&slowdown);
306 slowdown *= multiplier;
307 sprites[i]->velocity += slowdown;
310 if (sprites[i]->type == snowsprite) {
311 sprites[i]->size -= multiplier / 120;
312 sprites[i]->rotation += multiplier * 360;
313 sprites[i]->position.y -= multiplier;
314 sprites[i]->position += windvector * multiplier;
315 if (sprites[i]->position.y < tempviewer.y - 6) sprites[i]->position.y += 12;
316 if (sprites[i]->position.y > tempviewer.y + 6) sprites[i]->position.y -= 12;
317 if (sprites[i]->position.z < tempviewer.z - 6) sprites[i]->position.z += 12;
318 if (sprites[i]->position.z > tempviewer.z + 6) sprites[i]->position.z -= 12;
319 if (sprites[i]->position.x < tempviewer.x - 6) sprites[i]->position.x += 12;
320 if (sprites[i]->position.x > tempviewer.x + 6) sprites[i]->position.x -= 12;
322 if (sprites[i]->type == bloodsprite) {
324 sprites[i]->rotation += multiplier * 100;
325 sprites[i]->velocity.y += gravity * multiplier;
327 XYZ where, startpoint, endpoint, movepoint, footpoint;
331 for (unsigned j = 0; j < Person::players.size(); j++) {
332 if (!spritehit && Person::players[j]->dead && sprites[i]->alivetime > .1) {
333 where = sprites[i]->oldposition;
334 where -= Person::players[j]->coords;
335 if (!Person::players[j]->skeleton.free)
336 where = DoRotation(where, 0, -Person::players[j]->yaw, 0);
338 where = sprites[i]->position;
339 where -= Person::players[j]->coords;
340 if (!Person::players[j]->skeleton.free)
341 where = DoRotation(where, 0, -Person::players[j]->yaw, 0);
346 whichtri = Person::players[j]->skeleton.drawmodel.LineCheck(&startpoint, &endpoint, &footpoint, &movepoint, &rotationpoint);
347 if (whichtri != -1) {
349 Person::players[j]->DoBloodBigWhere(0, 160, sprites[i]->oldposition);
355 whichpatchx = sprites[i]->position.x / (terrain.size / subdivision * terrain.scale);
356 whichpatchz = sprites[i]->position.z / (terrain.size / subdivision * terrain.scale);
357 if (whichpatchx > 0 && whichpatchz > 0 && whichpatchx < subdivision && whichpatchz < subdivision)
358 if (terrain.patchobjectnum[whichpatchx][whichpatchz]) {
360 for (int j = 0; j < terrain.patchobjectnum[whichpatchx][whichpatchz]; j++) {
361 k = terrain.patchobjects[whichpatchx][whichpatchz][j];
362 start = sprites[i]->oldposition;
363 end = sprites[i]->position;
365 if (objects.model[k].LineCheck(&start, &end, &colpoint, &objects.position[k], &objects.yaw[k]) != -1) {
366 if (detail == 2 || (detail == 1 && abs(Random() % 4) == 0) || (detail == 0 && abs(Random() % 8) == 0))
367 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);
374 if (sprites[i]->position.y < terrain.getHeight(sprites[i]->position.x, sprites[i]->position.z)) {
375 terrain.MakeDecal(blooddecalfast, sprites[i]->position, sprites[i]->size * 1.6/*+abs((float)(Random()%100))/2400*/, .6, Random() % 360);
380 if (sprites[i]->type == splintersprite) {
381 sprites[i]->rotation += sprites[i]->rotatespeed * multiplier;
382 sprites[i]->opacity -= multiplier / 2;
383 if (sprites[i]->special == 0 || sprites[i]->special == 2 || sprites[i]->special == 3)
384 sprites[i]->velocity.y += gravity * multiplier;
385 if (sprites[i]->special == 1)
386 sprites[i]->velocity.y += gravity * multiplier * .5;
388 if (sprites[i]->type == flamesprite || sprites[i]->type == weaponflamesprite || sprites[i]->type == weaponshinesprite || sprites[i]->type == bloodflamesprite) {
389 sprites[i]->rotation += multiplier * sprites[i]->rotatespeed;
390 sprites[i]->opacity -= multiplier * 5 / 4;
391 if (sprites[i]->type != weaponshinesprite && sprites[i]->type != bloodflamesprite)
392 if (sprites[i]->opacity < .5 && sprites[i]->opacity + multiplier * 5 / 4 >= .5 && (abs(Random() % 4) == 0 || (sprites[i]->initialsize > 2 && Random() % 2 == 0)))
393 MakeSprite(smoketype, sprites[i]->position, sprites[i]->velocity, .9, .9, .6, sprites[i]->size * 1.2, .4);
394 if (sprites[i]->alivetime > .14 && (sprites[i]->type == flamesprite)) {
395 sprites[i]->velocity = 0;
396 sprites[i]->velocity.y = 1.5;
399 if (sprites[i]->type == smoketype) {
400 sprites[i]->opacity -= multiplier / 3 / sprites[i]->initialsize;
401 sprites[i]->color[0] -= multiplier;
402 sprites[i]->color[1] -= multiplier;
403 sprites[i]->color[2] -= multiplier;
404 if (sprites[i]->color[0] < .6)
405 sprites[i]->color[0] = .6;
406 if (sprites[i]->color[1] < .6)
407 sprites[i]->color[1] = .6;
408 if (sprites[i]->color[2] < .6)
409 sprites[i]->color[2] = .6;
410 sprites[i]->size += multiplier;
411 sprites[i]->velocity = 0;
412 sprites[i]->velocity.y = 1.5;
413 sprites[i]->rotation += multiplier * sprites[i]->rotatespeed / 5;
415 if (sprites[i]->opacity <= 0 || sprites[i]->size <= 0)
419 for (int i = sprites.size() - 1; i >= 0; i--) {
420 sprites[i]->oldposition = sprites[i]->position;
422 glAlphaFunc(GL_GREATER, 0.0001);
423 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
426 void Sprite::DeleteSprite(int i)
428 sprites.erase(sprites.begin() + i);
431 void Sprite::MakeSprite(int atype, XYZ where, XYZ avelocity, float red, float green, float blue, float asize, float aopacity)
433 if (sprites.size() < max_sprites - 1) {
434 sprites.push_back(new Sprite());
435 if ((atype != bloodsprite && atype != bloodflamesprite) || bloodtoggle) {
436 sprites.back()->special = 0;
437 sprites.back()->type = atype;
438 sprites.back()->position = where;
439 sprites.back()->oldposition = where;
440 sprites.back()->velocity = avelocity;
441 sprites.back()->alivetime = 0;
442 sprites.back()->opacity = aopacity;
443 sprites.back()->size = asize;
444 sprites.back()->initialsize = asize;
445 sprites.back()->color[0] = red;
446 sprites.back()->color[1] = green;
447 sprites.back()->color[2] = blue;
448 sprites.back()->rotatespeed = abs(Random() % 720) - 360;
449 sprites.back()->speed = float(abs(Random() % 100)) / 200 + 1.5;
463 memset(color, 0, sizeof(color));
471 void Sprite::clearTextures()
473 toothtexture.destroy();
474 cloudtexture.destroy();
475 cloudimpacttexture.destroy();
476 bloodtexture.destroy();
477 flametexture.destroy();
478 bloodflametexture.destroy();
479 smoketexture.destroy();
480 snowflaketexture.destroy();
481 shinetexture.destroy();
482 splintertexture.destroy();
483 leaftexture.destroy();