File: client\cl_newfx.c

    1 /*
    2 Copyright (C) 1997-2001 Id Software, Inc.
    3 
    4 This program is free software; you can redistribute it and/or
    5 modify it under the terms of the GNU General Public License
    6 as published by the Free Software Foundation; either version 2
    7 of the License, or (at your option) any later version.
    8 
    9 This program is distributed in the hope that it will be useful,
   10 but WITHOUT ANY WARRANTY; without even the implied warranty of
   11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
   12 
   13 See the GNU General Public License for more details.
   14 
   15 You should have received a copy of the GNU General Public License
   16 along with this program; if not, write to the Free Software
   17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
   18 
   19 */
   20 // cl_newfx.c -- MORE entity effects parsing and management
   21 
   22 #include "client.h"
   23 
   24 extern cparticle_t      *active_particles, *free_particles;
   25 extern cparticle_t      particles[MAX_PARTICLES];
   26 extern int                      cl_numparticles;
   27 extern cvar_t           *vid_ref;
   28 
   29 extern void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up);
   30 
   31 
   32 /*
   33 ======
   34 vectoangles2 - this is duplicated in the game DLL, but I need it here.
   35 ======
   36 */
   37 void vectoangles2 (vec3_t value1, vec3_t angles)
   38 {
   39         float   forward;
   40         float   yaw, pitch;
   41         
   42         if (value1[1] == 0 && value1[0] == 0)
   43         {
   44                 yaw = 0;
   45                 if (value1[2] > 0)
   46                         pitch = 90;
   47                 else
   48                         pitch = 270;
   49         }
   50         else
   51         {
   52         // PMM - fixed to correct for pitch of 0
   53                 if (value1[0])
   54                         yaw = (atan2(value1[1], value1[0]) * 180 / M_PI);
   55                 else if (value1[1] > 0)
   56                         yaw = 90;
   57                 else
   58                         yaw = 270;
   59 
   60                 if (yaw < 0)
   61                         yaw += 360;
   62 
   63                 forward = sqrt (value1[0]*value1[0] + value1[1]*value1[1]);
   64                 pitch = (atan2(value1[2], forward) * 180 / M_PI);
   65                 if (pitch < 0)
   66                         pitch += 360;
   67         }
   68 
   69         angles[PITCH] = -pitch;
   70         angles[YAW] = yaw;
   71         angles[ROLL] = 0;
   72 }
   73 
   74 //=============
   75 //=============
   76 void CL_Flashlight (int ent, vec3_t pos)
   77 {
   78         cdlight_t       *dl;
   79 
   80         dl = CL_AllocDlight (ent);
   81         VectorCopy (pos,  dl->origin);
   82         dl->radius = 400;
   83         dl->minlight = 250;
   84         dl->die = cl.time + 100;
   85         dl->color[0] = 1;
   86         dl->color[1] = 1;
   87         dl->color[2] = 1;
   88 }
   89 
   90 /*
   91 ======
   92 CL_ColorFlash - flash of light
   93 ======
   94 */
   95 void CL_ColorFlash (vec3_t pos, int ent, int intensity, float r, float g, float b)
   96 {
   97         cdlight_t       *dl;
   98 
   99         if((vidref_val == VIDREF_SOFT) && ((r < 0) || (g<0) || (b<0)))
  100         {
  101                 intensity = -intensity;
  102                 r = -r;
  103                 g = -g;
  104                 b = -b;
  105         }
  106 
  107         dl = CL_AllocDlight (ent);
  108         VectorCopy (pos,  dl->origin);
  109         dl->radius = intensity;
  110         dl->minlight = 250;
  111         dl->die = cl.time + 100;
  112         dl->color[0] = r;
  113         dl->color[1] = g;
  114         dl->color[2] = b;
  115 }
  116 
  117 
  118 /*
  119 ======
  120 CL_DebugTrail
  121 ======
  122 */
  123 void CL_DebugTrail (vec3_t start, vec3_t end)
  124 {
  125         vec3_t          move;
  126         vec3_t          vec;
  127         float           len;
  128 //      int                     j;
  129         cparticle_t     *p;
  130         float           dec;
  131         vec3_t          right, up;
  132 //      int                     i;
  133 //      float           d, c, s;
  134 //      vec3_t          dir;
  135 
  136         VectorCopy (start, move);
  137         VectorSubtract (end, start, vec);
  138         len = VectorNormalize (vec);
  139 
  140         MakeNormalVectors (vec, right, up);
  141 
  142 //      VectorScale(vec, RT2_SKIP, vec);
  143 
  144 //      dec = 1.0;
  145 //      dec = 0.75;
  146         dec = 3;
  147         VectorScale (vec, dec, vec);
  148         VectorCopy (start, move);
  149 
  150         while (len > 0)
  151         {
  152                 len -= dec;
  153 
  154                 if (!free_particles)
  155                         return;
  156                 p = free_particles;
  157                 free_particles = p->next;
  158                 p->next = active_particles;
  159                 active_particles = p;
  160 
  161                 p->time = cl.time;
  162                 VectorClear (p->accel);
  163                 VectorClear (p->vel);
  164                 p->alpha = 1.0;
  165                 p->alphavel = -0.1;
  166 //              p->alphavel = 0;
  167                 p->color = 0x74 + (rand()&7);
  168                 VectorCopy (move, p->org);
  169 /*
  170                 for (j=0 ; j<3 ; j++)
  171                 {
  172                         p->org[j] = move[j] + crand()*2;
  173                         p->vel[j] = crand()*3;
  174                         p->accel[j] = 0;
  175                 }
  176 */
  177                 VectorAdd (move, vec, move);
  178         }
  179 
  180 }
  181 
  182 /*
  183 ===============
  184 CL_SmokeTrail
  185 ===============
  186 */
  187 void CL_SmokeTrail (vec3_t start, vec3_t end, int colorStart, int colorRun, int spacing)
  188 {
  189         vec3_t          move;
  190         vec3_t          vec;
  191         float           len;
  192         int                     j;
  193         cparticle_t     *p;
  194 
  195         VectorCopy (start, move);
  196         VectorSubtract (end, start, vec);
  197         len = VectorNormalize (vec);
  198 
  199         VectorScale (vec, spacing, vec);
  200 
  201         // FIXME: this is a really silly way to have a loop
  202         while (len > 0)
  203         {
  204                 len -= spacing;
  205 
  206                 if (!free_particles)
  207                         return;
  208                 p = free_particles;
  209                 free_particles = p->next;
  210                 p->next = active_particles;
  211                 active_particles = p;
  212                 VectorClear (p->accel);
  213                 
  214                 p->time = cl.time;
  215 
  216                 p->alpha = 1.0;
  217                 p->alphavel = -1.0 / (1+frand()*0.5);
  218                 p->color = colorStart + (rand() % colorRun);
  219                 for (j=0 ; j<3 ; j++)
  220                 {
  221                         p->org[j] = move[j] + crand()*3;
  222                         p->accel[j] = 0;
  223                 }
  224                 p->vel[2] = 20 + crand()*5;
  225 
  226                 VectorAdd (move, vec, move);
  227         }
  228 }
  229 
  230 void CL_ForceWall (vec3_t start, vec3_t end, int color)
  231 {
  232         vec3_t          move;
  233         vec3_t          vec;
  234         float           len;
  235         int                     j;
  236         cparticle_t     *p;
  237 
  238         VectorCopy (start, move);
  239         VectorSubtract (end, start, vec);
  240         len = VectorNormalize (vec);
  241 
  242         VectorScale (vec, 4, vec);
  243 
  244         // FIXME: this is a really silly way to have a loop
  245         while (len > 0)
  246         {
  247                 len -= 4;
  248 
  249                 if (!free_particles)
  250                         return;
  251                 
  252                 if (frand() > 0.3)
  253                 {
  254                         p = free_particles;
  255                         free_particles = p->next;
  256                         p->next = active_particles;
  257                         active_particles = p;
  258                         VectorClear (p->accel);
  259                         
  260                         p->time = cl.time;
  261 
  262                         p->alpha = 1.0;
  263                         p->alphavel =  -1.0 / (3.0+frand()*0.5);
  264                         p->color = color;
  265                         for (j=0 ; j<3 ; j++)
  266                         {
  267                                 p->org[j] = move[j] + crand()*3;
  268                                 p->accel[j] = 0;
  269                         }
  270                         p->vel[0] = 0;
  271                         p->vel[1] = 0;
  272                         p->vel[2] = -40 - (crand()*10);
  273                 }
  274 
  275                 VectorAdd (move, vec, move);
  276         }
  277 }
  278 
  279 void CL_FlameEffects (centity_t *ent, vec3_t origin)
  280 {
  281         int                     n, count;
  282         int                     j;
  283         cparticle_t     *p;
  284 
  285         count = rand() & 0xF;
  286 
  287         for(n=0;n<count;n++)
  288         {
  289                 if (!free_particles)
  290                         return;
  291                         
  292                 p = free_particles;
  293                 free_particles = p->next;
  294                 p->next = active_particles;
  295                 active_particles = p;
  296                 
  297                 VectorClear (p->accel);
  298                 p->time = cl.time;
  299 
  300                 p->alpha = 1.0;
  301                 p->alphavel = -1.0 / (1+frand()*0.2);
  302                 p->color = 226 + (rand() % 4);
  303                 for (j=0 ; j<3 ; j++)
  304                 {
  305                         p->org[j] = origin[j] + crand()*5;
  306                         p->vel[j] = crand()*5;
  307                 }
  308                 p->vel[2] = crand() * -10;
  309                 p->accel[2] = -PARTICLE_GRAVITY;
  310         }
  311 
  312         count = rand() & 0x7;
  313 
  314         for(n=0;n<count;n++)
  315         {
  316                 if (!free_particles)
  317                         return;
  318                 p = free_particles;
  319                 free_particles = p->next;
  320                 p->next = active_particles;
  321                 active_particles = p;
  322                 VectorClear (p->accel);
  323                 
  324                 p->time = cl.time;
  325 
  326                 p->alpha = 1.0;
  327                 p->alphavel = -1.0 / (1+frand()*0.5);
  328                 p->color = 0 + (rand() % 4);
  329                 for (j=0 ; j<3 ; j++)
  330                 {
  331                         p->org[j] = origin[j] + crand()*3;
  332                 }
  333                 p->vel[2] = 20 + crand()*5;
  334         }
  335 
  336 }
  337 
  338 
  339 /*
  340 ===============
  341 CL_GenericParticleEffect
  342 ===============
  343 */
  344 void CL_GenericParticleEffect (vec3_t org, vec3_t dir, int color, int count, int numcolors, int dirspread, float alphavel)
  345 {
  346         int                     i, j;
  347         cparticle_t     *p;
  348         float           d;
  349 
  350         for (i=0 ; i<count ; i++)
  351         {
  352                 if (!free_particles)
  353                         return;
  354                 p = free_particles;
  355                 free_particles = p->next;
  356                 p->next = active_particles;
  357                 active_particles = p;
  358 
  359                 p->time = cl.time;
  360                 if (numcolors > 1)
  361                         p->color = color + (rand() & numcolors);
  362                 else
  363                         p->color = color;
  364 
  365                 d = rand() & dirspread;
  366                 for (j=0 ; j<3 ; j++)
  367                 {
  368                         p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
  369                         p->vel[j] = crand()*20;
  370                 }
  371 
  372                 p->accel[0] = p->accel[1] = 0;
  373                 p->accel[2] = -PARTICLE_GRAVITY;
  374 //              VectorCopy (accel, p->accel);
  375                 p->alpha = 1.0;
  376 
  377                 p->alphavel = -1.0 / (0.5 + frand()*alphavel);
  378 //              p->alphavel = alphavel;
  379         }
  380 }
  381 
  382 /*
  383 ===============
  384 CL_BubbleTrail2 (lets you control the # of bubbles by setting the distance between the spawns)
  385 
  386 ===============
  387 */
  388 void CL_BubbleTrail2 (vec3_t start, vec3_t end, int dist)
  389 {
  390         vec3_t          move;
  391         vec3_t          vec;
  392         float           len;
  393         int                     i, j;
  394         cparticle_t     *p;
  395         float           dec;
  396 
  397         VectorCopy (start, move);
  398         VectorSubtract (end, start, vec);
  399         len = VectorNormalize (vec);
  400 
  401         dec = dist;
  402         VectorScale (vec, dec, vec);
  403 
  404         for (i=0 ; i<len ; i+=dec)
  405         {
  406                 if (!free_particles)
  407                         return;
  408 
  409                 p = free_particles;
  410                 free_particles = p->next;
  411                 p->next = active_particles;
  412                 active_particles = p;
  413 
  414                 VectorClear (p->accel);
  415                 p->time = cl.time;
  416 
  417                 p->alpha = 1.0;
  418                 p->alphavel = -1.0 / (1+frand()*0.1);
  419                 p->color = 4 + (rand()&7);
  420                 for (j=0 ; j<3 ; j++)
  421                 {
  422                         p->org[j] = move[j] + crand()*2;
  423                         p->vel[j] = crand()*10;
  424                 }
  425                 p->org[2] -= 4;
  426 //              p->vel[2] += 6;
  427                 p->vel[2] += 20;
  428 
  429                 VectorAdd (move, vec, move);
  430         }
  431 }
  432 
  433 //#define CORKSCREW             1
  434 //#define DOUBLE_SCREW  1
  435 #define RINGS           1
  436 //#define       SPRAY           1
  437 
  438 #ifdef CORKSCREW
