Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 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_tent.c -- client side temporary entities
  21.  
  22. #include "quakedef.h"
  23.  
  24. int                     num_temp_entities;
  25. entity_t        cl_temp_entities[MAX_TEMP_ENTITIES];
  26. beam_t          cl_beams[MAX_BEAMS];
  27.  
  28. sfx_t                   *cl_sfx_wizhit;
  29. sfx_t                   *cl_sfx_knighthit;
  30. sfx_t                   *cl_sfx_tink1;
  31. sfx_t                   *cl_sfx_ric1;
  32. sfx_t                   *cl_sfx_ric2;
  33. sfx_t                   *cl_sfx_ric3;
  34. sfx_t                   *cl_sfx_r_exp3;
  35. #ifdef QUAKE2
  36. sfx_t                   *cl_sfx_imp;
  37. sfx_t                   *cl_sfx_rail;
  38. #endif
  39.  
  40. /*
  41. =================
  42. CL_ParseTEnt
  43. =================
  44. */
  45. void CL_InitTEnts (void)
  46. {
  47.         cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
  48.         cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
  49.         cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
  50.         cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
  51.         cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
  52.         cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
  53.         cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
  54. #ifdef QUAKE2
  55.         cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav");
  56.         cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav");
  57. #endif
  58. }
  59.  
  60. /*
  61. =================
  62. CL_ParseBeam
  63. =================
  64. */
  65. void CL_ParseBeam (model_t *m)
  66. {
  67.         int             ent;
  68.         vec3_t  start, end;
  69.         beam_t  *b;
  70.         int             i;
  71.        
  72.         ent = MSG_ReadShort ();
  73.        
  74.         start[0] = MSG_ReadCoord ();
  75.         start[1] = MSG_ReadCoord ();
  76.         start[2] = MSG_ReadCoord ();
  77.        
  78.         end[0] = MSG_ReadCoord ();
  79.         end[1] = MSG_ReadCoord ();
  80.         end[2] = MSG_ReadCoord ();
  81.  
  82. // override any beam with the same entity
  83.         for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  84.                 if (b->entity == ent)
  85.                 {
  86.                         b->entity = ent;
  87.                         b->model = m;
  88.                         b->endtime = cl.time + 0.2;
  89.                         VectorCopy (start, b->start);
  90.                         VectorCopy (end, b->end);
  91.                         return;
  92.                 }
  93.  
  94. // find a free beam
  95.         for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  96.         {
  97.                 if (!b->model || b->endtime < cl.time)
  98.                 {
  99.                         b->entity = ent;
  100.                         b->model = m;
  101.                         b->endtime = cl.time + 0.2;
  102.                         VectorCopy (start, b->start);
  103.                         VectorCopy (end, b->end);
  104.                         return;
  105.                 }
  106.         }
  107.         Con_Printf ("beam list overflow!\n");  
  108. }
  109.  
  110. /*
  111. =================
  112. CL_ParseTEnt
  113. =================
  114. */
  115. void CL_ParseTEnt (void)
  116. {
  117.         int             type;
  118.         vec3_t  pos;
  119. #ifdef QUAKE2
  120.         vec3_t  endpos;
  121. #endif
  122.         dlight_t        *dl;
  123.         int             rnd;
  124.         int             colorStart, colorLength;
  125.  
  126.         type = MSG_ReadByte ();
  127.         switch (type)
  128.         {
  129.         case TE_WIZSPIKE:                       // spike hitting wall
  130.                 pos[0] = MSG_ReadCoord ();
  131.                 pos[1] = MSG_ReadCoord ();
  132.                 pos[2] = MSG_ReadCoord ();
  133.                 R_RunParticleEffect (pos, vec3_origin, 20, 30);
  134.                 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
  135.                 break;
  136.                
  137.         case TE_KNIGHTSPIKE:                    // spike hitting wall
  138.                 pos[0] = MSG_ReadCoord ();
  139.                 pos[1] = MSG_ReadCoord ();
  140.                 pos[2] = MSG_ReadCoord ();
  141.                 R_RunParticleEffect (pos, vec3_origin, 226, 20);
  142.                 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
  143.                 break;
  144.                
  145.         case TE_SPIKE:                  // spike hitting wall
  146.                 pos[0] = MSG_ReadCoord ();
  147.                 pos[1] = MSG_ReadCoord ();
  148.                 pos[2] = MSG_ReadCoord ();
  149. #ifdef GLTEST
  150.                 Test_Spawn (pos);
  151. #else
  152.                 R_RunParticleEffect (pos, vec3_origin, 0, 10);
  153. #endif
  154.                 if ( rand() % 5 )
  155.                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
  156.                 else
  157.                 {
  158.                         rnd = rand() & 3;
  159.                         if (rnd == 1)
  160.                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
  161.                         else if (rnd == 2)
  162.                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
  163.                         else
  164.                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
  165.                 }
  166.                 break;
  167.         case TE_SUPERSPIKE:                     // super spike hitting wall
  168.                 pos[0] = MSG_ReadCoord ();
  169.                 pos[1] = MSG_ReadCoord ();
  170.                 pos[2] = MSG_ReadCoord ();
  171.                 R_RunParticleEffect (pos, vec3_origin, 0, 20);
  172.  
  173.                 if ( rand() % 5 )
  174.                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
  175.                 else
  176.                 {
  177.                         rnd = rand() & 3;
  178.                         if (rnd == 1)
  179.                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
  180.                         else if (rnd == 2)
  181.                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
  182.                         else
  183.                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
  184.                 }
  185.                 break;
  186.                
  187.         case TE_GUNSHOT:                        // bullet hitting wall
  188.                 pos[0] = MSG_ReadCoord ();
  189.                 pos[1] = MSG_ReadCoord ();
  190.                 pos[2] = MSG_ReadCoord ();
  191.                 R_RunParticleEffect (pos, vec3_origin, 0, 20);
  192.                 break;
  193.                
  194.         case TE_EXPLOSION:                      // rocket explosion
  195.                 pos[0] = MSG_ReadCoord ();
  196.                 pos[1] = MSG_ReadCoord ();
  197.                 pos[2] = MSG_ReadCoord ();
  198.                 R_ParticleExplosion (pos);
  199.                 dl = CL_AllocDlight (0);
  200.                 VectorCopy (pos, dl->origin);
  201.                 dl->radius = 350;
  202.                 dl->die = cl.time + 0.5;
  203.                 dl->decay = 300;
  204.                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
  205.                 break;
  206.                
  207.         case TE_TAREXPLOSION:                   // tarbaby explosion
  208.                 pos[0] = MSG_ReadCoord ();
  209.                 pos[1] = MSG_ReadCoord ();
  210.                 pos[2] = MSG_ReadCoord ();
  211.                 R_BlobExplosion (pos);
  212.  
  213.                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
  214.                 break;
  215.  
  216.         case TE_LIGHTNING1:                             // lightning bolts
  217.                 CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
  218.                 break;
  219.        
  220.         case TE_LIGHTNING2:                             // lightning bolts
  221.                 CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
  222.                 break;
  223.        
  224.         case TE_LIGHTNING3:                             // lightning bolts
  225.                 CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
  226.                 break;
  227.        
  228. // PGM 01/21/97
  229.         case TE_BEAM:                           // grappling hook beam
  230.                 CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
  231.                 break;
  232. // PGM 01/21/97
  233.  
  234.         case TE_LAVASPLASH:    
  235.                 pos[0] = MSG_ReadCoord ();
  236.                 pos[1] = MSG_ReadCoord ();
  237.                 pos[2] = MSG_ReadCoord ();
  238.                 R_LavaSplash (pos);
  239.                 break;
  240.        
  241.         case TE_TELEPORT:
  242.                 pos[0] = MSG_ReadCoord ();
  243.                 pos[1] = MSG_ReadCoord ();
  244.                 pos[2] = MSG_ReadCoord ();
  245.                 R_TeleportSplash (pos);
  246.                 break;
  247.                
  248.         case TE_EXPLOSION2:                             // color mapped explosion
  249.                 pos[0] = MSG_ReadCoord ();
  250.                 pos[1] = MSG_ReadCoord ();
  251.                 pos[2] = MSG_ReadCoord ();
  252.                 colorStart = MSG_ReadByte ();
  253.                 colorLength = MSG_ReadByte ();
  254.                 R_ParticleExplosion2 (pos, colorStart, colorLength);
  255.                 dl = CL_AllocDlight (0);
  256.                 VectorCopy (pos, dl->origin);
  257.                 dl->radius = 350;
  258.                 dl->die = cl.time + 0.5;
  259.                 dl->decay = 300;
  260.                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
  261.                 break;
  262.                
  263. #ifdef QUAKE2
  264.         case TE_IMPLOSION:
  265.                 pos[0] = MSG_ReadCoord ();
  266.                 pos[1] = MSG_ReadCoord ();
  267.                 pos[2] = MSG_ReadCoord ();
  268.                 S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1);
  269.                 break;
  270.  
  271.         case TE_RAILTRAIL:
  272.                 pos[0] = MSG_ReadCoord ();
  273.                 pos[1] = MSG_ReadCoord ();
  274.                 pos[2] = MSG_ReadCoord ();
  275.                 endpos[0] = MSG_ReadCoord ();
  276.                 endpos[1] = MSG_ReadCoord ();
  277.                 endpos[2] = MSG_ReadCoord ();
  278.                 S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1);
  279.                 S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1);
  280.                 R_RocketTrail (pos, endpos, 0+128);
  281.                 R_ParticleExplosion (endpos);
  282.                 dl = CL_AllocDlight (-1);
  283.                 VectorCopy (endpos, dl->origin);
  284.                 dl->radius = 350;
  285.                 dl->die = cl.time + 0.5;
  286.                 dl->decay = 300;
  287.                 break;
  288. #endif
  289.  
  290.         default:
  291.                 Sys_Error ("CL_ParseTEnt: bad type");
  292.         }
  293. }
  294.  
  295.  
  296. /*
  297. =================
  298. CL_NewTempEntity
  299. =================
  300. */
  301. entity_t *CL_NewTempEntity (void)
  302. {
  303.         entity_t        *ent;
  304.  
  305.         if (cl_numvisedicts == MAX_VISEDICTS)
  306.                 return NULL;
  307.         if (num_temp_entities == MAX_TEMP_ENTITIES)
  308.                 return NULL;
  309.         ent = &cl_temp_entities[num_temp_entities];
  310.         memset (ent, 0, sizeof(*ent));
  311.         num_temp_entities++;
  312.         cl_visedicts[cl_numvisedicts] = ent;
  313.         cl_numvisedicts++;
  314.  
  315.         ent->colormap = vid.colormap;
  316.         return ent;
  317. }
  318.  
  319.  
  320. /*
  321. =================
  322. CL_UpdateTEnts
  323. =================
  324. */
  325. void CL_UpdateTEnts (void)
  326. {
  327.         int                     i;
  328.         beam_t          *b;
  329.         vec3_t          dist, org;
  330.         float           d;
  331.         entity_t        *ent;
  332.         float           yaw, pitch;
  333.         float           forward;
  334.  
  335.         num_temp_entities = 0;
  336.  
  337. // update lightning
  338.         for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  339.         {
  340.                 if (!b->model || b->endtime < cl.time)
  341.                         continue;
  342.  
  343.         // if coming from the player, update the start position
  344.                 if (b->entity == cl.viewentity)
  345.                 {
  346.                         VectorCopy (cl_entities[cl.viewentity].origin, b->start);
  347.                 }
  348.  
  349.         // calculate pitch and yaw
  350.                 VectorSubtract (b->end, b->start, dist);
  351.  
  352.                 if (dist[1] == 0 && dist[0] == 0)
  353.                 {
  354.                         yaw = 0;
  355.                         if (dist[2] > 0)
  356.                                 pitch = 90;
  357.                         else
  358.                                 pitch = 270;
  359.                 }
  360.                 else
  361.                 {
  362.                         yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
  363.                         if (yaw < 0)
  364.                                 yaw += 360;
  365.        
  366.                         forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
  367.                         pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
  368.                         if (pitch < 0)
  369.                                 pitch += 360;
  370.                 }
  371.  
  372.         // add new entities for the lightning
  373.                 VectorCopy (b->start, org);
  374.                 d = VectorNormalize(dist);
  375.                 while (d > 0)
  376.                 {
  377.                         ent = CL_NewTempEntity ();
  378.                         if (!ent)
  379.                                 return;
  380.                         VectorCopy (org, ent->origin);
  381.                         ent->model = b->model;
  382.                         ent->angles[0] = pitch;
  383.                         ent->angles[1] = yaw;
  384.                         ent->angles[2] = rand()%360;
  385.  
  386.                         for (i=0 ; i<3 ; i++)
  387.                                 org[i] += dist[i]*30;
  388.                         d -= 30;
  389.                 }
  390.         }
  391.        
  392. }
  393.  
  394.  
  395.