home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / client / cl_tent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-21  |  9.3 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.