File: client\cl_fx.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_fx.c -- entity effects parsing and management
   21 
   22 #include "client.h"
   23 
   24 void CL_LogoutEffect (vec3_t org, int type);
   25 void CL_ItemRespawnParticles (vec3_t org);
   26 
   27 static vec3_t avelocities [NUMVERTEXNORMALS];
   28 
   29 extern  struct model_s  *cl_mod_smoke;
   30 extern  struct model_s  *cl_mod_flash;
   31 
   32 /*
   33 ==============================================================
   34 
   35 LIGHT STYLE MANAGEMENT
   36 
   37 ==============================================================
   38 */
   39 
   40 typedef struct
   41 {
   42         int             length;
   43         float   value[3];
   44         float   map[MAX_QPATH];
   45 } clightstyle_t;
   46 
   47 clightstyle_t   cl_lightstyle[MAX_LIGHTSTYLES];
   48 int                     lastofs;
   49 
   50 /*
   51 ================
   52 CL_ClearLightStyles
   53 ================
   54 */
   55 void CL_ClearLightStyles (void)
   56 {
   57         memset (cl_lightstyle, 0, sizeof(cl_lightstyle));
   58         lastofs = -1;
   59 }
   60 
   61 /*
   62 ================
   63 CL_RunLightStyles
   64 ================
   65 */
   66 void CL_RunLightStyles (void)
   67 {
   68         int             ofs;
   69         int             i;
   70         clightstyle_t   *ls;
   71 
   72         ofs = cl.time / 100;
   73         if (ofs == lastofs)
   74                 return;
   75         lastofs = ofs;
   76 
   77         for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
   78         {
   79                 if (!ls->length)
   80                 {
   81                         ls->value[0] = ls->value[1] = ls->value[2] = 1.0;
   82                         continue;
   83                 }
   84                 if (ls->length == 1)
   85                         ls->value[0] = ls->value[1] = ls->value[2] = ls->map[0];
   86                 else
   87                         ls->value[0] = ls->value[1] = ls->value[2] = ls->map[ofs%ls->length];
   88         }
   89 }
   90 
   91 
   92 void CL_SetLightstyle (int i)
   93 {
   94         char    *s;
   95         int             j, k;
   96 
   97         s = cl.configstrings[i+CS_LIGHTS];
   98 
   99         j = strlen (s);
  100         if (j >= MAX_QPATH)
  101                 Com_Error (ERR_DROP, "svc_lightstyle length=%i", j);
  102 
  103         cl_lightstyle[i].length = j;
  104 
  105         for (k=0 ; k<j ; k++)
  106                 cl_lightstyle[i].map[k] = (float)(s[k]-'a')/(float)('m'-'a');
  107 }
  108 
  109 /*
  110 ================
  111 CL_AddLightStyles
  112 ================
  113 */
  114 void CL_AddLightStyles (void)
  115 {
  116         int             i;
  117         clightstyle_t   *ls;
  118 
  119         for (i=0,ls=cl_lightstyle ; i<MAX_LIGHTSTYLES ; i++, ls++)
  120                 V_AddLightStyle (i, ls->value[0], ls->value[1], ls->value[2]);
  121 }
  122 
  123 /*
  124 ==============================================================
  125 
  126 DLIGHT MANAGEMENT
  127 
  128 ==============================================================
  129 */
  130 
  131 cdlight_t               cl_dlights[MAX_DLIGHTS];
  132 
  133 /*
  134 ================
  135 CL_ClearDlights
  136 ================
  137 */
  138 void CL_ClearDlights (void)
  139 {
  140         memset (cl_dlights, 0, sizeof(cl_dlights));
  141 }
  142 
  143 /*
  144 ===============
  145 CL_AllocDlight
  146 
  147 ===============
  148 */
  149 cdlight_t *CL_AllocDlight (int key)
  150 {
  151         int             i;
  152         cdlight_t       *dl;
  153 
  154 // first look for an exact key match
  155         if (key)
  156         {
  157                 dl = cl_dlights;
  158                 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
  159                 {
  160                         if (dl->key == key)
  161                         {
  162                                 memset (dl, 0, sizeof(*dl));
  163                                 dl->key = key;
  164                                 return dl;
  165                         }
  166                 }
  167         }
  168 
  169 // then look for anything else
  170         dl = cl_dlights;
  171         for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
  172         {
  173                 if (dl->die < cl.time)
  174                 {
  175                         memset (dl, 0, sizeof(*dl));
  176                         dl->key = key;
  177                         return dl;
  178                 }
  179         }
  180 
  181         dl = &cl_dlights[0];
  182         memset (dl, 0, sizeof(*dl));
  183         dl->key = key;
  184         return dl;
  185 }
  186 
  187 /*
  188 ===============
  189 CL_NewDlight
  190 ===============
  191 */
  192 void CL_NewDlight (int key, float x, float y, float z, float radius, float time)
  193 {
  194         cdlight_t       *dl;
  195 
  196         dl = CL_AllocDlight (key);
  197         dl->origin[0] = x;
  198         dl->origin[1] = y;
  199         dl->origin[2] = z;
  200         dl->radius = radius;
  201         dl->die = cl.time + time;
  202 }
  203 
  204 
  205 /*
  206 ===============
  207 CL_RunDLights
  208 
  209 ===============
  210 */
  211 void CL_RunDLights (void)
  212 {
  213         int                     i;
  214         cdlight_t       *dl;
  215 
  216         dl = cl_dlights;
  217         for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
  218         {
  219                 if (!dl->radius)
  220                         continue;
  221                 
  222                 if (dl->die < cl.time)
  223                 {
  224                         dl->radius = 0;
  225                         return;
  226                 }
  227                 dl->radius -= cls.frametime*dl->decay;
  228                 if (dl->radius < 0)
  229                         dl->radius = 0;
  230         }
  231 }
  232 
  233 /*
  234 ==============
  235 CL_ParseMuzzleFlash
  236 ==============
  237 */
  238 void CL_ParseMuzzleFlash (void)
  239 {
  240         vec3_t          fv, rv;
  241         cdlight_t       *dl;
  242         int                     i, weapon;
  243         centity_t       *pl;
  244         int                     silenced;
  245         float           volume;
  246         char            soundname[64];
  247 
  248         i = MSG_ReadShort (&net_message);
  249         if (i < 1 || i >= MAX_EDICTS)
  250                 Com_Error (ERR_DROP, "CL_ParseMuzzleFlash: bad entity");
  251 
  252         weapon = MSG_ReadByte (&net_message);
  253         silenced = weapon & MZ_SILENCED;
  254         weapon &= ~MZ_SILENCED;
  255 
  256         pl = &cl_entities[i];
  257 
  258         dl = CL_AllocDlight (i);
  259         VectorCopy (pl->current.origin,  dl->origin);
  260         AngleVectors (pl->current.angles, fv, rv, NULL);
  261         VectorMA (dl->origin, 18, fv, dl->origin);
  262         VectorMA (dl->origin, 16, rv, dl->origin);
  263         if (silenced)
  264                 dl->radius = 100 + (rand()&31);
  265         else
  266                 dl->radius = 200 + (rand()&31);
  267         dl->minlight = 32;
  268         dl->die = cl.time; // + 0.1;
  269 
  270         if (silenced)
  271                 volume = 0.2;
  272         else
  273                 volume = 1;
  274 
  275         switch (weapon)
  276         {
  277         case MZ_BLASTER:
  278                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  279                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
  280                 break;
  281         case MZ_BLUEHYPERBLASTER:
  282                 dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
  283                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
  284                 break;
  285         case MZ_HYPERBLASTER:
  286                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  287                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/hyprbf1a.wav"), volume, ATTN_NORM, 0);
  288                 break;
  289         case MZ_MACHINEGUN:
  290                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  291                 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
  292                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
  293                 break;
  294         case MZ_SHOTGUN:
  295                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  296                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotgf1b.wav"), volume, ATTN_NORM, 0);
  297                 S_StartSound (NULL, i, CHAN_AUTO,   S_RegisterSound("weapons/shotgr1b.wav"), volume, ATTN_NORM, 0.1);
  298                 break;
  299         case MZ_SSHOTGUN:
  300                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  301                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/sshotf1b.wav"), volume, ATTN_NORM, 0);
  302                 break;
  303         case MZ_CHAINGUN1:
  304                 dl->radius = 200 + (rand()&31);
  305                 dl->color[0] = 1;dl->color[1] = 0.25;dl->color[2] = 0;
  306                 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
  307                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
  308                 break;
  309         case MZ_CHAINGUN2:
  310                 dl->radius = 225 + (rand()&31);
  311                 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
  312                 dl->die = cl.time  + 0.1;       // long delay
  313                 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
  314                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
  315                 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
  316                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.05);
  317                 break;
  318         case MZ_CHAINGUN3:
  319                 dl->radius = 250 + (rand()&31);
  320                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  321                 dl->die = cl.time  + 0.1;       // long delay
  322                 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
  323                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0);
  324                 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
  325                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.033);
  326                 Com_sprintf(soundname, sizeof(soundname), "weapons/machgf%ib.wav", (rand() % 5) + 1);
  327                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound(soundname), volume, ATTN_NORM, 0.066);
  328                 break;
  329         case MZ_RAILGUN:
  330                 dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0;
  331                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/railgf1a.wav"), volume, ATTN_NORM, 0);
  332                 break;
  333         case MZ_ROCKET:
  334                 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
  335                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rocklf1a.wav"), volume, ATTN_NORM, 0);
  336                 S_StartSound (NULL, i, CHAN_AUTO,   S_RegisterSound("weapons/rocklr1b.wav"), volume, ATTN_NORM, 0.1);
  337                 break;
  338         case MZ_GRENADE:
  339                 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
  340                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), volume, ATTN_NORM, 0);
  341                 S_StartSound (NULL, i, CHAN_AUTO,   S_RegisterSound("weapons/grenlr1b.wav"), volume, ATTN_NORM, 0.1);
  342                 break;
  343         case MZ_BFG:
  344                 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
  345                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__f1y.wav"), volume, ATTN_NORM, 0);
  346                 break;
  347 
  348         case MZ_LOGIN:
  349                 dl->color[0] = 0;dl->color[1] = 1; dl->color[2] = 0;
  350                 dl->die = cl.time + 1.0;
  351                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
  352                 CL_LogoutEffect (pl->current.origin, weapon);
  353                 break;
  354         case MZ_LOGOUT:
  355                 dl->color[0] = 1;dl->color[1] = 0; dl->color[2] = 0;
  356                 dl->die = cl.time + 1.0;
  357                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
  358                 CL_LogoutEffect (pl->current.origin, weapon);
  359                 break;
  360         case MZ_RESPAWN:
  361                 dl->color[0] = 1;dl->color[1] = 1; dl->color[2] = 0;
  362                 dl->die = cl.time + 1.0;
  363                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/grenlf1a.wav"), 1, ATTN_NORM, 0);
  364                 CL_LogoutEffect (pl->current.origin, weapon);
  365                 break;
  366         // RAFAEL
  367         case MZ_PHALANX:
  368                 dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
  369                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/plasshot.wav"), volume, ATTN_NORM, 0);
  370                 break;
  371         // RAFAEL
  372         case MZ_IONRIPPER:      
  373                 dl->color[0] = 1;dl->color[1] = 0.5; dl->color[2] = 0.5;
  374                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/rippfire.wav"), volume, ATTN_NORM, 0);
  375                 break;
  376 
  377 // ======================
  378 // PGM
  379         case MZ_ETF_RIFLE:
  380                 dl->color[0] = 0.9;dl->color[1] = 0.7;dl->color[2] = 0;
  381                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/nail1.wav"), volume, ATTN_NORM, 0);
  382                 break;
  383         case MZ_SHOTGUN2:
  384                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  385                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/shotg2.wav"), volume, ATTN_NORM, 0);
  386                 break;
  387         case MZ_HEATBEAM:
  388                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  389                 dl->die = cl.time + 100;
  390 //              S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/bfg__l1a.wav"), volume, ATTN_NORM, 0);
  391                 break;
  392         case MZ_BLASTER2:
  393                 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
  394                 // FIXME - different sound for blaster2 ??
  395                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/blastf1a.wav"), volume, ATTN_NORM, 0);
  396                 break;
  397         case MZ_TRACKER:
  398                 // negative flashes handled the same in gl/soft until CL_AddDLights
  399                 dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1;
  400                 S_StartSound (NULL, i, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), volume, ATTN_NORM, 0);
  401                 break;          
  402         case MZ_NUKE1:
  403                 dl->color[0] = 1;dl->color[1] = 0;dl->color[2] = 0;
  404                 dl->die = cl.time + 100;
  405                 break;
  406         case MZ_NUKE2:
  407                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  408                 dl->die = cl.time + 100;
  409                 break;
  410         case MZ_NUKE4:
  411                 dl->color[0] = 0;dl->color[1] = 0;dl->color[2] = 1;
  412                 dl->die = cl.time + 100;
  413                 break;
  414         case MZ_NUKE8:
  415                 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 1;
  416                 dl->die = cl.time + 100;
  417                 break;
  418 // PGM
  419 // ======================
  420         }
  421 }
  422 
  423 
  424 /*
  425 ==============
  426 CL_ParseMuzzleFlash2
  427 ==============
  428 */
  429 void CL_ParseMuzzleFlash2 (void) 
  430 {
  431         int                     ent;
  432         vec3_t          origin;
  433         int                     flash_number;
  434         cdlight_t       *dl;
  435         vec3_t          forward, right;
  436         char            soundname[64];
  437 
  438         ent = MSG_ReadShort (&net_message);
  439         if (ent < 1 || ent >= MAX_EDICTS)
  440                 Com_Error (ERR_DROP, "CL_ParseMuzzleFlash2: bad entity");
  441 
  442         flash_number = MSG_ReadByte (&net_message);
  443 
  444         // locate the origin
  445         AngleVectors (cl_entities[ent].current.angles, forward, right, NULL);
  446         origin[0] = cl_entities[ent].current.origin[0] + forward[0] * monster_flash_offset[flash_number][0] + right[0] * monster_flash_offset[flash_number][1];
  447         origin[1] = cl_entities[ent].current.origin[1] + forward[1] * monster_flash_offset[flash_number][0] + right[1] * monster_flash_offset[flash_number][1];
  448         origin[2] = cl_entities[ent].current.origin[2] + forward[2] * monster_flash_offset[flash_number][0] + right[2] * monster_flash_offset[flash_number][1] + monster_flash_offset[flash_number][2];
  449 
  450         dl = CL_AllocDlight (ent);
  451         VectorCopy (origin,  dl->origin);
  452         dl->radius = 200 + (rand()&31);
  453         dl->minlight = 32;
  454         dl->die = cl.time;      // + 0.1;
  455 
  456         switch (flash_number)
  457         {
  458         case MZ2_INFANTRY_MACHINEGUN_1:
  459         case MZ2_INFANTRY_MACHINEGUN_2:
  460         case MZ2_INFANTRY_MACHINEGUN_3:
  461         case MZ2_INFANTRY_MACHINEGUN_4:
  462         case MZ2_INFANTRY_MACHINEGUN_5:
  463         case MZ2_INFANTRY_MACHINEGUN_6:
  464         case MZ2_INFANTRY_MACHINEGUN_7:
  465         case MZ2_INFANTRY_MACHINEGUN_8:
  466         case MZ2_INFANTRY_MACHINEGUN_9:
  467         case MZ2_INFANTRY_MACHINEGUN_10:
  468         case MZ2_INFANTRY_MACHINEGUN_11:
  469         case MZ2_INFANTRY_MACHINEGUN_12:
  470         case MZ2_INFANTRY_MACHINEGUN_13:
  471                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  472                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  473                 CL_SmokeAndFlash(origin);
  474                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
  475                 break;
  476 
  477         case MZ2_SOLDIER_MACHINEGUN_1:
  478         case MZ2_SOLDIER_MACHINEGUN_2:
  479         case MZ2_SOLDIER_MACHINEGUN_3:
  480         case MZ2_SOLDIER_MACHINEGUN_4:
  481         case MZ2_SOLDIER_MACHINEGUN_5:
  482         case MZ2_SOLDIER_MACHINEGUN_6:
  483         case MZ2_SOLDIER_MACHINEGUN_7:
  484         case MZ2_SOLDIER_MACHINEGUN_8:
  485                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  486                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  487                 CL_SmokeAndFlash(origin);
  488                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck3.wav"), 1, ATTN_NORM, 0);
  489                 break;
  490 
  491         case MZ2_GUNNER_MACHINEGUN_1:
  492         case MZ2_GUNNER_MACHINEGUN_2:
  493         case MZ2_GUNNER_MACHINEGUN_3:
  494         case MZ2_GUNNER_MACHINEGUN_4:
  495         case MZ2_GUNNER_MACHINEGUN_5:
  496         case MZ2_GUNNER_MACHINEGUN_6:
  497         case MZ2_GUNNER_MACHINEGUN_7:
  498         case MZ2_GUNNER_MACHINEGUN_8:
  499                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  500                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  501                 CL_SmokeAndFlash(origin);
  502                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck2.wav"), 1, ATTN_NORM, 0);
  503                 break;
  504 
  505         case MZ2_ACTOR_MACHINEGUN_1:
  506         case MZ2_SUPERTANK_MACHINEGUN_1:
  507         case MZ2_SUPERTANK_MACHINEGUN_2:
  508         case MZ2_SUPERTANK_MACHINEGUN_3:
  509         case MZ2_SUPERTANK_MACHINEGUN_4:
  510         case MZ2_SUPERTANK_MACHINEGUN_5:
  511         case MZ2_SUPERTANK_MACHINEGUN_6:
  512         case MZ2_TURRET_MACHINEGUN:                     // PGM
  513                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  514 
  515                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  516                 CL_SmokeAndFlash(origin);
  517                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NORM, 0);
  518                 break;
  519 
  520         case MZ2_BOSS2_MACHINEGUN_L1:
  521         case MZ2_BOSS2_MACHINEGUN_L2:
  522         case MZ2_BOSS2_MACHINEGUN_L3:
  523         case MZ2_BOSS2_MACHINEGUN_L4:
  524         case MZ2_BOSS2_MACHINEGUN_L5:
  525         case MZ2_CARRIER_MACHINEGUN_L1:         // PMM
  526         case MZ2_CARRIER_MACHINEGUN_L2:         // PMM
  527                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  528 
  529                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  530                 CL_SmokeAndFlash(origin);
  531                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("infantry/infatck1.wav"), 1, ATTN_NONE, 0);
  532                 break;
  533 
  534         case MZ2_SOLDIER_BLASTER_1:
  535         case MZ2_SOLDIER_BLASTER_2:
  536         case MZ2_SOLDIER_BLASTER_3:
  537         case MZ2_SOLDIER_BLASTER_4:
  538         case MZ2_SOLDIER_BLASTER_5:
  539         case MZ2_SOLDIER_BLASTER_6:
  540         case MZ2_SOLDIER_BLASTER_7:
  541         case MZ2_SOLDIER_BLASTER_8:
  542         case MZ2_TURRET_BLASTER:                        // PGM
  543                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  544                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck2.wav"), 1, ATTN_NORM, 0);
  545                 break;
  546 
  547         case MZ2_FLYER_BLASTER_1:
  548         case MZ2_FLYER_BLASTER_2:
  549                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  550                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("flyer/flyatck3.wav"), 1, ATTN_NORM, 0);
  551                 break;
  552 
  553         case MZ2_MEDIC_BLASTER_1:
  554                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  555                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("medic/medatck1.wav"), 1, ATTN_NORM, 0);
  556                 break;
  557 
  558         case MZ2_HOVER_BLASTER_1:
  559                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  560                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("hover/hovatck1.wav"), 1, ATTN_NORM, 0);
  561                 break;
  562 
  563         case MZ2_FLOAT_BLASTER_1:
  564                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  565                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("floater/fltatck1.wav"), 1, ATTN_NORM, 0);
  566                 break;
  567 
  568         case MZ2_SOLDIER_SHOTGUN_1:
  569         case MZ2_SOLDIER_SHOTGUN_2:
  570         case MZ2_SOLDIER_SHOTGUN_3:
  571         case MZ2_SOLDIER_SHOTGUN_4:
  572         case MZ2_SOLDIER_SHOTGUN_5:
  573         case MZ2_SOLDIER_SHOTGUN_6:
  574         case MZ2_SOLDIER_SHOTGUN_7:
  575         case MZ2_SOLDIER_SHOTGUN_8:
  576                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  577                 CL_SmokeAndFlash(origin);
  578                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("soldier/solatck1.wav"), 1, ATTN_NORM, 0);
  579                 break;
  580 
  581         case MZ2_TANK_BLASTER_1:
  582         case MZ2_TANK_BLASTER_2:
  583         case MZ2_TANK_BLASTER_3:
  584                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  585                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
  586                 break;
  587 
  588         case MZ2_TANK_MACHINEGUN_1:
  589         case MZ2_TANK_MACHINEGUN_2:
  590         case MZ2_TANK_MACHINEGUN_3:
  591         case MZ2_TANK_MACHINEGUN_4:
  592         case MZ2_TANK_MACHINEGUN_5:
  593         case MZ2_TANK_MACHINEGUN_6:
  594         case MZ2_TANK_MACHINEGUN_7:
  595         case MZ2_TANK_MACHINEGUN_8:
  596         case MZ2_TANK_MACHINEGUN_9:
  597         case MZ2_TANK_MACHINEGUN_10:
  598         case MZ2_TANK_MACHINEGUN_11:
  599         case MZ2_TANK_MACHINEGUN_12:
  600         case MZ2_TANK_MACHINEGUN_13:
  601         case MZ2_TANK_MACHINEGUN_14:
  602         case MZ2_TANK_MACHINEGUN_15:
  603         case MZ2_TANK_MACHINEGUN_16:
  604         case MZ2_TANK_MACHINEGUN_17:
  605         case MZ2_TANK_MACHINEGUN_18:
  606         case MZ2_TANK_MACHINEGUN_19:
  607                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  608                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  609                 CL_SmokeAndFlash(origin);
  610                 Com_sprintf(soundname, sizeof(soundname), "tank/tnkatk2%c.wav", 'a' + rand() % 5);
  611                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound(soundname), 1, ATTN_NORM, 0);
  612                 break;
  613 
  614         case MZ2_CHICK_ROCKET_1:
  615         case MZ2_TURRET_ROCKET:                 // PGM
  616                 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
  617                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("chick/chkatck2.wav"), 1, ATTN_NORM, 0);
  618                 break;
  619 
  620         case MZ2_TANK_ROCKET_1:
  621         case MZ2_TANK_ROCKET_2:
  622         case MZ2_TANK_ROCKET_3:
  623                 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
  624                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck1.wav"), 1, ATTN_NORM, 0);
  625                 break;
  626 
  627         case MZ2_SUPERTANK_ROCKET_1:
  628         case MZ2_SUPERTANK_ROCKET_2:
  629         case MZ2_SUPERTANK_ROCKET_3:
  630         case MZ2_BOSS2_ROCKET_1:
  631         case MZ2_BOSS2_ROCKET_2:
  632         case MZ2_BOSS2_ROCKET_3:
  633         case MZ2_BOSS2_ROCKET_4:
  634         case MZ2_CARRIER_ROCKET_1:
  635 //      case MZ2_CARRIER_ROCKET_2:
  636 //      case MZ2_CARRIER_ROCKET_3:
  637 //      case MZ2_CARRIER_ROCKET_4:
  638                 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0.2;
  639                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/rocket.wav"), 1, ATTN_NORM, 0);
  640                 break;
  641 
  642         case MZ2_GUNNER_GRENADE_1:
  643         case MZ2_GUNNER_GRENADE_2:
  644         case MZ2_GUNNER_GRENADE_3:
  645         case MZ2_GUNNER_GRENADE_4:
  646                 dl->color[0] = 1;dl->color[1] = 0.5;dl->color[2] = 0;
  647                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("gunner/gunatck3.wav"), 1, ATTN_NORM, 0);
  648                 break;
  649 
  650         case MZ2_GLADIATOR_RAILGUN_1:
  651         // PMM
  652         case MZ2_CARRIER_RAILGUN:
  653         case MZ2_WIDOW_RAIL:
  654         // pmm
  655                 dl->color[0] = 0.5;dl->color[1] = 0.5;dl->color[2] = 1.0;
  656                 break;
  657 
  658 // --- Xian's shit starts ---
  659         case MZ2_MAKRON_BFG:
  660                 dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5;
  661                 //S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/bfg_fire.wav"), 1, ATTN_NORM, 0);
  662                 break;
  663 
  664         case MZ2_MAKRON_BLASTER_1:
  665         case MZ2_MAKRON_BLASTER_2:
  666         case MZ2_MAKRON_BLASTER_3:
  667         case MZ2_MAKRON_BLASTER_4:
  668         case MZ2_MAKRON_BLASTER_5:
  669         case MZ2_MAKRON_BLASTER_6:
  670         case MZ2_MAKRON_BLASTER_7:
  671         case MZ2_MAKRON_BLASTER_8:
  672         case MZ2_MAKRON_BLASTER_9:
  673         case MZ2_MAKRON_BLASTER_10:
  674         case MZ2_MAKRON_BLASTER_11:
  675         case MZ2_MAKRON_BLASTER_12:
  676         case MZ2_MAKRON_BLASTER_13:
  677         case MZ2_MAKRON_BLASTER_14:
  678         case MZ2_MAKRON_BLASTER_15:
  679         case MZ2_MAKRON_BLASTER_16:
  680         case MZ2_MAKRON_BLASTER_17:
  681                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  682                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("makron/blaster.wav"), 1, ATTN_NORM, 0);
  683                 break;
  684         
  685         case MZ2_JORG_MACHINEGUN_L1:
  686         case MZ2_JORG_MACHINEGUN_L2:
  687         case MZ2_JORG_MACHINEGUN_L3:
  688         case MZ2_JORG_MACHINEGUN_L4:
  689         case MZ2_JORG_MACHINEGUN_L5:
  690         case MZ2_JORG_MACHINEGUN_L6:
  691                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  692                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  693                 CL_SmokeAndFlash(origin);
  694                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("boss3/xfire.wav"), 1, ATTN_NORM, 0);
  695                 break;
  696 
  697         case MZ2_JORG_MACHINEGUN_R1:
  698         case MZ2_JORG_MACHINEGUN_R2:
  699         case MZ2_JORG_MACHINEGUN_R3:
  700         case MZ2_JORG_MACHINEGUN_R4:
  701         case MZ2_JORG_MACHINEGUN_R5:
  702         case MZ2_JORG_MACHINEGUN_R6:
  703                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  704                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  705                 CL_SmokeAndFlash(origin);
  706                 break;
  707 
  708         case MZ2_JORG_BFG_1:
  709                 dl->color[0] = 0.5;dl->color[1] = 1 ;dl->color[2] = 0.5;
  710                 break;
  711 
  712         case MZ2_BOSS2_MACHINEGUN_R1:
  713         case MZ2_BOSS2_MACHINEGUN_R2:
  714         case MZ2_BOSS2_MACHINEGUN_R3:
  715         case MZ2_BOSS2_MACHINEGUN_R4:
  716         case MZ2_BOSS2_MACHINEGUN_R5:
  717         case MZ2_CARRIER_MACHINEGUN_R1:                 // PMM
  718         case MZ2_CARRIER_MACHINEGUN_R2:                 // PMM
  719 
  720                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  721 
  722                 CL_ParticleEffect (origin, vec3_origin, 0, 40);
  723                 CL_SmokeAndFlash(origin);
  724                 break;
  725 
  726 // ======
  727 // ROGUE
  728         case MZ2_STALKER_BLASTER:
  729         case MZ2_DAEDALUS_BLASTER:
  730         case MZ2_MEDIC_BLASTER_2:
  731         case MZ2_WIDOW_BLASTER:
  732         case MZ2_WIDOW_BLASTER_SWEEP1:
  733         case MZ2_WIDOW_BLASTER_SWEEP2:
  734         case MZ2_WIDOW_BLASTER_SWEEP3:
  735         case MZ2_WIDOW_BLASTER_SWEEP4:
  736         case MZ2_WIDOW_BLASTER_SWEEP5:
  737         case MZ2_WIDOW_BLASTER_SWEEP6:
  738         case MZ2_WIDOW_BLASTER_SWEEP7:
  739         case MZ2_WIDOW_BLASTER_SWEEP8:
  740         case MZ2_WIDOW_BLASTER_SWEEP9:
  741         case MZ2_WIDOW_BLASTER_100:
  742         case MZ2_WIDOW_BLASTER_90:
  743         case MZ2_WIDOW_BLASTER_80:
  744         case MZ2_WIDOW_BLASTER_70:
  745         case MZ2_WIDOW_BLASTER_60:
  746         case MZ2_WIDOW_BLASTER_50:
  747         case MZ2_WIDOW_BLASTER_40:
  748         case MZ2_WIDOW_BLASTER_30:
  749         case MZ2_WIDOW_BLASTER_20:
  750         case MZ2_WIDOW_BLASTER_10:
  751         case MZ2_WIDOW_BLASTER_0:
  752         case MZ2_WIDOW_BLASTER_10L:
  753         case MZ2_WIDOW_BLASTER_20L:
  754         case MZ2_WIDOW_BLASTER_30L:
  755         case MZ2_WIDOW_BLASTER_40L:
  756         case MZ2_WIDOW_BLASTER_50L:
  757         case MZ2_WIDOW_BLASTER_60L:
  758         case MZ2_WIDOW_BLASTER_70L:
  759         case MZ2_WIDOW_RUN_1:
  760         case MZ2_WIDOW_RUN_2:
  761         case MZ2_WIDOW_RUN_3:
  762         case MZ2_WIDOW_RUN_4:
  763         case MZ2_WIDOW_RUN_5:
  764         case MZ2_WIDOW_RUN_6:
  765         case MZ2_WIDOW_RUN_7:
  766         case MZ2_WIDOW_RUN_8:
  767                 dl->color[0] = 0;dl->color[1] = 1;dl->color[2] = 0;
  768                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("tank/tnkatck3.wav"), 1, ATTN_NORM, 0);
  769                 break;
  770 
  771         case MZ2_WIDOW_DISRUPTOR:
  772                 dl->color[0] = -1;dl->color[1] = -1;dl->color[2] = -1;
  773                 S_StartSound (NULL, ent, CHAN_WEAPON, S_RegisterSound("weapons/disint2.wav"), 1, ATTN_NORM, 0);
  774                 break;
  775 
  776         case MZ2_WIDOW_PLASMABEAM:
  777         case MZ2_WIDOW2_BEAMER_1:
  778         case MZ2_WIDOW2_BEAMER_2:
  779         case MZ2_WIDOW2_BEAMER_3:
  780         case MZ2_WIDOW2_BEAMER_4:
  781         case MZ2_WIDOW2_BEAMER_5:
  782         case MZ2_WIDOW2_BEAM_SWEEP_1:
  783         case MZ2_WIDOW2_BEAM_SWEEP_2:
  784         case MZ2_WIDOW2_BEAM_SWEEP_3:
  785         case MZ2_WIDOW2_BEAM_SWEEP_4:
  786         case MZ2_WIDOW2_BEAM_SWEEP_5:
  787         case MZ2_WIDOW2_BEAM_SWEEP_6:
  788         case MZ2_WIDOW2_BEAM_SWEEP_7:
  789         case MZ2_WIDOW2_BEAM_SWEEP_8:
  790         case MZ2_WIDOW2_BEAM_SWEEP_9:
  791         case MZ2_WIDOW2_BEAM_SWEEP_10:
  792         case MZ2_WIDOW2_BEAM_SWEEP_11:
  793                 dl->radius = 300 + (rand()&100);
  794                 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 0;
  795                 dl->die = cl.time + 200;
  796                 break;
  797 // ROGUE
  798 // ======
  799 
  800 // --- Xian's shit ends ---
  801 
  802         }
  803 }
  804 
  805 
  806 /*
  807 ===============
  808 CL_AddDLights
  809 
  810 ===============
  811 */
  812 void CL_AddDLights (void)
  813 {
  814         int                     i;
  815         cdlight_t       *dl;
  816 
  817         dl = cl_dlights;
  818 
  819 //=====
  820 //PGM
  821         if(vidref_val == VIDREF_GL)
  822         {
  823                 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
  824                 {
  825                         if (!dl->radius)
  826                                 continue;
  827                         V_AddLight (dl->origin, dl->radius,
  828                                 dl->color[0], dl->color[1], dl->color[2]);
  829                 }
  830         }
  831         else
  832         {
  833                 for (i=0 ; i<MAX_DLIGHTS ; i++, dl++)
  834                 {
  835                         if (!dl->radius)
  836                                 continue;
  837 
  838                         // negative light in software. only black allowed
  839                         if ((dl->color[0] < 0) || (dl->color[1] < 0) || (dl->color[2] < 0))
  840                         {
  841                                 dl->radius = -(dl->radius);
  842                                 dl->color[0] = 1;
  843                                 dl->color[1] = 1;
  844                                 dl->color[2] = 1;
  845                         }
  846                         V_AddLight (dl->origin, dl->radius,
  847                                 dl->color[0], dl->color[1], dl->color[2]);
  848                 }
  849         }
  850 //PGM
  851 //=====
  852 }
  853 
  854 
  855 
  856 /*
  857 ==============================================================
  858 
  859 PARTICLE MANAGEMENT
  860 
  861 ==============================================================
  862 */
  863 
  864 /*
  865 // THIS HAS BEEN RELOCATED TO CLIENT.H
  866 typedef struct particle_s
  867 {
  868         struct particle_s       *next;
  869 
  870         float           time;
  871 
  872         vec3_t          org;
  873         vec3_t          vel;
  874         vec3_t          accel;
  875         float           color;
  876         float           colorvel;
  877         float           alpha;
  878         float           alphavel;
  879 } cparticle_t;
  880 
  881 
  882 #define PARTICLE_GRAVITY        40
  883 */
  884 
  885 cparticle_t     *active_particles, *free_particles;
  886 
  887 cparticle_t     particles[MAX_PARTICLES];
  888 int                     cl_numparticles = MAX_PARTICLES;
  889 
  890 
  891 /*
  892 ===============
  893 CL_ClearParticles
  894 ===============
  895 */
  896 void CL_ClearParticles (void)
  897 {
  898         int             i;
  899         
  900         free_particles = &particles[0];
  901         active_particles = NULL;
  902 
  903         for (i=0 ;i<cl_numparticles ; i++)
  904                 particles[i].next = &particles[i+1];
  905         particles[cl_numparticles-1].next = NULL;
  906 }
  907 
  908 
  909 /*
  910 ===============
  911 CL_ParticleEffect
  912 
  913 Wall impact puffs
  914 ===============
  915 */
  916 void CL_ParticleEffect (vec3_t org, vec3_t dir, int color, int count)
  917 {
  918         int                     i, j;
  919         cparticle_t     *p;
  920         float           d;
  921 
  922         for (i=0 ; i<count ; i++)
  923         {
  924                 if (!free_particles)
  925                         return;
  926                 p = free_particles;
  927                 free_particles = p->next;
  928                 p->next = active_particles;
  929                 active_particles = p;
  930 
  931                 p->time = cl.time;
  932                 p->color = color + (rand()&7);
  933 
  934                 d = rand()&31;
  935                 for (j=0 ; j<3 ; j++)
  936                 {
  937                         p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
  938                         p->vel[j] = crand()*20;
  939                 }
  940 
  941                 p->accel[0] = p->accel[1] = 0;
  942                 p->accel[2] = -PARTICLE_GRAVITY;
  943                 p->alpha = 1.0;
  944 
  945                 p->alphavel = -1.0 / (0.5 + frand()*0.3);
  946         }
  947 }
  948 
  949 
  950 /*
  951 ===============
  952 CL_ParticleEffect2
  953 ===============
  954 */
  955 void CL_ParticleEffect2 (vec3_t org, vec3_t dir, int color, int count)
  956 {
  957         int                     i, j;
  958         cparticle_t     *p;
  959         float           d;
  960 
  961         for (i=0 ; i<count ; i++)
  962         {
  963                 if (!free_particles)
  964                         return;
  965                 p = free_particles;
  966                 free_particles = p->next;
  967                 p->next = active_particles;
  968                 active_particles = p;
  969 
  970                 p->time = cl.time;
  971                 p->color = color;
  972 
  973                 d = rand()&7;
  974                 for (j=0 ; j<3 ; j++)
  975                 {
  976                         p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
  977                         p->vel[j] = crand()*20;
  978                 }
  979 
  980                 p->accel[0] = p->accel[1] = 0;
  981                 p->accel[2] = -PARTICLE_GRAVITY;
  982                 p->alpha = 1.0;
  983 
  984                 p->alphavel = -1.0 / (0.5 + frand()*0.3);
  985         }
  986 }
  987 
  988 
  989 // RAFAEL
  990 /*
  991 ===============
  992 CL_ParticleEffect3
  993 ===============
  994 */
  995 void CL_ParticleEffect3 (vec3_t org, vec3_t dir, int color, int count)
  996 {
  997         int                     i, j;
  998         cparticle_t     *p;
  999         float           d;
 1000 
 1001         for (i=0 ; i<count ; i++)
 1002         {
 1003                 if (!free_particles)
 1004                         return;
 1005                 p = free_particles;
 1006                 free_particles = p->next;
 1007                 p->next = active_particles;
 1008                 active_particles = p;
 1009 
 1010                 p->time = cl.time;
 1011                 p->color = color;
 1012 
 1013                 d = rand()&7;
 1014                 for (j=0 ; j<3 ; j++)
 1015                 {
 1016                         p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
 1017                         p->vel[j] = crand()*20;
 1018                 }
 1019 
 1020                 p->accel[0] = p->accel[1] = 0;
 1021                 p->accel[2] = PARTICLE_GRAVITY;
 1022                 p->alpha = 1.0;
 1023 
 1024                 p->alphavel = -1.0 / (0.5 + frand()*0.3);
 1025         }
 1026 }
 1027 
 1028 /*
 1029 ===============
 1030 CL_TeleporterParticles
 1031 ===============
 1032 */
 1033 void CL_TeleporterParticles (entity_state_t *ent)
 1034 {
 1035         int                     i, j;
 1036         cparticle_t     *p;
 1037 
 1038         for (i=0 ; i<8 ; i++)
 1039         {
 1040                 if (!free_particles)
 1041                         return;
 1042                 p = free_particles;
 1043                 free_particles = p->next;
 1044                 p->next = active_particles;
 1045                 active_particles = p;
 1046 
 1047                 p->time = cl.time;
 1048                 p->color = 0xdb;
 1049 
 1050                 for (j=0 ; j<2 ; j++)
 1051                 {
 1052                         p->org[j] = ent->origin[j] - 16 + (rand()&31);
 1053                         p->vel[j] = crand()*14;
 1054                 }
 1055 
 1056                 p->org[2] = ent->origin[2] - 8 + (rand()&7);
 1057                 p->vel[2] = 80 + (rand()&7);
 1058 
 1059                 p->accel[0] = p->accel[1] = 0;
 1060                 p->accel[2] = -PARTICLE_GRAVITY;
 1061                 p->alpha = 1.0;
 1062 
 1063                 p->alphavel = -0.5;
 1064         }
 1065 }
 1066 
 1067 
 1068 /*
 1069 ===============
 1070 CL_LogoutEffect
 1071 
 1072 ===============
 1073 */
 1074 void CL_LogoutEffect (vec3_t org, int type)
 1075 {
 1076         int                     i, j;
 1077         cparticle_t     *p;
 1078 
 1079         for (i=0 ; i<500 ; i++)
 1080         {
 1081                 if (!free_particles)
 1082                         return;
 1083                 p = free_particles;
 1084                 free_particles = p->next;
 1085                 p->next = active_particles;
 1086                 active_particles = p;
 1087 
 1088                 p->time = cl.time;
 1089 
 1090                 if (type == MZ_LOGIN)
 1091                         p->color = 0xd0 + (rand()&7);   // green
 1092                 else if (type == MZ_LOGOUT)
 1093                         p->color = 0x40 + (rand()&7);   // red
 1094                 else
 1095                         p->color = 0xe0 + (rand()&7);   // yellow
 1096 
 1097                 p->org[0] = org[0] - 16 + frand()*32;
 1098                 p->org[1] = org[1] - 16 + frand()*32;
 1099                 p->org[2] = org[2] - 24 + frand()*56;
 1100 
 1101                 for (j=0 ; j<3 ; j++)
 1102                         p->vel[j] = crand()*20;
 1103 
 1104                 p->accel[0] = p->accel[1] = 0;
 1105                 p->accel[2] = -PARTICLE_GRAVITY;
 1106                 p->alpha = 1.0;
 1107 
 1108                 p->alphavel = -1.0 / (1.0 + frand()*0.3);
 1109         }
 1110 }
 1111 
 1112 
 1113 /*
 1114 ===============
 1115 CL_ItemRespawnParticles
 1116 
 1117 ===============
 1118 */
 1119 void CL_ItemRespawnParticles (vec3_t org)
 1120 {
 1121         int                     i, j;
 1122         cparticle_t     *p;
 1123 
 1124         for (i=0 ; i<64 ; i++)
 1125         {
 1126                 if (!free_particles)
 1127                         return;
 1128                 p = free_particles;
 1129                 free_particles = p->next;
 1130                 p->next = active_particles;
 1131                 active_particles = p;
 1132 
 1133                 p->time = cl.time;
 1134 
 1135                 p->color = 0xd4 + (rand()&3);   // green
 1136 
 1137                 p->org[0] = org[0] + crand()*8;
 1138                 p->org[1] = org[1] + crand()*8;
 1139                 p->org[2] = org[2] + crand()*8;
 1140 
 1141                 for (j=0 ; j<3 ; j++)
 1142                         p->vel[j] = crand()*8;
 1143 
 1144                 p->accel[0] = p->accel[1] = 0;
 1145                 p->accel[2] = -PARTICLE_GRAVITY*0.2;
 1146                 p->alpha = 1.0;
 1147 
 1148                 p->alphavel = -1.0 / (1.0 + frand()*0.3);
 1149         }
 1150 }
 1151 
 1152 
 1153 /*
 1154 ===============
 1155 CL_ExplosionParticles
 1156 ===============
 1157 */
 1158 void CL_ExplosionParticles (vec3_t org)
 1159 {
 1160         int                     i, j;
 1161         cparticle_t     *p;
 1162 
 1163         for (i=0 ; i<256 ; i++)
 1164         {
 1165                 if (!free_particles)
 1166                         return;
 1167                 p = free_particles;
 1168                 free_particles = p->next;
 1169                 p->next = active_particles;
 1170                 active_particles = p;
 1171 
 1172                 p->time = cl.time;
 1173                 p->color = 0xe0 + (rand()&7);
 1174 
 1175                 for (j=0 ; j<3 ; j++)
 1176                 {
 1177                         p->org[j] = org[j] + ((rand()%32)-16);
 1178                         p->vel[j] = (rand()%384)-192;
 1179                 }
 1180 
 1181                 p->accel[0] = p->accel[1] = 0;
 1182                 p->accel[2] = -PARTICLE_GRAVITY;
 1183                 p->alpha = 1.0;
 1184 
 1185                 p->alphavel = -0.8 / (0.5 + frand()*0.3);
 1186         }
 1187 }
 1188 
 1189 
 1190 /*
 1191 ===============
 1192 CL_BigTeleportParticles
 1193 ===============
 1194 */
 1195 void CL_BigTeleportParticles (vec3_t org)
 1196 {
 1197         int                     i;
 1198         cparticle_t     *p;
 1199         float           angle, dist;
 1200         static int colortable[4] = {2*8,13*8,21*8,18*8};
 1201 
 1202         for (i=0 ; i<4096 ; i++)
 1203         {
 1204                 if (!free_particles)
 1205                         return;
 1206                 p = free_particles;
 1207                 free_particles = p->next;
 1208                 p->next = active_particles;
 1209                 active_particles = p;
 1210 
 1211                 p->time = cl.time;
 1212 
 1213                 p->color = colortable[rand()&3];
 1214 
 1215                 angle = M_PI*2*(rand()&1023)/1023.0;
 1216                 dist = rand()&31;
 1217                 p->org[0] = org[0] + cos(angle)*dist;
 1218                 p->vel[0] = cos(angle)*(70+(rand()&63));
 1219                 p->accel[0] = -cos(angle)*100;
 1220 
 1221                 p->org[1] = org[1] + sin(angle)*dist;
 1222                 p->vel[1] = sin(angle)*(70+(rand()&63));
 1223                 p->accel[1] = -sin(angle)*100;
 1224 
 1225                 p->org[2] = org[2] + 8 + (rand()%90);
 1226                 p->vel[2] = -100 + (rand()&31);
 1227                 p->accel[2] = PARTICLE_GRAVITY*4;
 1228                 p->alpha = 1.0;
 1229 
 1230                 p->alphavel = -0.3 / (0.5 + frand()*0.3);
 1231         }
 1232 }
 1233 
 1234 
 1235 /*
 1236 ===============
 1237 CL_BlasterParticles
 1238 
 1239 Wall impact puffs
 1240 ===============
 1241 */
 1242 void CL_BlasterParticles (vec3_t org, vec3_t dir)
 1243 {
 1244         int                     i, j;
 1245         cparticle_t     *p;
 1246         float           d;
 1247         int                     count;
 1248 
 1249         count = 40;
 1250         for (i=0 ; i<count ; i++)
 1251         {
 1252                 if (!free_particles)
 1253                         return;
 1254                 p = free_particles;
 1255                 free_particles = p->next;
 1256                 p->next = active_particles;
 1257                 active_particles = p;
 1258 
 1259                 p->time = cl.time;
 1260                 p->color = 0xe0 + (rand()&7);
 1261 
 1262                 d = rand()&15;
 1263                 for (j=0 ; j<3 ; j++)
 1264                 {
 1265                         p->org[j] = org[j] + ((rand()&7)-4) + d*dir[j];
 1266                         p->vel[j] = dir[j] * 30 + crand()*40;
 1267                 }
 1268 
 1269                 p->accel[0] = p->accel[1] = 0;
 1270                 p->accel[2] = -PARTICLE_GRAVITY;
 1271                 p->alpha = 1.0;
 1272 
 1273                 p->alphavel = -1.0 / (0.5 + frand()*0.3);
 1274         }
 1275 }
 1276 
 1277 
 1278 /*
 1279 ===============
 1280 CL_BlasterTrail
 1281 
 1282 ===============
 1283 */
 1284 void CL_BlasterTrail (vec3_t start, vec3_t end)
 1285 {
 1286         vec3_t          move;
 1287         vec3_t          vec;
 1288         float           len;
 1289         int                     j;
 1290         cparticle_t     *p;
 1291         int                     dec;
 1292 
 1293         VectorCopy (start, move);
 1294         VectorSubtract (end, start, vec);
 1295         len = VectorNormalize (vec);
 1296 
 1297         dec = 5;
 1298         VectorScale (vec, 5, vec);
 1299 
 1300         // FIXME: this is a really silly way to have a loop
 1301         while (len > 0)
 1302         {
 1303                 len -= dec;
 1304 
 1305                 if (!free_particles)
 1306                         return;
 1307                 p = free_particles;
 1308                 free_particles = p->next;
 1309                 p->next = active_particles;
 1310                 active_particles = p;
 1311                 VectorClear (p->accel);
 1312                 
 1313                 p->time = cl.time;
 1314 
 1315                 p->alpha = 1.0;
 1316                 p->alphavel = -1.0 / (0.3+frand()*0.2);
 1317                 p->color = 0xe0;
 1318                 for (j=0 ; j<3 ; j++)
 1319                 {
 1320                         p->org[j] = move[j] + crand();
 1321                         p->vel[j] = crand()*5;
 1322                         p->accel[j] = 0;
 1323                 }
 1324 
 1325                 VectorAdd (move, vec, move);
 1326         }
 1327 }
 1328 
 1329 /*
 1330 ===============
 1331 CL_QuadTrail
 1332 
 1333 ===============
 1334 */
 1335 void CL_QuadTrail (vec3_t start, vec3_t end)
 1336 {
 1337         vec3_t          move;
 1338         vec3_t          vec;
 1339         float           len;
 1340         int                     j;
 1341         cparticle_t     *p;
 1342         int                     dec;
 1343 
 1344         VectorCopy (start, move);
 1345         VectorSubtract (end, start, vec);
 1346         len = VectorNormalize (vec);
 1347 
 1348         dec = 5;
 1349         VectorScale (vec, 5, vec);
 1350 
 1351         while (len > 0)
 1352         {
 1353                 len -= dec;
 1354 
 1355                 if (!free_particles)
 1356                         return;
 1357                 p = free_particles;
 1358                 free_particles = p->next;
 1359                 p->next = active_particles;
 1360                 active_particles = p;
 1361                 VectorClear (p->accel);
 1362                 
 1363                 p->time = cl.time;
 1364 
 1365                 p->alpha = 1.0;
 1366                 p->alphavel = -1.0 / (0.8+frand()*0.2);
 1367                 p->color = 115;
 1368                 for (j=0 ; j<3 ; j++)
 1369                 {
 1370                         p->org[j] = move[j] + crand()*16;
 1371                         p->vel[j] = crand()*5;
 1372                         p->accel[j] = 0;
 1373                 }
 1374 
 1375                 VectorAdd (move, vec, move);
 1376         }
 1377 }
 1378 
 1379 /*
 1380 ===============
 1381 CL_FlagTrail
 1382 
 1383 ===============
 1384 */
 1385 void CL_FlagTrail (vec3_t start, vec3_t end, float color)
 1386 {
 1387         vec3_t          move;
 1388         vec3_t          vec;
 1389         float           len;
 1390         int                     j;
 1391         cparticle_t     *p;
 1392         int                     dec;
 1393 
 1394         VectorCopy (start, move);
 1395         VectorSubtract (end, start, vec);
 1396         len = VectorNormalize (vec);
 1397 
 1398         dec = 5;
 1399         VectorScale (vec, 5, vec);
 1400 
 1401         while (len > 0)
 1402         {
 1403                 len -= dec;
 1404 
 1405                 if (!free_particles)
 1406                         return;
 1407                 p = free_particles;
 1408                 free_particles = p->next;
 1409                 p->next = active_particles;
 1410                 active_particles = p;
 1411                 VectorClear (p->accel);
 1412                 
 1413                 p->time = cl.time;
 1414 
 1415                 p->alpha = 1.0;
 1416                 p->alphavel = -1.0 / (0.8+frand()*0.2);
 1417                 p->color = color;
 1418                 for (j=0 ; j<3 ; j++)
 1419                 {
 1420                         p->org[j] = move[j] + crand()*16;
 1421                         p->vel[j] = crand()*5;
 1422                         p->accel[j] = 0;
 1423                 }
 1424 
 1425                 VectorAdd (move, vec, move);
 1426         }
 1427 }
 1428 
 1429 /*
 1430 ===============
 1431 CL_DiminishingTrail
 1432 
 1433 ===============
 1434 */
 1435 void CL_DiminishingTrail (vec3_t start, vec3_t end, centity_t *old, int flags)
 1436 {
 1437         vec3_t          move;
 1438         vec3_t          vec;
 1439         float           len;
 1440         int                     j;
 1441         cparticle_t     *p;
 1442         float           dec;
 1443         float           orgscale;
 1444         float           velscale;
 1445 
 1446         VectorCopy (start, move);
 1447         VectorSubtract (end, start, vec);
 1448         len = VectorNormalize (vec);
 1449 
 1450         dec = 0.5;
 1451         VectorScale (vec, dec, vec);
 1452 
 1453         if (old->trailcount > 900)
 1454         {
 1455                 orgscale = 4;
 1456                 velscale = 15;
 1457         }
 1458         else if (old->trailcount > 800)
 1459         {
 1460                 orgscale = 2;
 1461                 velscale = 10;
 1462         }
 1463         else
 1464         {
 1465                 orgscale = 1;
 1466                 velscale = 5;
 1467         }
 1468 
 1469         while (len > 0)
 1470         {
 1471                 len -= dec;
 1472 
 1473                 if (!free_particles)
 1474                         return;
 1475 
 1476                 // drop less particles as it flies
 1477                 if ((rand()&1023) < old->trailcount)
 1478                 {
 1479                         p = free_particles;
 1480                         free_particles = p->next;
 1481                         p->next = active_particles;
 1482                         active_particles = p;
 1483                         VectorClear (p->accel);
 1484                 
 1485                         p->time = cl.time;
 1486 
 1487                         if (flags & EF_GIB)
 1488                         {
 1489                                 p->alpha = 1.0;
 1490                                 p->alphavel = -1.0 / (1+frand()*0.4);
 1491                                 p->color = 0xe8 + (rand()&7);
 1492                                 for (j=0 ; j<3 ; j++)
 1493                                 {
 1494                                         p->org[j] = move[j] + crand()*orgscale;
 1495                                         p->vel[j] = crand()*velscale;
 1496                                         p->accel[j] = 0;
 1497                                 }
 1498                                 p->vel[2] -= PARTICLE_GRAVITY;
 1499                         }
 1500                         else if (flags & EF_GREENGIB)
 1501                         {
 1502                                 p->alpha = 1.0;
 1503                                 p->alphavel = -1.0 / (1+frand()*0.4);
 1504                                 p->color = 0xdb + (rand()&7);
 1505                                 for (j=0; j< 3; j++)
 1506                                 {
 1507                                         p->org[j] = move[j] + crand()*orgscale;
 1508                                         p->vel[j] = crand()*velscale;
 1509                                         p->accel[j] = 0;
 1510                                 }
 1511                                 p->vel[2] -= PARTICLE_GRAVITY;
 1512                         }
 1513                         else
 1514                         {
 1515                                 p->alpha = 1.0;
 1516                                 p->alphavel = -1.0 / (1+frand()*0.2);
 1517                                 p->color = 4 + (rand()&7);
 1518                                 for (j=0 ; j<3 ; j++)
 1519                                 {
 1520                                         p->org[j] = move[j] + crand()*orgscale;
 1521                                         p->vel[j] = crand()*velscale;
 1522                                 }
 1523                                 p->accel[2] = 20;
 1524                         }
 1525                 }
 1526 
 1527                 old->trailcount -= 5;
 1528                 if (old->trailcount < 100)
 1529                         old->trailcount = 100;
 1530                 VectorAdd (move, vec, move);
 1531         }
 1532 }
 1533 
 1534 void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
 1535 {
 1536         float           d;
 1537 
 1538         // this rotate and negat guarantees a vector
 1539         // not colinear with the original
 1540         right[1] = -forward[0];
 1541         right[2] = forward[1];
 1542         right[0] = forward[2];
 1543 
 1544         d = DotProduct (right, forward);
 1545         VectorMA (right, -d, forward, right);
 1546         VectorNormalize (right);
 1547         CrossProduct (right, forward, up);
 1548 }
 1549 
 1550 /*
 1551 ===============
 1552 CL_RocketTrail
 1553 
 1554 ===============
 1555 */
 1556 void CL_RocketTrail (vec3_t start, vec3_t end, centity_t *old)
 1557 {
 1558         vec3_t          move;
 1559         vec3_t          vec;
 1560         float           len;
 1561         int                     j;
 1562         cparticle_t     *p;
 1563         float           dec;
 1564 
 1565         // smoke
 1566         CL_DiminishingTrail (start, end, old, EF_ROCKET);
 1567 
 1568         // fire
 1569         VectorCopy (start, move);
 1570         VectorSubtract (end, start, vec);
 1571         len = VectorNormalize (vec);
 1572 
 1573         dec = 1;
 1574         VectorScale (vec, dec, vec);
 1575 
 1576         while (len > 0)
 1577         {
 1578                 len -= dec;
 1579 
 1580                 if (!free_particles)
 1581                         return;
 1582 
 1583                 if ( (rand()&7) == 0)
 1584                 {
 1585                         p = free_particles;
 1586                         free_particles = p->next;
 1587                         p->next = active_particles;
 1588                         active_particles = p;
 1589                         
 1590                         VectorClear (p->accel);
 1591                         p->time = cl.time;
 1592 
 1593                         p->alpha = 1.0;
 1594                         p->alphavel = -1.0 / (1+frand()*0.2);
 1595                         p->color = 0xdc + (rand()&3);
 1596                         for (j=0 ; j<3 ; j++)
 1597                         {
 1598                                 p->org[j] = move[j] + crand()*5;
 1599                                 p->vel[j] = crand()*20;
 1600                         }
 1601                         p->accel[2] = -PARTICLE_GRAVITY;
 1602                 }
 1603                 VectorAdd (move, vec, move);
 1604         }
 1605 }
 1606 
 1607 /*
 1608 ===============
 1609 CL_RailTrail
 1610 
 1611 ===============
 1612 */
 1613 void CL_RailTrail (vec3_t start, vec3_t end)
 1614 {
 1615         vec3_t          move;
 1616         vec3_t          vec;
 1617         float           len;
 1618         int                     j;
 1619         cparticle_t     *p;
 1620         float           dec;
 1621         vec3_t          right, up;
 1622         int                     i;
 1623         float           d, c, s;
 1624         vec3_t          dir;
 1625         byte            clr = 0x74;
 1626 
 1627         VectorCopy (start, move);
 1628         VectorSubtract (end, start, vec);
 1629         len = VectorNormalize (vec);
 1630 
 1631         MakeNormalVectors (vec, right, up);
 1632 
 1633         for (i=0 ; i<len ; i++)
 1634         {
 1635                 if (!free_particles)
 1636                         return;
 1637 
 1638                 p = free_particles;
 1639                 free_particles = p->next;
 1640                 p->next = active_particles;
 1641                 active_particles = p;
 1642                 
 1643                 p->time = cl.time;
 1644                 VectorClear (p->accel);
 1645 
 1646                 d = i * 0.1;
 1647                 c = cos(d);
 1648                 s = sin(d);
 1649 
 1650                 VectorScale (right, c, dir);
 1651                 VectorMA (dir, s, up, dir);
 1652 
 1653                 p->alpha = 1.0;
 1654                 p->alphavel = -1.0 / (1+frand()*0.2);
 1655                 p->color = clr + (rand()&7);
 1656                 for (j=0 ; j<3 ; j++)
 1657                 {
 1658                         p->org[j] = move[j] + dir[j]*3;
 1659                         p->vel[j] = dir[j]*6;
 1660                 }
 1661 
 1662                 VectorAdd (move, vec, move);
 1663         }
 1664 
 1665         dec = 0.75;
 1666         VectorScale (vec, dec, vec);
 1667         VectorCopy (start, move);
 1668 
 1669         while (len > 0)
 1670         {
 1671                 len -= dec;
 1672 
 1673                 if (!free_particles)
 1674                         return;
 1675                 p = free_particles;
 1676                 free_particles = p->next;
 1677                 p->next = active_particles;
 1678                 active_particles = p;
 1679 
 1680                 p->time = cl.time;
 1681                 VectorClear (p->accel);
 1682 
 1683                 p->alpha = 1.0;
 1684                 p->alphavel = -1.0 / (0.6+frand()*0.2);
 1685                 p->color = 0x0 + rand()&15;
 1686 
 1687                 for (j=0 ; j<3 ; j++)
 1688                 {
 1689                         p->org[j] = move[j] + crand()*3;
 1690                         p->vel[j] = crand()*3;
 1691                         p->accel[j] = 0;
 1692                 }
 1693 
 1694                 VectorAdd (move, vec, move);
 1695         }
 1696 }
 1697 
 1698 // RAFAEL
 1699 /*
 1700 ===============
 1701 CL_IonripperTrail
 1702 ===============
 1703 */
 1704 void CL_IonripperTrail (vec3_t start, vec3_t ent)
 1705 {
 1706         vec3_t  move;
 1707         vec3_t  vec;
 1708         float   len;
 1709         int             j;
 1710         cparticle_t *p;
 1711         int             dec;
 1712         int     left = 0;
 1713 
 1714         VectorCopy (start, move);
 1715         VectorSubtract (ent, start, vec);
 1716         len = VectorNormalize (vec);
 1717 
 1718         dec = 5;
 1719         VectorScale (vec, 5, vec);
 1720 
 1721         while (len > 0)
 1722         {
 1723                 len -= dec;
 1724 
 1725                 if (!free_particles)
 1726                         return;
 1727                 p = free_particles;
 1728                 free_particles = p->next;
 1729                 p->next = active_particles;
 1730                 active_particles = p;
 1731                 VectorClear (p->accel);
 1732 
 1733                 p->time = cl.time;
 1734                 p->alpha = 0.5;
 1735                 p->alphavel = -1.0 / (0.3 + frand() * 0.2);
 1736                 p->color = 0xe4 + (rand()&3);
 1737 
 1738                 for (j=0; j<3; j++)
 1739                 {
 1740                         p->org[j] = move[j];
 1741                         p->accel[j] = 0;
 1742                 }
 1743                 if (left)
 1744                 {
 1745                         left = 0;
 1746                         p->vel[0] = 10;
 1747                 }
 1748                 else 
 1749                 {
 1750                         left = 1;
 1751                         p->vel[0] = -10;
 1752                 }
 1753 
 1754                 p->vel[1] = 0;
 1755                 p->vel[2] = 0;
 1756 
 1757                 VectorAdd (move, vec, move);
 1758         }
 1759 }
 1760 
 1761 
 1762 /*
 1763 ===============
 1764 CL_BubbleTrail
 1765 
 1766 ===============
 1767 */
 1768 void CL_BubbleTrail (vec3_t start, vec3_t end)
 1769 {
 1770         vec3_t          move;
 1771         vec3_t          vec;
 1772         float           len;
 1773         int                     i, j;
 1774         cparticle_t     *p;
 1775         float           dec;
 1776 
 1777         VectorCopy (start, move);
 1778         VectorSubtract (end, start, vec);
 1779         len = VectorNormalize (vec);
 1780 
 1781         dec = 32;
 1782         VectorScale (vec, dec, vec);
 1783 
 1784         for (i=0 ; i<len ; i+=dec)
 1785         {
 1786                 if (!free_particles)
 1787                         return;
 1788 
 1789                 p = free_particles;
 1790                 free_particles = p->next;
 1791                 p->next = active_particles;
 1792                 active_particles = p;
 1793 
 1794                 VectorClear (p->accel);
 1795                 p->time = cl.time;
 1796 
 1797                 p->alpha = 1.0;
 1798                 p->alphavel = -1.0 / (1+frand()*0.2);
 1799                 p->color = 4 + (rand()&7);
 1800                 for (j=0 ; j<3 ; j++)
 1801                 {
 1802                         p->org[j] = move[j] + crand()*2;
 1803                         p->vel[j] = crand()*5;
 1804                 }
 1805                 p->vel[2] += 6;
 1806 
 1807                 VectorAdd (move, vec, move);
 1808         }
 1809 }
 1810 
 1811 
 1812 /*
 1813 ===============
 1814 CL_FlyParticles
 1815 ===============
 1816 */
 1817 
 1818 #define BEAMLENGTH                      16
 1819 void CL_FlyParticles (vec3_t origin, int count)
 1820 {
 1821         int                     i;
 1822         cparticle_t     *p;
 1823         float           angle;
 1824         float           sr, sp, sy, cr, cp, cy;
 1825         vec3_t          forward;
 1826         float           dist = 64;
 1827         float           ltime;
 1828 
 1829 
 1830         if (count > NUMVERTEXNORMALS)
 1831                 count = NUMVERTEXNORMALS;
 1832 
 1833         if (!avelocities[0][0])
 1834         {
 1835                 for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
 1836                         avelocities[0][i] = (rand()&255) * 0.01;
 1837         }
 1838 
 1839 
 1840         ltime = (float)cl.time / 1000.0;
 1841         for (i=0 ; i<count ; i+=2)
 1842         {
 1843                 angle = ltime * avelocities[i][0];
 1844                 sy = sin(angle);
 1845                 cy = cos(angle);
 1846                 angle = ltime * avelocities[i][1];
 1847                 sp = sin(angle);
 1848                 cp = cos(angle);
 1849                 angle = ltime * avelocities[i][2];
 1850                 sr = sin(angle);
 1851                 cr = cos(angle);
 1852         
 1853                 forward[0] = cp*cy;
 1854                 forward[1] = cp*sy;
 1855                 forward[2] = -sp;
 1856 
 1857                 if (!free_particles)
 1858                         return;
 1859                 p = free_particles;
 1860                 free_particles = p->next;
 1861                 p->next = active_particles;
 1862                 active_particles = p;
 1863 
 1864                 p->time = cl.time;
 1865 
 1866                 dist = sin(ltime + i)*64;
 1867                 p->org[0] = origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH;
 1868                 p->org[1] = origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH;
 1869                 p->org[2] = origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH;
 1870 
 1871                 VectorClear (p->vel);
 1872                 VectorClear (p->accel);
 1873 
 1874                 p->color = 0;
 1875                 p->colorvel = 0;
 1876 
 1877                 p->alpha = 1;
 1878                 p->alphavel = -100;
 1879         }
 1880 }
 1881 
 1882 void CL_FlyEffect (centity_t *ent, vec3_t origin)
 1883 {
 1884         int             n;
 1885         int             count;
 1886         int             starttime;
 1887 
 1888         if (ent->fly_stoptime < cl.time)
 1889         {
 1890                 starttime = cl.time;
 1891                 ent->fly_stoptime = cl.time + 60000;
 1892         }
 1893         else
 1894         {
 1895                 starttime = ent->fly_stoptime - 60000;
 1896         }
 1897 
 1898         n = cl.time - starttime;
 1899         if (n < 20000)
 1900                 count = n * 162 / 20000.0;
 1901         else
 1902         {
 1903                 n = ent->fly_stoptime - cl.time;
 1904                 if (n < 20000)
 1905                         count = n * 162 / 20000.0;
 1906                 else
 1907                         count = 162;
 1908         }
 1909 
 1910         CL_FlyParticles (origin, count);
 1911 }
 1912 
 1913 
 1914 /*
 1915 ===============
 1916 CL_BfgParticles
 1917 ===============
 1918 */
 1919 
 1920 #define BEAMLENGTH                      16
 1921 void CL_BfgParticles (entity_t *ent)
 1922 {
 1923         int                     i;
 1924         cparticle_t     *p;
 1925         float           angle;
 1926         float           sr, sp, sy, cr, cp, cy;
 1927         vec3_t          forward;
 1928         float           dist = 64;
 1929         vec3_t          v;
 1930         float           ltime;
 1931         
 1932         if (!avelocities[0][0])
 1933         {
 1934                 for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
 1935                         avelocities[0][i] = (rand()&255) * 0.01;
 1936         }
 1937 
 1938 
 1939         ltime = (float)cl.time / 1000.0;
 1940         for (i=0 ; i<NUMVERTEXNORMALS ; i++)
 1941         {
 1942                 angle = ltime * avelocities[i][0];
 1943                 sy = sin(angle);
 1944                 cy = cos(angle);
 1945                 angle = ltime * avelocities[i][1];
 1946                 sp = sin(angle);
 1947                 cp = cos(angle);
 1948                 angle = ltime * avelocities[i][2];
 1949                 sr = sin(angle);
 1950                 cr = cos(angle);
 1951         
 1952                 forward[0] = cp*cy;
 1953                 forward[1] = cp*sy;
 1954                 forward[2] = -sp;
 1955 
 1956                 if (!free_particles)
 1957                         return;
 1958                 p = free_particles;
 1959                 free_particles = p->next;
 1960                 p->next = active_particles;
 1961                 active_particles = p;
 1962 
 1963                 p->time = cl.time;
 1964 
 1965                 dist = sin(ltime + i)*64;
 1966                 p->org[0] = ent->origin[0] + bytedirs[i][0]*dist + forward[0]*BEAMLENGTH;
 1967                 p->org[1] = ent->origin[1] + bytedirs[i][1]*dist + forward[1]*BEAMLENGTH;
 1968                 p->org[2] = ent->origin[2] + bytedirs[i][2]*dist + forward[2]*BEAMLENGTH;
 1969 
 1970                 VectorClear (p->vel);
 1971                 VectorClear (p->accel);
 1972 
 1973                 VectorSubtract (p->org, ent->origin, v);
 1974                 dist = VectorLength(v) / 90.0;
 1975                 p->color = floor (0xd0 + dist * 7);
 1976                 p->colorvel = 0;
 1977 
 1978                 p->alpha = 1.0 - dist;
 1979                 p->alphavel = -100;
 1980         }
 1981 }
 1982 
 1983 
 1984 /*
 1985 ===============
 1986 CL_TrapParticles
 1987 ===============
 1988 */
 1989 // RAFAEL
 1990 void CL_TrapParticles (entity_t *ent)
 1991 {
 1992         vec3_t          move;
 1993         vec3_t          vec;
 1994         vec3_t          start, end;
 1995         float           len;
 1996         int                     j;
 1997         cparticle_t     *p;
 1998         int                     dec;
 1999 
 2000         ent->origin[2]-=14;
 2001         VectorCopy (ent->origin, start);
 2002         VectorCopy (ent->origin, end);
 2003         end[2]+=64;
 2004 
 2005         VectorCopy (start, move);
 2006         VectorSubtract (end, start, vec);
 2007         len = VectorNormalize (vec);
 2008 
 2009         dec = 5;
 2010         VectorScale (vec, 5, vec);
 2011 
 2012         // FIXME: this is a really silly way to have a loop
 2013         while (len > 0)
 2014         {
 2015                 len -= dec;
 2016 
 2017                 if (!free_particles)
 2018                         return;
 2019                 p = free_particles;
 2020                 free_particles = p->next;
 2021                 p->next = active_particles;
 2022                 active_particles = p;
 2023                 VectorClear (p->accel);
 2024                 
 2025                 p->time = cl.time;
 2026 
 2027                 p->alpha = 1.0;
 2028                 p->alphavel = -1.0 / (0.3+frand()*0.2);
 2029                 p->color = 0xe0;
 2030                 for (j=0 ; j<3 ; j++)
 2031                 {
 2032                         p->org[j] = move[j] + crand();
 2033                         p->vel[j] = crand()*15;
 2034                         p->accel[j] = 0;
 2035                 }
 2036                 p->accel[2] = PARTICLE_GRAVITY;
 2037 
 2038                 VectorAdd (move, vec, move);
 2039         }
 2040 
 2041         {
 2042 
 2043         
 2044         int                     i, j, k;
 2045         cparticle_t     *p;
 2046         float           vel;
 2047         vec3_t          dir;
 2048         vec3_t          org;
 2049 
 2050         
 2051         ent->origin[2]+=14;
 2052         VectorCopy (ent->origin, org);
 2053 
 2054 
 2055         for (i=-2 ; i<=2 ; i+=4)
 2056                 for (j=-2 ; j<=2 ; j+=4)
 2057                         for (k=-2 ; k<=4 ; k+=4)
 2058                         {
 2059                                 if (!free_particles)
 2060                                         return;
 2061                                 p = free_particles;
 2062                                 free_particles = p->next;
 2063                                 p->next = active_particles;
 2064                                 active_particles = p;
 2065 
 2066                                 p->time = cl.time;
 2067                                 p->color = 0xe0 + (rand()&3);
 2068 
 2069                                 p->alpha = 1.0;
 2070                                 p->alphavel = -1.0 / (0.3 + (rand()&7) * 0.02);
 2071                                 
 2072                                 p->org[0] = org[0] + i + ((rand()&23) * crand());
 2073                                 p->org[1] = org[1] + j + ((rand()&23) * crand());
 2074                                 p->org[2] = org[2] + k + ((rand()&23) * crand());
 2075         
 2076                                 dir[0] = j * 8;
 2077                                 dir[1] = i * 8;
 2078                                 dir[2] = k * 8;
 2079         
 2080                                 VectorNormalize (dir);                                          
 2081                                 vel = 50 + rand()&63;
 2082                                 VectorScale (dir, vel, p->vel);
 2083 
 2084                                 p->accel[0] = p->accel[1] = 0;
 2085                                 p->accel[2] = -PARTICLE_GRAVITY;
 2086                         }
 2087         }
 2088 }
 2089 
 2090 
 2091 /*
 2092 ===============
 2093 CL_BFGExplosionParticles
 2094 ===============
 2095 */
 2096 //FIXME combined with CL_ExplosionParticles
 2097 void CL_BFGExplosionParticles (vec3_t org)
 2098 {
 2099         int                     i, j;
 2100         cparticle_t     *p;
 2101 
 2102         for (i=0 ; i<256 ; i++)
 2103         {
 2104                 if (!free_particles)
 2105                         return;
 2106                 p = free_particles;
 2107                 free_particles = p->next;
 2108                 p->next = active_particles;
 2109                 active_particles = p;
 2110 
 2111                 p->time = cl.time;
 2112                 p->color = 0xd0 + (rand()&7);
 2113 
 2114                 for (j=0 ; j<3 ; j++)
 2115                 {
 2116                         p->org[j] = org[j] + ((rand()%32)-16);
 2117                         p->vel[j] = (rand()%384)-192;
 2118                 }
 2119 
 2120                 p->accel[0] = p->accel[1] = 0;
 2121                 p->accel[2] = -PARTICLE_GRAVITY;
 2122                 p->alpha = 1.0;
 2123 
 2124                 p->alphavel = -0.8 / (0.5 + frand()*0.3);
 2125         }
 2126 }
 2127 
 2128 
 2129 /*
 2130 ===============
 2131 CL_TeleportParticles
 2132 
 2133 ===============
 2134 */
 2135 void CL_TeleportParticles (vec3_t org)
 2136 {
 2137         int                     i, j, k;
 2138         cparticle_t     *p;
 2139         float           vel;
 2140         vec3_t          dir;
 2141 
 2142         for (i=-16 ; i<=16 ; i+=4)
 2143                 for (j=-16 ; j<=16 ; j+=4)
 2144                         for (k=-16 ; k<=32 ; k+=4)
 2145                         {
 2146                                 if (!free_particles)
 2147                                         return;
 2148                                 p = free_particles;
 2149                                 free_particles = p->next;
 2150                                 p->next = active_particles;
 2151                                 active_particles = p;
 2152 
 2153                                 p->time = cl.time;
 2154                                 p->color = 7 + (rand()&7);
 2155 
 2156                                 p->alpha = 1.0;
 2157                                 p->alphavel = -1.0 / (0.3 + (rand()&7) * 0.02);
 2158                                 
 2159                                 p->org[0] = org[0] + i + (rand()&3);
 2160                                 p->org[1] = org[1] + j + (rand()&3);
 2161                                 p->org[2] = org[2] + k + (rand()&3);
 2162         
 2163                                 dir[0] = j*8;
 2164                                 dir[1] = i*8;
 2165                                 dir[2] = k*8;
 2166         
 2167                                 VectorNormalize (dir);                                          
 2168                                 vel = 50 + (rand()&63);
 2169                                 VectorScale (dir, vel, p->vel);
 2170 
 2171                                 p->accel[0] = p->accel[1] = 0;
 2172                                 p->accel[2] = -PARTICLE_GRAVITY;
 2173                         }
 2174 }
 2175 
 2176 
 2177 /*
 2178 ===============
 2179 CL_AddParticles
 2180 ===============
 2181 */
 2182 void CL_AddParticles (void)
 2183 {
 2184         cparticle_t             *p, *next;
 2185         float                   alpha;
 2186         float                   time, time2;
 2187         vec3_t                  org;
 2188         int                             color;
 2189         cparticle_t             *active, *tail;
 2190 
 2191         active = NULL;
 2192         tail = NULL;
 2193 
 2194         for (p=active_particles ; p ; p=next)
 2195         {
 2196                 next = p->next;
 2197 
 2198                 // PMM - added INSTANT_PARTICLE handling for heat beam
 2199                 if (p->alphavel != INSTANT_PARTICLE)
 2200                 {
 2201                         time = (cl.time - p->time)*0.001;
 2202                         alpha = p->alpha + time*p->alphavel;
 2203                         if (alpha <= 0)
 2204                         {       // faded out
 2205                                 p->next = free_particles;
 2206                                 free_particles = p;
 2207                                 continue;
 2208                         }
 2209                 }
 2210                 else
 2211                 {
 2212                         alpha = p->alpha;
 2213                 }
 2214 
 2215                 p->next = NULL;
 2216                 if (!tail)
 2217                         active = tail = p;
 2218                 else
 2219                 {
 2220                         tail->next = p;
 2221                         tail = p;
 2222                 }
 2223 
 2224                 if (alpha > 1.0)
 2225                         alpha = 1;
 2226                 color = p->color;
 2227 
 2228                 time2 = time*time;
 2229 
 2230                 org[0] = p->org[0] + p->vel[0]*time + p->accel[0]*time2;
 2231                 org[1] = p->org[1] + p->vel[1]*time + p->accel[1]*time2;
 2232                 org[2] = p->org[2] + p->vel[2]*time + p->accel[2]*time2;
 2233 
 2234                 V_AddParticle (org, color, alpha);
 2235                 // PMM
 2236                 if (p->alphavel == INSTANT_PARTICLE)
 2237                 {
 2238                         p->alphavel = 0.0;
 2239                         p->alpha = 0.0;
 2240                 }
 2241         }
 2242 
 2243         active_particles = active;
 2244 }
 2245 
 2246 
 2247 /*
 2248 ==============
 2249 CL_EntityEvent
 2250 
 2251 An entity has just been parsed that has an event value
 2252 
 2253 the female events are there for backwards compatability
 2254 ==============
 2255 */
 2256 extern struct sfx_s     *cl_sfx_footsteps[4];
 2257 
 2258 void CL_EntityEvent (entity_state_t *ent)
 2259 {
 2260         switch (ent->event)
 2261         {
 2262         case EV_ITEM_RESPAWN:
 2263                 S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("items/respawn1.wav"), 1, ATTN_IDLE, 0);
 2264                 CL_ItemRespawnParticles (ent->origin);
 2265                 break;
 2266         case EV_PLAYER_TELEPORT:
 2267                 S_StartSound (NULL, ent->number, CHAN_WEAPON, S_RegisterSound("misc/tele1.wav"), 1, ATTN_IDLE, 0);
 2268                 CL_TeleportParticles (ent->origin);
 2269                 break;
 2270         case EV_FOOTSTEP:
 2271                 if (cl_footsteps->value)
 2272                         S_StartSound (NULL, ent->number, CHAN_BODY, cl_sfx_footsteps[rand()&3], 1, ATTN_NORM, 0);
 2273                 break;
 2274         case EV_FALLSHORT:
 2275                 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("player/land1.wav"), 1, ATTN_NORM, 0);
 2276                 break;
 2277         case EV_FALL:
 2278                 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall2.wav"), 1, ATTN_NORM, 0);
 2279                 break;
 2280         case EV_FALLFAR:
 2281                 S_StartSound (NULL, ent->number, CHAN_AUTO, S_RegisterSound ("*fall1.wav"), 1, ATTN_NORM, 0);
 2282                 break;
 2283         }
 2284 }
 2285 
 2286 
 2287 /*
 2288 ==============
 2289 CL_ClearEffects
 2290 
 2291 ==============
 2292 */
 2293 void CL_ClearEffects (void)
 2294 {
 2295         CL_ClearParticles ();
 2296         CL_ClearDlights ();
 2297         CL_ClearLightStyles ();
 2298 }
 2299