home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 113 / EnigmaAmiga113CD.iso / software / sviluppo / quakeworld_src / client / cl_tent.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-17  |  9.9 KB  |  460 lines

  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.  
  25. #define MAX_BEAMS 8
  26. typedef struct
  27. {
  28.   int   entity;
  29.   struct model_s  *model;
  30.   float endtime;
  31.   vec3_t  start, end;
  32. } beam_t;
  33.  
  34. beam_t    cl_beams[MAX_BEAMS];
  35.  
  36. #define MAX_EXPLOSIONS  8
  37. typedef struct
  38. {
  39.   vec3_t  origin;
  40.   float start;
  41.   model_t *model;
  42. } explosion_t;
  43.  
  44. explosion_t cl_explosions[MAX_EXPLOSIONS];
  45.  
  46.  
  47. sfx_t     *cl_sfx_wizhit;
  48. sfx_t     *cl_sfx_knighthit;
  49. sfx_t     *cl_sfx_tink1;
  50. sfx_t     *cl_sfx_ric1;
  51. sfx_t     *cl_sfx_ric2;
  52. sfx_t     *cl_sfx_ric3;
  53. sfx_t     *cl_sfx_r_exp3;
  54.  
  55. /*
  56. =================
  57. CL_ParseTEnts
  58. =================
  59. */
  60. void CL_InitTEnts (void)
  61. {
  62.   cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
  63.   cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
  64.   cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
  65.   cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
  66.   cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
  67.   cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
  68.   cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
  69. }
  70.  
  71. /*
  72. =================
  73. CL_ClearTEnts
  74. =================
  75. */
  76. void CL_ClearTEnts (void)
  77. {
  78.   memset (&cl_beams, 0, sizeof(cl_beams));
  79.   memset (&cl_explosions, 0, sizeof(cl_explosions));
  80. }
  81.  
  82. /*
  83. =================
  84. CL_AllocExplosion
  85. =================
  86. */
  87. explosion_t *CL_AllocExplosion (void)
  88. {
  89.   int   i;
  90.   float time;
  91.   int   index;
  92.   
  93.   for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  94.     if (!cl_explosions[i].model)
  95.       return &cl_explosions[i];
  96. // find the oldest explosion
  97.   time = cl.time;
  98.   index = 0;
  99.  
  100.   for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  101.     if (cl_explosions[i].start < time)
  102.     {
  103.       time = cl_explosions[i].start;
  104.       index = i;
  105.     }
  106.   return &cl_explosions[index];
  107. }
  108.  
  109. /*
  110. =================
  111. CL_ParseBeam
  112. =================
  113. */
  114. void CL_ParseBeam (model_t *m)
  115. {
  116.   int   ent;
  117.   vec3_t  start, end;
  118.   beam_t  *b;
  119.   int   i;
  120.   
  121.   ent = MSG_ReadShort ();
  122.   
  123.   start[0] = MSG_ReadCoord ();
  124.   start[1] = MSG_ReadCoord ();
  125.   start[2] = MSG_ReadCoord ();
  126.   
  127.   end[0] = MSG_ReadCoord ();
  128.   end[1] = MSG_ReadCoord ();
  129.   end[2] = MSG_ReadCoord ();
  130.  
  131. // override any beam with the same entity
  132.   for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  133.     if (b->entity == ent)
  134.     {
  135.       b->entity = ent;
  136.       b->model = m;
  137.       b->endtime = cl.time + 0.2;
  138.       VectorCopy (start, b->start);
  139.       VectorCopy (end, b->end);
  140.       return;
  141.     }
  142.  
  143. // find a free beam
  144.   for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  145.   {
  146.     if (!b->model || b->endtime < cl.time)
  147.     {
  148.       b->entity = ent;
  149.       b->model = m;
  150.       b->endtime = cl.time + 0.2;
  151.       VectorCopy (start, b->start);
  152.       VectorCopy (end, b->end);
  153.       return;
  154.     }
  155.   }
  156.   Con_Printf ("beam list overflow!\n"); 
  157. }
  158.  
  159. /*
  160. =================
  161. CL_ParseTEnt
  162. =================
  163. */
  164. void CL_ParseTEnt (void)
  165. {
  166.   int   type;
  167.   vec3_t  pos;
  168.   dlight_t  *dl;
  169.   int   rnd;
  170.   explosion_t *ex;
  171.   int   cnt;
  172.  
  173.   type = MSG_ReadByte ();
  174.   switch (type)
  175.   {
  176.   case TE_WIZSPIKE:     // spike hitting wall
  177.     pos[0] = MSG_ReadCoord ();
  178.     pos[1] = MSG_ReadCoord ();
  179.     pos[2] = MSG_ReadCoord ();
  180.     R_RunParticleEffect (pos, vec3_origin, 20, 30);
  181.     S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
  182.     break;
  183.     
  184.   case TE_KNIGHTSPIKE:      // spike hitting wall
  185.     pos[0] = MSG_ReadCoord ();
  186.     pos[1] = MSG_ReadCoord ();
  187.     pos[2] = MSG_ReadCoord ();
  188.     R_RunParticleEffect (pos, vec3_origin, 226, 20);
  189.     S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
  190.     break;
  191.     
  192.   case TE_SPIKE:      // spike hitting wall
  193.     pos[0] = MSG_ReadCoord ();
  194.     pos[1] = MSG_ReadCoord ();
  195.     pos[2] = MSG_ReadCoord ();
  196.     R_RunParticleEffect (pos, vec3_origin, 0, 10);
  197.  
  198.     if ( rand() % 5 )
  199.       S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
  200.     else
  201.     {
  202.       rnd = rand() & 3;
  203.       if (rnd == 1)
  204.         S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
  205.       else if (rnd == 2)
  206.         S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
  207.       else
  208.         S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
  209.     }
  210.     break;
  211.   case TE_SUPERSPIKE:     // super spike hitting wall
  212.     pos[0] = MSG_ReadCoord ();
  213.     pos[1] = MSG_ReadCoord ();
  214.     pos[2] = MSG_ReadCoord ();
  215.     R_RunParticleEffect (pos, vec3_origin, 0, 20);
  216.  
  217.     if ( rand() % 5 )
  218.       S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
  219.     else
  220.     {
  221.       rnd = rand() & 3;
  222.       if (rnd == 1)
  223.         S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
  224.       else if (rnd == 2)
  225.         S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
  226.       else
  227.         S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
  228.     }
  229.     break;
  230.     
  231.   case TE_EXPLOSION:      // rocket explosion
  232.   // particles
  233.     pos[0] = MSG_ReadCoord ();
  234.     pos[1] = MSG_ReadCoord ();
  235.     pos[2] = MSG_ReadCoord ();
  236.     R_ParticleExplosion (pos);
  237.     
  238.   // light
  239.     dl = CL_AllocDlight (0);
  240.     VectorCopy (pos, dl->origin);
  241.     dl->radius = 350;
  242.     dl->die = cl.time + 0.5;
  243.     dl->decay = 300;
  244.     dl->color[0] = 0.2;
  245.     dl->color[1] = 0.1;
  246.     dl->color[2] = 0.05;
  247.     dl->color[3] = 0.7;
  248.   
  249.   // sound
  250.     S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
  251.   
  252.   // sprite
  253.     ex = CL_AllocExplosion ();
  254.     VectorCopy (pos, ex->origin);
  255.     ex->start = cl.time;
  256.     ex->model = Mod_ForName ("progs/s_explod.spr", true);
  257.     break;
  258.     
  259.   case TE_TAREXPLOSION:     // tarbaby explosion
  260.     pos[0] = MSG_ReadCoord ();
  261.     pos[1] = MSG_ReadCoord ();
  262.     pos[2] = MSG_ReadCoord ();
  263.     R_BlobExplosion (pos);
  264.  
  265.     S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
  266.     break;
  267.  
  268.   case TE_LIGHTNING1:       // lightning bolts
  269.     CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
  270.     break;
  271.   
  272.   case TE_LIGHTNING2:       // lightning bolts
  273.     CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
  274.     break;
  275.   
  276.   case TE_LIGHTNING3:       // lightning bolts
  277.     CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
  278.     break;
  279.   
  280.   case TE_LAVASPLASH: 
  281.     pos[0] = MSG_ReadCoord ();
  282.     pos[1] = MSG_ReadCoord ();
  283.     pos[2] = MSG_ReadCoord ();
  284.     R_LavaSplash (pos);
  285.     break;
  286.   
  287.   case TE_TELEPORT:
  288.     pos[0] = MSG_ReadCoord ();
  289.     pos[1] = MSG_ReadCoord ();
  290.     pos[2] = MSG_ReadCoord ();
  291.     R_TeleportSplash (pos);
  292.     break;
  293.  
  294.   case TE_GUNSHOT:      // bullet hitting wall
  295.     cnt = MSG_ReadByte ();
  296.     pos[0] = MSG_ReadCoord ();
  297.     pos[1] = MSG_ReadCoord ();
  298.     pos[2] = MSG_ReadCoord ();
  299.     R_RunParticleEffect (pos, vec3_origin, 0, 20*cnt);
  300.     break;
  301.     
  302.   case TE_BLOOD:        // bullets hitting body
  303.     cnt = MSG_ReadByte ();
  304.     pos[0] = MSG_ReadCoord ();
  305.     pos[1] = MSG_ReadCoord ();
  306.     pos[2] = MSG_ReadCoord ();
  307.     R_RunParticleEffect (pos, vec3_origin, 73, 20*cnt);
  308.     break;
  309.  
  310.   case TE_LIGHTNINGBLOOD:   // lightning hitting body
  311.     pos[0] = MSG_ReadCoord ();
  312.     pos[1] = MSG_ReadCoord ();
  313.     pos[2] = MSG_ReadCoord ();
  314.     R_RunParticleEffect (pos, vec3_origin, 225, 50);
  315.     break;
  316.  
  317.   default:
  318.     Sys_Error ("CL_ParseTEnt: bad type");
  319.   }
  320. }
  321.  
  322.  
  323. /*
  324. =================
  325. CL_NewTempEntity
  326. =================
  327. */
  328. entity_t *CL_NewTempEntity (void)
  329. {
  330.   entity_t  *ent;
  331.  
  332.   if (cl_numvisedicts == MAX_VISEDICTS)
  333.     return NULL;
  334.   ent = &cl_visedicts[cl_numvisedicts];
  335.   cl_numvisedicts++;
  336.   ent->keynum = 0;
  337.   
  338.   memset (ent, 0, sizeof(*ent));
  339.  
  340.   ent->colormap = vid.colormap;
  341.   return ent;
  342. }
  343.  
  344.  
  345. /*
  346. =================
  347. CL_UpdateBeams
  348. =================
  349. */
  350. void CL_UpdateBeams (void)
  351. {
  352.   int     i;
  353.   beam_t    *b;
  354.   vec3_t    dist, org;
  355.   float   d;
  356.   entity_t  *ent;
  357.   float   yaw, pitch;
  358.   float   forward;
  359.  
  360. // update lightning
  361.   for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  362.   {
  363.     if (!b->model || b->endtime < cl.time)
  364.       continue;
  365.  
  366.   // if coming from the player, update the start position
  367.     if (b->entity == cl.playernum+1)  // entity 0 is the world
  368.     {
  369.       VectorCopy (cl.simorg, b->start);
  370. //      b->start[2] -= 22;  // adjust for view height
  371.     }
  372.  
  373.   // calculate pitch and yaw
  374.     VectorSubtract (b->end, b->start, dist);
  375.  
  376.     if (dist[1] == 0 && dist[0] == 0)
  377.     {
  378.       yaw = 0;
  379.       if (dist[2] > 0)
  380.         pitch = 90;
  381.       else
  382.         pitch = 270;
  383.     }
  384.     else
  385.     {
  386.       yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
  387.       if (yaw < 0)
  388.         yaw += 360;
  389.   
  390.       forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
  391.       pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
  392.       if (pitch < 0)
  393.         pitch += 360;
  394.     }
  395.  
  396.   // add new entities for the lightning
  397.     VectorCopy (b->start, org);
  398.     d = VectorNormalize(dist);
  399.     while (d > 0)
  400.     {
  401.       ent = CL_NewTempEntity ();
  402.       if (!ent)
  403.         return;
  404.       VectorCopy (org, ent->origin);
  405.       ent->model = b->model;
  406.       ent->angles[0] = pitch;
  407.       ent->angles[1] = yaw;
  408.       ent->angles[2] = rand()%360;
  409.  
  410.       for (i=0 ; i<3 ; i++)
  411.         org[i] += dist[i]*30;
  412.       d -= 30;
  413.     }
  414.   }
  415.   
  416. }
  417.  
  418. /*
  419. =================
  420. CL_UpdateExplosions
  421. =================
  422. */
  423. void CL_UpdateExplosions (void)
  424. {
  425.   int     i;
  426.   int     f;
  427.   explosion_t *ex;
  428.   entity_t  *ent;
  429.  
  430.   for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++)
  431.   {
  432.     if (!ex->model)
  433.       continue;
  434.     f = 10*(cl.time - ex->start);
  435.     if (f >= ex->model->numframes)
  436.     {
  437.       ex->model = NULL;
  438.       continue;
  439.     }
  440.  
  441.     ent = CL_NewTempEntity ();
  442.     if (!ent)
  443.       return;
  444.     VectorCopy (ex->origin, ent->origin);
  445.     ent->model = ex->model;
  446.     ent->frame = f;
  447.   }
  448. }
  449.  
  450. /*
  451. =================
  452. CL_UpdateTEnts
  453. =================
  454. */
  455. void CL_UpdateTEnts (void)
  456. {
  457.   CL_UpdateBeams ();
  458.   CL_UpdateExplosions ();
  459. }
  460.