cl_tent.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. // cl_tent.c -- client side temporary entities
  16. #include "quakedef.h"
  17. #define MAX_BEAMS 8
  18. typedef struct
  19. {
  20. int entity;
  21. struct model_s *model;
  22. float endtime;
  23. vec3_t start, end;
  24. } beam_t;
  25. beam_t cl_beams[MAX_BEAMS];
  26. #define MAX_EXPLOSIONS 8
  27. typedef struct
  28. {
  29. vec3_t origin;
  30. float start;
  31. model_t *model;
  32. } explosion_t;
  33. explosion_t cl_explosions[MAX_EXPLOSIONS];
  34. sfx_t *cl_sfx_wizhit;
  35. sfx_t *cl_sfx_knighthit;
  36. sfx_t *cl_sfx_tink1;
  37. sfx_t *cl_sfx_ric1;
  38. sfx_t *cl_sfx_ric2;
  39. sfx_t *cl_sfx_ric3;
  40. sfx_t *cl_sfx_r_exp3;
  41. /*
  42. =================
  43. CL_ParseTEnts
  44. =================
  45. */
  46. void CL_InitTEnts (void)
  47. {
  48. cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
  49. cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
  50. cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
  51. cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
  52. cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
  53. cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
  54. cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
  55. }
  56. /*
  57. =================
  58. CL_ClearTEnts
  59. =================
  60. */
  61. void CL_ClearTEnts (void)
  62. {
  63. memset (&cl_beams, 0, sizeof(cl_beams));
  64. memset (&cl_explosions, 0, sizeof(cl_explosions));
  65. }
  66. /*
  67. =================
  68. CL_AllocExplosion
  69. =================
  70. */
  71. explosion_t *CL_AllocExplosion (void)
  72. {
  73. int i;
  74. float time;
  75. int index;
  76. for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  77. if (!cl_explosions[i].model)
  78. return &cl_explosions[i];
  79. // find the oldest explosion
  80. time = cl.time;
  81. index = 0;
  82. for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  83. if (cl_explosions[i].start < time)
  84. {
  85. time = cl_explosions[i].start;
  86. index = i;
  87. }
  88. return &cl_explosions[index];
  89. }
  90. /*
  91. =================
  92. CL_ParseBeam
  93. =================
  94. */
  95. void CL_ParseBeam (model_t *m)
  96. {
  97. int ent;
  98. vec3_t start, end;
  99. beam_t *b;
  100. int i;
  101. ent = MSG_ReadShort ();
  102. start[0] = MSG_ReadCoord ();
  103. start[1] = MSG_ReadCoord ();
  104. start[2] = MSG_ReadCoord ();
  105. end[0] = MSG_ReadCoord ();
  106. end[1] = MSG_ReadCoord ();
  107. end[2] = MSG_ReadCoord ();
  108. // override any beam with the same entity
  109. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  110. if (b->entity == ent)
  111. {
  112. b->entity = ent;
  113. b->model = m;
  114. b->endtime = cl.time + 0.2;
  115. VectorCopy (start, b->start);
  116. VectorCopy (end, b->end);
  117. return;
  118. }
  119. // find a free beam
  120. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  121. {
  122. if (!b->model || b->endtime < cl.time)
  123. {
  124. b->entity = ent;
  125. b->model = m;
  126. b->endtime = cl.time + 0.2;
  127. VectorCopy (start, b->start);
  128. VectorCopy (end, b->end);
  129. return;
  130. }
  131. }
  132. Con_Printf ("beam list overflow!\n");
  133. }
  134. /*
  135. =================
  136. CL_ParseTEnt
  137. =================
  138. */
  139. void CL_ParseTEnt (void)
  140. {
  141. int type;
  142. vec3_t pos;
  143. dlight_t *dl;
  144. int rnd;
  145. explosion_t *ex;
  146. int cnt;
  147. type = MSG_ReadByte ();
  148. switch (type)
  149. {
  150. case TE_WIZSPIKE: // spike hitting wall
  151. pos[0] = MSG_ReadCoord ();
  152. pos[1] = MSG_ReadCoord ();
  153. pos[2] = MSG_ReadCoord ();
  154. R_RunParticleEffect (pos, vec3_origin, 20, 30);
  155. S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
  156. break;
  157. case TE_KNIGHTSPIKE: // spike hitting wall
  158. pos[0] = MSG_ReadCoord ();
  159. pos[1] = MSG_ReadCoord ();
  160. pos[2] = MSG_ReadCoord ();
  161. R_RunParticleEffect (pos, vec3_origin, 226, 20);
  162. S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
  163. break;
  164. case TE_SPIKE: // spike hitting wall
  165. pos[0] = MSG_ReadCoord ();
  166. pos[1] = MSG_ReadCoord ();
  167. pos[2] = MSG_ReadCoord ();
  168. R_RunParticleEffect (pos, vec3_origin, 0, 10);
  169. if ( rand() % 5 )
  170. S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
  171. else
  172. {
  173. rnd = rand() & 3;
  174. if (rnd == 1)
  175. S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
  176. else if (rnd == 2)
  177. S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
  178. else
  179. S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
  180. }
  181. break;
  182. case TE_SUPERSPIKE: // super spike hitting wall
  183. pos[0] = MSG_ReadCoord ();
  184. pos[1] = MSG_ReadCoord ();
  185. pos[2] = MSG_ReadCoord ();
  186. R_RunParticleEffect (pos, vec3_origin, 0, 20);
  187. if ( rand() % 5 )
  188. S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
  189. else
  190. {
  191. rnd = rand() & 3;
  192. if (rnd == 1)
  193. S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
  194. else if (rnd == 2)
  195. S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
  196. else
  197. S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
  198. }
  199. break;
  200. case TE_EXPLOSION: // rocket explosion
  201. // particles
  202. pos[0] = MSG_ReadCoord ();
  203. pos[1] = MSG_ReadCoord ();
  204. pos[2] = MSG_ReadCoord ();
  205. R_ParticleExplosion (pos);
  206. // light
  207. dl = CL_AllocDlight (0);
  208. VectorCopy (pos, dl->origin);
  209. dl->radius = 350;
  210. dl->die = cl.time + 0.5;
  211. dl->decay = 300;
  212. dl->color[0] = 0.2;
  213. dl->color[1] = 0.1;
  214. dl->color[2] = 0.05;
  215. dl->color[3] = 0.7;
  216. // sound
  217. S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
  218. // sprite
  219. ex = CL_AllocExplosion ();
  220. VectorCopy (pos, ex->origin);
  221. ex->start = cl.time;
  222. ex->model = Mod_ForName ("progs/s_explod.spr", true);
  223. break;
  224. case TE_TAREXPLOSION: // tarbaby explosion
  225. pos[0] = MSG_ReadCoord ();
  226. pos[1] = MSG_ReadCoord ();
  227. pos[2] = MSG_ReadCoord ();
  228. R_BlobExplosion (pos);
  229. S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
  230. break;
  231. case TE_LIGHTNING1: // lightning bolts
  232. CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
  233. break;
  234. case TE_LIGHTNING2: // lightning bolts
  235. CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
  236. break;
  237. case TE_LIGHTNING3: // lightning bolts
  238. CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
  239. break;
  240. case TE_LAVASPLASH:
  241. pos[0] = MSG_ReadCoord ();
  242. pos[1] = MSG_ReadCoord ();
  243. pos[2] = MSG_ReadCoord ();
  244. R_LavaSplash (pos);
  245. break;
  246. case TE_TELEPORT:
  247. pos[0] = MSG_ReadCoord ();
  248. pos[1] = MSG_ReadCoord ();
  249. pos[2] = MSG_ReadCoord ();
  250. R_TeleportSplash (pos);
  251. break;
  252. case TE_GUNSHOT: // bullet hitting wall
  253. cnt = MSG_ReadByte ();
  254. pos[0] = MSG_ReadCoord ();
  255. pos[1] = MSG_ReadCoord ();
  256. pos[2] = MSG_ReadCoord ();
  257. R_RunParticleEffect (pos, vec3_origin, 0, 20*cnt);
  258. break;
  259. case TE_BLOOD: // bullets hitting body
  260. cnt = MSG_ReadByte ();
  261. pos[0] = MSG_ReadCoord ();
  262. pos[1] = MSG_ReadCoord ();
  263. pos[2] = MSG_ReadCoord ();
  264. R_RunParticleEffect (pos, vec3_origin, 73, 20*cnt);
  265. break;
  266. case TE_LIGHTNINGBLOOD: // lightning hitting body
  267. pos[0] = MSG_ReadCoord ();
  268. pos[1] = MSG_ReadCoord ();
  269. pos[2] = MSG_ReadCoord ();
  270. R_RunParticleEffect (pos, vec3_origin, 225, 50);
  271. break;
  272. default:
  273. Sys_Error ("CL_ParseTEnt: bad type");
  274. }
  275. }
  276. /*
  277. =================
  278. CL_NewTempEntity
  279. =================
  280. */
  281. entity_t *CL_NewTempEntity (void)
  282. {
  283. entity_t *ent;
  284. if (cl_numvisedicts == MAX_VISEDICTS)
  285. return NULL;
  286. ent = &cl_visedicts[cl_numvisedicts];
  287. cl_numvisedicts++;
  288. ent->keynum = 0;
  289. memset (ent, 0, sizeof(*ent));
  290. ent->colormap = vid.colormap;
  291. return ent;
  292. }
  293. /*
  294. =================
  295. CL_UpdateBeams
  296. =================
  297. */
  298. void CL_UpdateBeams (void)
  299. {
  300. int i;
  301. beam_t *b;
  302. vec3_t dist, org;
  303. float d;
  304. entity_t *ent;
  305. float yaw, pitch;
  306. float forward;
  307. // update lightning
  308. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  309. {
  310. if (!b->model || b->endtime < cl.time)
  311. continue;
  312. // if coming from the player, update the start position
  313. if (b->entity == cl.playernum+1) // entity 0 is the world
  314. {
  315. VectorCopy (cl.simorg, b->start);
  316. // b->start[2] -= 22; // adjust for view height
  317. }
  318. // calculate pitch and yaw
  319. VectorSubtract (b->end, b->start, dist);
  320. if (dist[1] == 0 && dist[0] == 0)
  321. {
  322. yaw = 0;
  323. if (dist[2] > 0)
  324. pitch = 90;
  325. else
  326. pitch = 270;
  327. }
  328. else
  329. {
  330. yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
  331. if (yaw < 0)
  332. yaw += 360;
  333. forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
  334. pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
  335. if (pitch < 0)
  336. pitch += 360;
  337. }
  338. // add new entities for the lightning
  339. VectorCopy (b->start, org);
  340. d = VectorNormalize(dist);
  341. while (d > 0)
  342. {
  343. ent = CL_NewTempEntity ();
  344. if (!ent)
  345. return;
  346. VectorCopy (org, ent->origin);
  347. ent->model = b->model;
  348. ent->angles[0] = pitch;
  349. ent->angles[1] = yaw;
  350. ent->angles[2] = rand()%360;
  351. for (i=0 ; i<3 ; i++)
  352. org[i] += dist[i]*30;
  353. d -= 30;
  354. }
  355. }
  356. }
  357. /*
  358. =================
  359. CL_UpdateExplosions
  360. =================
  361. */
  362. void CL_UpdateExplosions (void)
  363. {
  364. int i;
  365. int f;
  366. explosion_t *ex;
  367. entity_t *ent;
  368. for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++)
  369. {
  370. if (!ex->model)
  371. continue;
  372. f = 10*(cl.time - ex->start);
  373. if (f >= ex->model->numframes)
  374. {
  375. ex->model = NULL;
  376. continue;
  377. }
  378. ent = CL_NewTempEntity ();
  379. if (!ent)
  380. return;
  381. VectorCopy (ex->origin, ent->origin);
  382. ent->model = ex->model;
  383. ent->frame = f;
  384. }
  385. }
  386. /*
  387. =================
  388. CL_UpdateTEnts
  389. =================
  390. */
  391. void CL_UpdateTEnts (void)
  392. {
  393. CL_UpdateBeams ();
  394. CL_UpdateExplosions ();
  395. }