439 void CL_Heatbeam (vec3_t start, vec3_t end) 440 { 441 vec3_t move; 442 vec3_t vec; 443 float len; 444 int j,k; 445 cparticle_t *p; 446 vec3_t right, up; 447 int i; 448 float d, c, s; 449 vec3_t dir; 450 float ltime; 451 float step = 5.0; 452 453 VectorCopy (start, move); 454 VectorSubtract (end, start, vec); 455 len = VectorNormalize (vec); 456 457 // MakeNormalVectors (vec, right, up); 458 VectorCopy (cl.v_right, right); 459 VectorCopy (cl.v_up, up); 460 VectorMA (move, -1, right, move); 461 VectorMA (move, -1, up, move); 462 463 VectorScale (vec, step, vec); 464 ltime = (float) cl.time/1000.0; 465 466 // for (i=0 ; i<len ; i++) 467 for (i=0 ; i<len ; i+=step) 468 { 469 d = i * 0.1 - fmod(ltime,16.0)*M_PI; 470 c = cos(d)/1.75; 471 s = sin(d)/1.75; 472 #ifdef DOUBLE_SCREW 473 for (k=-1; k<2; k+=2) 474 { 475 #else 476 k=1; 477 #endif 478 if (!free_particles) 479 return; 480 481 p = free_particles; 482 free_particles = p->next; 483 p->next = active_particles; 484 active_particles = p; 485 486 p->time = cl.time; 487 VectorClear (p->accel); 488 489 p->alpha = 0.5; 490 // p->alphavel = -1.0 / (1+frand()*0.2); 491 // only last one frame! 492 p->alphavel = INSTANT_PARTICLE; 493 // p->color = 0x74 + (rand()&7); 494 // p->color = 223 - (rand()&7); 495 p->color = 223; 496 // p->color = 240; 497 498 // trim it so it looks like it's starting at the origin 499 if (i < 10) 500 { 501 VectorScale (right, c*(i/10.0)*k, dir); 502 VectorMA (dir, s*(i/10.0)*k, up, dir); 503 } 504 else 505 { 506 VectorScale (right, c*k, dir); 507 VectorMA (dir, s*k, up, dir); 508 } 509 510 for (j=0 ; j<3 ; j++) 511 { 512 p->org[j] = move[j] + dir[j]*3; 513 // p->vel[j] = dir[j]*6; 514 p->vel[j] = 0; 515 } 516 #ifdef DOUBLE_SCREW 517 } 518 #endif 519 VectorAdd (move, vec, move); 520 } 521 }
522 #endif 523 #ifdef RINGS 524 //void CL_Heatbeam (vec3_t start, vec3_t end) 525 void CL_Heatbeam (vec3_t start, vec3_t forward) 526 { 527 vec3_t move; 528 vec3_t vec; 529 float len; 530 int j; 531 cparticle_t *p; 532 vec3_t right, up; 533 int i; 534 float c, s; 535 vec3_t dir; 536 float ltime; 537 float step = 32.0, rstep; 538 float start_pt; 539 float rot; 540 float variance; 541 vec3_t end; 542 543 VectorMA (start, 4096, forward, end); 544 545 VectorCopy (start, move); 546 VectorSubtract (end, start, vec); 547 len = VectorNormalize (vec); 548 549 // FIXME - pmm - these might end up using old values? 550 // MakeNormalVectors (vec, right, up); 551 VectorCopy (cl.v_right, right); 552 VectorCopy (cl.v_up, up); 553 if (vidref_val == VIDREF_GL) 554 { // GL mode 555 VectorMA (move, -0.5, right, move); 556 VectorMA (move, -0.5, up, move); 557 } 558 // otherwise assume SOFT 559 560 ltime = (float) cl.time/1000.0; 561 start_pt = fmod(ltime*96.0,step); 562 VectorMA (move, start_pt, vec, move); 563 564 VectorScale (vec, step, vec); 565 566 // Com_Printf ("%f\n", ltime); 567 rstep = M_PI/10.0; 568 for (i=start_pt ; i<len ; i+=step) 569 { 570 if (i>step*5) // don't bother after the 5th ring 571 break; 572 573 for (rot = 0; rot < M_PI*2; rot += rstep) 574 { 575 576 if (!free_particles) 577 return; 578 579 p = free_particles; 580 free_particles = p->next; 581 p->next = active_particles; 582 active_particles = p; 583 584 p->time = cl.time; 585 VectorClear (p->accel); 586 // rot+= fmod(ltime, 12.0)*M_PI; 587 // c = cos(rot)/2.0; 588 // s = sin(rot)/2.0; 589 // variance = 0.4 + ((float)rand()/(float)RAND_MAX) *0.2; 590 variance = 0.5; 591 c = cos(rot)*variance; 592 s = sin(rot)*variance; 593 594 // trim it so it looks like it's starting at the origin 595 if (i < 10) 596 { 597 VectorScale (right, c*(i/10.0), dir); 598 VectorMA (dir, s*(i/10.0), up, dir); 599 } 600 else 601 { 602 VectorScale (right, c, dir); 603 VectorMA (dir, s, up, dir); 604 } 605 606 p->alpha = 0.5; 607 // p->alphavel = -1.0 / (1+frand()*0.2); 608 p->alphavel = -1000.0; 609 // p->color = 0x74 + (rand()&7); 610 p->color = 223 - (rand()&7); 611 for (j=0 ; j<3 ; j++) 612 { 613 p->org[j] = move[j] + dir[j]*3; 614 // p->vel[j] = dir[j]*6; 615 p->vel[j] = 0; 616 } 617 } 618 VectorAdd (move, vec, move); 619 } 620 } 621 #endif 622 #ifdef SPRAY
623 void CL_Heatbeam (vec3_t start, vec3_t end) 624 { 625 vec3_t move; 626 vec3_t vec; 627 float len; 628 int j; 629 cparticle_t *p; 630 vec3_t forward, right, up; 631 int i; 632 float d, c, s; 633 vec3_t dir; 634 float ltime; 635 float step = 32.0, rstep; 636 float start_pt; 637 float rot; 638 639 VectorCopy (start, move); 640 VectorSubtract (end, start, vec); 641 len = VectorNormalize (vec); 642 643 // MakeNormalVectors (vec, right, up); 644 VectorCopy (cl.v_forward, forward); 645 VectorCopy (cl.v_right, right); 646 VectorCopy (cl.v_up, up); 647 VectorMA (move, -0.5, right, move); 648 VectorMA (move, -0.5, up, move); 649 650 for (i=0; i<8; i++) 651 { 652 if (!free_particles) 653 return; 654 655 p = free_particles; 656 free_particles = p->next; 657 p->next = active_particles; 658 active_particles = p; 659 660 p->time = cl.time; 661 VectorClear (p->accel); 662 663 d = crand()*M_PI; 664 c = cos(d)*30; 665 s = sin(d)*30; 666 667 p->alpha = 1.0; 668 p->alphavel = -5.0 / (1+frand()); 669 p->color = 223 - (rand()&7); 670 671 for (j=0 ; j<3 ; j++) 672 { 673 p->org[j] = move[j]; 674 } 675 VectorScale (vec, 450, p->vel); 676 VectorMA (p->vel, c, right, p->vel); 677 VectorMA (p->vel, s, up, p->vel); 678 } 679 /* 680 681 ltime = (float) cl.time/1000.0; 682 start_pt = fmod(ltime*16.0,step); 683 VectorMA (move, start_pt, vec, move); 684 685 VectorScale (vec, step, vec); 686 687 // Com_Printf ("%f\n", ltime); 688 rstep = M_PI/12.0; 689 for (i=start_pt ; i<len ; i+=step) 690 { 691 if (i>step*5) // don't bother after the 5th ring 692 break; 693 694 for (rot = 0; rot < M_PI*2; rot += rstep) 695 { 696 if (!free_particles) 697 return; 698 699 p = free_particles; 700 free_particles = p->next; 701 p->next = active_particles; 702 active_particles = p; 703 704 p->time = cl.time; 705 VectorClear (p->accel); 706 // rot+= fmod(ltime, 12.0)*M_PI; 707 // c = cos(rot)/2.0; 708 // s = sin(rot)/2.0; 709 c = cos(rot)/1.5; 710 s = sin(rot)/1.5; 711 712 // trim it so it looks like it's starting at the origin 713 if (i < 10) 714 { 715 VectorScale (right, c*(i/10.0), dir); 716 VectorMA (dir, s*(i/10.0), up, dir); 717 } 718 else 719 { 720 VectorScale (right, c, dir); 721 VectorMA (dir, s, up, dir); 722 } 723 724 p->alpha = 0.5; 725 // p->alphavel = -1.0 / (1+frand()*0.2); 726 p->alphavel = -1000.0; 727 // p->color = 0x74 + (rand()&7); 728 p->color = 223 - (rand()&7); 729 for (j=0 ; j<3 ; j++) 730 { 731 p->org[j] = move[j] + dir[j]*3; 732 // p->vel[j] = dir[j]*6; 733 p->vel[j] = 0; 734 } 735 } 736 VectorAdd (move, vec, move); 737 } 738 */ 739 }
740 #endif 741 742 /* 743 =============== 744 CL_ParticleSteamEffect 745 746 Puffs with velocity along direction, with some randomness thrown in 747 =============== 748 */ 749 void CL_ParticleSteamEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude) 750 { 751 int i, j; 752 cparticle_t *p; 753 float d; 754 vec3_t r, u; 755 756 // vectoangles2 (dir, angle_dir); 757 // AngleVectors (angle_dir, f, r, u); 758 759 MakeNormalVectors (dir, r, u); 760 761 for (i=0 ; i<count ; i++) 762 { 763 if (!free_particles) 764 return; 765 p = free_particles; 766 free_particles = p->next; 767 p->next = active_particles; 768 active_particles = p; 769 770 p->time = cl.time; 771 p->color = color + (rand()&7); 772 773 for (j=0 ; j<3 ; j++) 774 { 775 p->org[j] = org[j] + magnitude*0.1*crand(); 776 // p->vel[j] = dir[j]*magnitude; 777 } 778 VectorScale (dir, magnitude, p->vel); 779 d = crand()*magnitude/3; 780 VectorMA (p->vel, d, r, p->vel); 781 d = crand()*magnitude/3; 782 VectorMA (p->vel, d, u, p->vel); 783 784 p->accel[0] = p->accel[1] = 0; 785 p->accel[2] = -PARTICLE_GRAVITY/2; 786 p->alpha = 1.0; 787 788 p->alphavel = -1.0 / (0.5 + frand()*0.3); 789 } 790 } 791 792 void CL_ParticleSteamEffect2 (cl_sustain_t *self) 793 //vec3_t org, vec3_t dir, int color, int count, int magnitude) 794 { 795 int i, j; 796 cparticle_t *p; 797 float d; 798 vec3_t r, u; 799 vec3_t dir; 800 801 // vectoangles2 (dir, angle_dir); 802 // AngleVectors (angle_dir, f, r, u); 803 804 VectorCopy (self->dir, dir); 805 MakeNormalVectors (dir, r, u); 806 807 for (i=0 ; i<self->count ; i++) 808 { 809 if (!free_particles) 810 return; 811 p = free_particles; 812 free_particles = p->next; 813 p->next = active_particles; 814 active_particles = p; 815 816 p->time = cl.time; 817 p->color = self->color + (rand()&7); 818 819 for (j=0 ; j<3 ; j++) 820 { 821 p->org[j] = self->org[j] + self->magnitude*0.1*crand(); 822 // p->vel[j] = dir[j]*magnitude; 823 } 824 VectorScale (dir, self->magnitude, p->vel); 825 d = crand()*self->magnitude/3; 826 VectorMA (p->vel, d, r, p->vel); 827 d = crand()*self->magnitude/3; 828 VectorMA (p->vel, d, u, p->vel); 829 830 p->accel[0] = p->accel[1] = 0; 831 p->accel[2] = -PARTICLE_GRAVITY/2; 832 p->alpha = 1.0; 833 834 p->alphavel = -1.0 / (0.5 + frand()*0.3); 835 } 836 self->nextthink += self->thinkinterval; 837 } 838 839 /* 840 =============== 841 CL_TrackerTrail 842 =============== 843 */ 844 void CL_TrackerTrail (vec3_t start, vec3_t end, int particleColor) 845 { 846 vec3_t move; 847 vec3_t vec; 848 vec3_t forward,right,up,angle_dir; 849 float len; 850 int j; 851 cparticle_t *p; 852 int dec; 853 float dist; 854 855 VectorCopy (start, move); 856 VectorSubtract (end, start, vec); 857 len = VectorNormalize (vec); 858 859 VectorCopy(vec, forward); 860 vectoangles2 (forward, angle_dir); 861 AngleVectors (angle_dir, forward, right, up); 862 863 dec = 3; 864 VectorScale (vec, 3, vec); 865 866 // FIXME: this is a really silly way to have a loop 867 while (len > 0) 868 { 869 len -= dec; 870 871 if (!free_particles) 872 return; 873 p = free_particles; 874 free_particles = p->next; 875 p->next = active_particles; 876 active_particles = p; 877 VectorClear (p->accel); 878 879 p->time = cl.time; 880 881 p->alpha = 1.0; 882 p->alphavel = -2.0; 883 p->color = particleColor; 884 dist = DotProduct(move, forward); 885 VectorMA(move, 8 * cos(dist), up, p->org); 886 for (j=0 ; j<3 ; j++) 887 { 888 // p->org[j] = move[j] + crand(); 889 p->vel[j] = 0; 890 p->accel[j] = 0; 891 } 892 p->vel[2] = 5; 893 894 VectorAdd (move, vec, move); 895 } 896 } 897 898 void CL_Tracker_Shell(vec3_t origin) 899 { 900 vec3_t dir; 901 int i; 902 cparticle_t *p; 903 904 for(i=0;i<300;i++) 905 { 906 if (!free_particles) 907 return; 908 p = free_particles; 909 free_particles = p->next; 910 p->next = active_particles; 911 active_particles = p; 912 VectorClear (p->accel); 913 914 p->time = cl.time; 915 916 p->alpha = 1.0; 917 p->alphavel = INSTANT_PARTICLE; 918 p->color = 0; 919 920 dir[0] = crand(); 921 dir[1] = crand(); 922 dir[2] = crand(); 923 VectorNormalize(dir); 924 925 VectorMA(origin, 40, dir, p->org); 926 } 927 } 928 929 void CL_MonsterPlasma_Shell(vec3_t origin) 930 { 931 vec3_t dir; 932 int i; 933 cparticle_t *p; 934 935 for(i=0;i<40;i++) 936 { 937 if (!free_particles) 938 return; 939 p = free_particles; 940 free_particles = p->next; 941 p->next = active_particles; 942 active_particles = p; 943 VectorClear (p->accel); 944 945 p->time = cl.time; 946 947 p->alpha = 1.0; 948 p->alphavel = INSTANT_PARTICLE; 949 p->color = 0xe0; 950 951 dir[0] = crand(); 952 dir[1] = crand(); 953 dir[2] = crand(); 954 VectorNormalize(dir); 955 956 VectorMA(origin, 10, dir, p->org); 957 // VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org); 958 } 959 } 960 961 void CL_Widowbeamout (cl_sustain_t *self) 962 { 963 vec3_t dir; 964 int i; 965 cparticle_t *p; 966 static int colortable[4] = {2*8,13*8,21*8,18*8}; 967 float ratio; 968 969 ratio = 1.0 - (((float)self->endtime - (float)cl.time)/2100.0); 970 971 for(i=0;i<300;i++) 972 { 973 if (!free_particles) 974 return; 975 p = free_particles; 976 free_particles = p->next; 977 p->next = active_particles; 978 active_particles = p; 979 VectorClear (p->accel); 980 981 p->time = cl.time; 982 983 p->alpha = 1.0; 984 p->alphavel = INSTANT_PARTICLE; 985 p->color = colortable[rand()&3]; 986 987 dir[0] = crand(); 988 dir[1] = crand(); 989 dir[2] = crand(); 990 VectorNormalize(dir); 991 992 VectorMA(self->org, (45.0 * ratio), dir, p->org); 993 // VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org); 994 } 995 } 996 997 void CL_Nukeblast (cl_sustain_t *self) 998 { 999 vec3_t dir; 1000 int i; 1001 cparticle_t *p; 1002 static int colortable[4] = {110, 112, 114, 116}; 1003 float ratio; 1004 1005 ratio = 1.0 - (((float)self->endtime - (float)cl.time)/1000.0); 1006 1007 for(i=0;i<700;i++) 1008 { 1009 if (!free_particles) 1010 return; 1011 p = free_particles; 1012 free_particles = p->next; 1013 p->next = active_particles; 1014 active_particles = p; 1015 VectorClear (p->accel); 1016 1017 p->time = cl.time; 1018 1019 p->alpha = 1.0; 1020 p->alphavel = INSTANT_PARTICLE; 1021 p->color = colortable[rand()&3]; 1022 1023 dir[0] = crand(); 1024 dir[1] = crand(); 1025 dir[2] = crand(); 1026 VectorNormalize(dir); 1027 1028 VectorMA(self->org, (200.0 * ratio), dir, p->org); 1029 // VectorMA(origin, 10*(((rand () & 0x7fff) / ((float)0x7fff))), dir, p->org); 1030 } 1031 } 1032 1033 void CL_WidowSplash (vec3_t org) 1034 { 1035 static int colortable[4] = {2*8,13*8,21*8,18*8}; 1036 int i; 1037 cparticle_t *p; 1038 vec3_t dir; 1039 1040 for (i=0 ; i<256 ; i++) 1041 { 1042 if (!free_particles) 1043 return; 1044 p = free_particles; 1045 free_particles = p->next; 1046 p->next = active_particles; 1047 active_particles = p; 1048 1049 p->time = cl.time; 1050 p->color = colortable[rand()&3]; 1051 1052 dir[0] = crand(); 1053 dir[1] = crand(); 1054 dir[2] = crand(); 1055 VectorNormalize(dir); 1056 VectorMA(org, 45.0, dir, p->org); 1057 VectorMA(vec3_origin, 40.0, dir, p->vel); 1058 1059 p->accel[0] = p->accel[1] = 0; 1060 p->alpha = 1.0; 1061 1062 p->alphavel = -0.8 / (0.5 + frand()*0.3); 1063 } 1064 1065 } 1066 1067 void CL_Tracker_Explode(vec3_t origin) 1068 { 1069 vec3_t dir, backdir; 1070 int i; 1071 cparticle_t *p; 1072 1073 for(i=0;i<300;i++) 1074 { 1075 if (!free_particles) 1076 return; 1077 p = free_particles; 1078 free_particles = p->next; 1079 p->next = active_particles; 1080 active_particles = p; 1081 VectorClear (p->accel); 1082 1083 p->time = cl.time; 1084 1085 p->alpha = 1.0; 1086 p->alphavel = -1.0; 1087 p->color = 0; 1088 1089 dir[0] = crand(); 1090 dir[1] = crand(); 1091 dir[2] = crand(); 1092 VectorNormalize(dir); 1093 VectorScale(dir, -1, backdir); 1094 1095 VectorMA(origin, 64, dir, p->org); 1096 VectorScale(backdir, 64, p->vel); 1097 } 1098 1099 } 1100 1101 /* 1102 =============== 1103 CL_TagTrail 1104 1105 =============== 1106 */ 1107 void CL_TagTrail (vec3_t start, vec3_t end, float color) 1108 { 1109 vec3_t move; 1110 vec3_t vec; 1111 float len; 1112 int j; 1113 cparticle_t *p; 1114 int dec; 1115 1116 VectorCopy (start, move); 1117 VectorSubtract (end, start, vec); 1118 len = VectorNormalize (vec); 1119 1120 dec = 5; 1121 VectorScale (vec, 5, vec); 1122 1123 while (len >= 0) 1124 { 1125 len -= dec; 1126 1127 if (!free_particles) 1128 return; 1129 p = free_particles; 1130 free_particles = p->next; 1131 p->next = active_particles; 1132 active_particles = p; 1133 VectorClear (p->accel); 1134 1135 p->time = cl.time; 1136 1137 p->alpha = 1.0; 1138 p->alphavel = -1.0 / (0.8+frand()*0.2); 1139 p->color = color; 1140 for (j=0 ; j<3 ; j++) 1141 { 1142 p->org[j] = move[j] + crand()*16; 1143 p->vel[j] = crand()*5; 1144 p->accel[j] = 0; 1145 } 1146 1147 VectorAdd (move, vec, move); 1148 } 1149 } 1150 1151 /* 1152 =============== 1153 CL_ColorExplosionParticles 1154 =============== 1155 */ 1156 void CL_ColorExplosionParticles (vec3_t org, int color, int run) 1157 { 1158 int i, j; 1159 cparticle_t *p; 1160 1161 for (i=0 ; i<128 ; i++) 1162 { 1163 if (!free_particles) 1164 return; 1165 p = free_particles; 1166 free_particles = p->next; 1167 p->next = active_particles; 1168 active_particles = p; 1169 1170 p->time = cl.time; 1171 p->color = color + (rand() % run); 1172 1173 for (j=0 ; j<3 ; j++) 1174 { 1175 p->org[j] = org[j] + ((rand()%32)-16); 1176 p->vel[j] = (rand()%256)-128; 1177 } 1178 1179 p->accel[0] = p->accel[1] = 0; 1180 p->accel[2] = -PARTICLE_GRAVITY; 1181 p->alpha = 1.0; 1182 1183 p->alphavel = -0.4 / (0.6 + frand()*0.2); 1184 } 1185 } 1186 1187 /* 1188 =============== 1189 CL_ParticleSmokeEffect - like the steam effect, but unaffected by gravity 1190 =============== 1191 */ 1192 void CL_ParticleSmokeEffect (vec3_t org, vec3_t dir, int color, int count, int magnitude) 1193 { 1194 int i, j; 1195 cparticle_t *p; 1196 float d; 1197 vec3_t r, u; 1198 1199 MakeNormalVectors (dir, r, u); 1200 1201 for (i=0 ; i<count ; i++) 1202 { 1203 if (!free_particles) 1204 return; 1205 p = free_particles; 1206 free_particles = p->next; 1207 p->next = active_particles; 1208 active_particles = p; 1209 1210 p->time = cl.time; 1211 p->color = color + (rand()&7); 1212 1213 for (j=0 ; j<3 ; j++) 1214 { 1215 p->org[j] = org[j] + magnitude*0.1*crand(); 1216 // p->vel[j] = dir[j]*magnitude; 1217 } 1218 VectorScale (dir, magnitude, p->vel); 1219 d = crand()*magnitude/3; 1220 VectorMA (p->vel, d, r, p->vel); 1221 d = crand()*magnitude/3; 1222 VectorMA (p->vel, d, u, p->vel); 1223 1224 p->accel[0] = p->accel[1] = p->accel[2] = 0; 1225 p->alpha = 1.0; 1226 1227 p->alphavel = -1.0 / (0.5 + frand()*0.3); 1228 } 1229 } 1230 1231 /* 1232 =============== 1233 CL_BlasterParticles2 1234 1235 Wall impact puffs (Green) 1236 =============== 1237 */ 1238 void CL_BlasterParticles2 (vec3_t org, vec3_t dir, unsigned int color) 1239 { 1240 int i, j; 1241 cparticle_t *p; 1242 float d; 1243 int count; 1244 1245 count = 40; 1246 for (i=0 ; i<count ; i++) 1247 { 1248 if (!free_particles) 1249 return; 1250 p = free_particles; 1251 free_particles = p->next; 1252 p->next = active_particles; 1253 active_particles = p; 1254 1255 p->time = cl.time; 1256 p->color = color + (rand()&7); 1257 1258 d = rand()&15; 1259 for (j=0 ; j<3 ; j++) 1260 { 1261 p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j]; 1262 p->vel[j] = dir[j] * 30 + crand()*40; 1263 } 1264 1265 p->accel[0] = p->accel[1] = 0; 1266 p->accel[2] = -PARTICLE_GRAVITY; 1267 p->alpha = 1.0; 1268 1269 p->alphavel = -1.0 / (0.5 + frand()*0.3); 1270 } 1271 } 1272 1273 /* 1274 =============== 1275 CL_BlasterTrail2 1276 1277 Green! 1278 =============== 1279 */ 1280 void CL_BlasterTrail2 (vec3_t start, vec3_t end) 1281 { 1282 vec3_t move; 1283 vec3_t vec; 1284 float len; 1285 int j; 1286 cparticle_t *p; 1287 int dec; 1288 1289 VectorCopy (start, move); 1290 VectorSubtract (end, start, vec); 1291 len = VectorNormalize (vec); 1292 1293 dec = 5; 1294 VectorScale (vec, 5, vec); 1295 1296 // FIXME: this is a really silly way to have a loop 1297 while (len > 0) 1298 { 1299 len -= dec; 1300 1301 if (!free_particles) 1302 return; 1303 p = free_particles; 1304 free_particles = p->next; 1305 p->next = active_particles; 1306 active_particles = p; 1307 VectorClear (p->accel); 1308 1309 p->time = cl.time; 1310 1311 p->alpha = 1.0; 1312 p->alphavel = -1.0 / (0.3+frand()*0.2); 1313 p->color = 0xd0; 1314 for (j=0 ; j<3 ; j++) 1315 { 1316 p->org[j] = move[j] + crand(); 1317 p->vel[j] = crand()*5; 1318 p->accel[j] = 0; 1319 } 1320 1321 VectorAdd (move, vec, move); 1322 } 1323 } 1324