cl_tent.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746
  1. /*
  2. Copyright (C) 1997-2001 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 "client.h"
  17. typedef enum
  18. {
  19. ex_free, ex_explosion, ex_misc, ex_flash, ex_mflash, ex_poly, ex_poly2
  20. } exptype_t;
  21. typedef struct
  22. {
  23. exptype_t type;
  24. entity_t ent;
  25. int frames;
  26. float light;
  27. vec3_t lightcolor;
  28. float start;
  29. int baseframe;
  30. } explosion_t;
  31. #define MAX_EXPLOSIONS 32
  32. explosion_t cl_explosions[MAX_EXPLOSIONS];
  33. #define MAX_BEAMS 32
  34. typedef struct
  35. {
  36. int entity;
  37. int dest_entity;
  38. struct model_s *model;
  39. int endtime;
  40. vec3_t offset;
  41. vec3_t start, end;
  42. } beam_t;
  43. beam_t cl_beams[MAX_BEAMS];
  44. //PMM - added this for player-linked beams. Currently only used by the plasma beam
  45. beam_t cl_playerbeams[MAX_BEAMS];
  46. #define MAX_LASERS 32
  47. typedef struct
  48. {
  49. entity_t ent;
  50. int endtime;
  51. } laser_t;
  52. laser_t cl_lasers[MAX_LASERS];
  53. //ROGUE
  54. cl_sustain_t cl_sustains[MAX_SUSTAINS];
  55. //ROGUE
  56. //PGM
  57. extern void CL_TeleportParticles (vec3_t org);
  58. //PGM
  59. void CL_BlasterParticles (vec3_t org, vec3_t dir);
  60. void CL_ExplosionParticles (vec3_t org);
  61. void CL_BFGExplosionParticles (vec3_t org);
  62. // RAFAEL
  63. void CL_BlueBlasterParticles (vec3_t org, vec3_t dir);
  64. struct sfx_s *cl_sfx_ric1;
  65. struct sfx_s *cl_sfx_ric2;
  66. struct sfx_s *cl_sfx_ric3;
  67. struct sfx_s *cl_sfx_lashit;
  68. struct sfx_s *cl_sfx_spark5;
  69. struct sfx_s *cl_sfx_spark6;
  70. struct sfx_s *cl_sfx_spark7;
  71. struct sfx_s *cl_sfx_railg;
  72. struct sfx_s *cl_sfx_rockexp;
  73. struct sfx_s *cl_sfx_grenexp;
  74. struct sfx_s *cl_sfx_watrexp;
  75. // RAFAEL
  76. struct sfx_s *cl_sfx_plasexp;
  77. struct sfx_s *cl_sfx_footsteps[4];
  78. struct model_s *cl_mod_explode;
  79. struct model_s *cl_mod_smoke;
  80. struct model_s *cl_mod_flash;
  81. struct model_s *cl_mod_parasite_segment;
  82. struct model_s *cl_mod_grapple_cable;
  83. struct model_s *cl_mod_parasite_tip;
  84. struct model_s *cl_mod_explo4;
  85. struct model_s *cl_mod_bfg_explo;
  86. struct model_s *cl_mod_powerscreen;
  87. // RAFAEL
  88. struct model_s *cl_mod_plasmaexplo;
  89. //ROGUE
  90. struct sfx_s *cl_sfx_lightning;
  91. struct sfx_s *cl_sfx_disrexp;
  92. struct model_s *cl_mod_lightning;
  93. struct model_s *cl_mod_heatbeam;
  94. struct model_s *cl_mod_monster_heatbeam;
  95. struct model_s *cl_mod_explo4_big;
  96. //ROGUE
  97. /*
  98. =================
  99. CL_RegisterTEntSounds
  100. =================
  101. */
  102. void CL_RegisterTEntSounds (void)
  103. {
  104. int i;
  105. char name[MAX_QPATH];
  106. // PMM - version stuff
  107. // Com_Printf ("%s\n", ROGUE_VERSION_STRING);
  108. // PMM
  109. cl_sfx_ric1 = S_RegisterSound ("world/ric1.wav");
  110. cl_sfx_ric2 = S_RegisterSound ("world/ric2.wav");
  111. cl_sfx_ric3 = S_RegisterSound ("world/ric3.wav");
  112. cl_sfx_lashit = S_RegisterSound("weapons/lashit.wav");
  113. cl_sfx_spark5 = S_RegisterSound ("world/spark5.wav");
  114. cl_sfx_spark6 = S_RegisterSound ("world/spark6.wav");
  115. cl_sfx_spark7 = S_RegisterSound ("world/spark7.wav");
  116. cl_sfx_railg = S_RegisterSound ("weapons/railgf1a.wav");
  117. cl_sfx_rockexp = S_RegisterSound ("weapons/rocklx1a.wav");
  118. cl_sfx_grenexp = S_RegisterSound ("weapons/grenlx1a.wav");
  119. cl_sfx_watrexp = S_RegisterSound ("weapons/xpld_wat.wav");
  120. // RAFAEL
  121. // cl_sfx_plasexp = S_RegisterSound ("weapons/plasexpl.wav");
  122. S_RegisterSound ("player/land1.wav");
  123. S_RegisterSound ("player/fall2.wav");
  124. S_RegisterSound ("player/fall1.wav");
  125. for (i=0 ; i<4 ; i++)
  126. {
  127. Com_sprintf (name, sizeof(name), "player/step%i.wav", i+1);
  128. cl_sfx_footsteps[i] = S_RegisterSound (name);
  129. }
  130. //PGM
  131. cl_sfx_lightning = S_RegisterSound ("weapons/tesla.wav");
  132. cl_sfx_disrexp = S_RegisterSound ("weapons/disrupthit.wav");
  133. // version stuff
  134. sprintf (name, "weapons/sound%d.wav", ROGUE_VERSION_ID);
  135. if (name[0] == 'w')
  136. name[0] = 'W';
  137. //PGM
  138. }
  139. /*
  140. =================
  141. CL_RegisterTEntModels
  142. =================
  143. */
  144. void CL_RegisterTEntModels (void)
  145. {
  146. cl_mod_explode = re.RegisterModel ("models/objects/explode/tris.md2");
  147. cl_mod_smoke = re.RegisterModel ("models/objects/smoke/tris.md2");
  148. cl_mod_flash = re.RegisterModel ("models/objects/flash/tris.md2");
  149. cl_mod_parasite_segment = re.RegisterModel ("models/monsters/parasite/segment/tris.md2");
  150. cl_mod_grapple_cable = re.RegisterModel ("models/ctf/segment/tris.md2");
  151. cl_mod_parasite_tip = re.RegisterModel ("models/monsters/parasite/tip/tris.md2");
  152. cl_mod_explo4 = re.RegisterModel ("models/objects/r_explode/tris.md2");
  153. cl_mod_bfg_explo = re.RegisterModel ("sprites/s_bfg2.sp2");
  154. cl_mod_powerscreen = re.RegisterModel ("models/items/armor/effect/tris.md2");
  155. re.RegisterModel ("models/objects/laser/tris.md2");
  156. re.RegisterModel ("models/objects/grenade2/tris.md2");
  157. re.RegisterModel ("models/weapons/v_machn/tris.md2");
  158. re.RegisterModel ("models/weapons/v_handgr/tris.md2");
  159. re.RegisterModel ("models/weapons/v_shotg2/tris.md2");
  160. re.RegisterModel ("models/objects/gibs/bone/tris.md2");
  161. re.RegisterModel ("models/objects/gibs/sm_meat/tris.md2");
  162. re.RegisterModel ("models/objects/gibs/bone2/tris.md2");
  163. // RAFAEL
  164. // re.RegisterModel ("models/objects/blaser/tris.md2");
  165. re.RegisterPic ("w_machinegun");
  166. re.RegisterPic ("a_bullets");
  167. re.RegisterPic ("i_health");
  168. re.RegisterPic ("a_grenades");
  169. //ROGUE
  170. cl_mod_explo4_big = re.RegisterModel ("models/objects/r_explode2/tris.md2");
  171. cl_mod_lightning = re.RegisterModel ("models/proj/lightning/tris.md2");
  172. cl_mod_heatbeam = re.RegisterModel ("models/proj/beam/tris.md2");
  173. cl_mod_monster_heatbeam = re.RegisterModel ("models/proj/widowbeam/tris.md2");
  174. //ROGUE
  175. }
  176. /*
  177. =================
  178. CL_ClearTEnts
  179. =================
  180. */
  181. void CL_ClearTEnts (void)
  182. {
  183. memset (cl_beams, 0, sizeof(cl_beams));
  184. memset (cl_explosions, 0, sizeof(cl_explosions));
  185. memset (cl_lasers, 0, sizeof(cl_lasers));
  186. //ROGUE
  187. memset (cl_playerbeams, 0, sizeof(cl_playerbeams));
  188. memset (cl_sustains, 0, sizeof(cl_sustains));
  189. //ROGUE
  190. }
  191. /*
  192. =================
  193. CL_AllocExplosion
  194. =================
  195. */
  196. explosion_t *CL_AllocExplosion (void)
  197. {
  198. int i;
  199. int time;
  200. int index;
  201. for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  202. {
  203. if (cl_explosions[i].type == ex_free)
  204. {
  205. memset (&cl_explosions[i], 0, sizeof (cl_explosions[i]));
  206. return &cl_explosions[i];
  207. }
  208. }
  209. // find the oldest explosion
  210. time = cl.time;
  211. index = 0;
  212. for (i=0 ; i<MAX_EXPLOSIONS ; i++)
  213. if (cl_explosions[i].start < time)
  214. {
  215. time = cl_explosions[i].start;
  216. index = i;
  217. }
  218. memset (&cl_explosions[index], 0, sizeof (cl_explosions[index]));
  219. return &cl_explosions[index];
  220. }
  221. /*
  222. =================
  223. CL_SmokeAndFlash
  224. =================
  225. */
  226. void CL_SmokeAndFlash(vec3_t origin)
  227. {
  228. explosion_t *ex;
  229. ex = CL_AllocExplosion ();
  230. VectorCopy (origin, ex->ent.origin);
  231. ex->type = ex_misc;
  232. ex->frames = 4;
  233. ex->ent.flags = RF_TRANSLUCENT;
  234. ex->start = cl.frame.servertime - 100;
  235. ex->ent.model = cl_mod_smoke;
  236. ex = CL_AllocExplosion ();
  237. VectorCopy (origin, ex->ent.origin);
  238. ex->type = ex_flash;
  239. ex->ent.flags = RF_FULLBRIGHT;
  240. ex->frames = 2;
  241. ex->start = cl.frame.servertime - 100;
  242. ex->ent.model = cl_mod_flash;
  243. }
  244. /*
  245. =================
  246. CL_ParseParticles
  247. =================
  248. */
  249. void CL_ParseParticles (void)
  250. {
  251. int color, count;
  252. vec3_t pos, dir;
  253. MSG_ReadPos (&net_message, pos);
  254. MSG_ReadDir (&net_message, dir);
  255. color = MSG_ReadByte (&net_message);
  256. count = MSG_ReadByte (&net_message);
  257. CL_ParticleEffect (pos, dir, color, count);
  258. }
  259. /*
  260. =================
  261. CL_ParseBeam
  262. =================
  263. */
  264. int CL_ParseBeam (struct model_s *model)
  265. {
  266. int ent;
  267. vec3_t start, end;
  268. beam_t *b;
  269. int i;
  270. ent = MSG_ReadShort (&net_message);
  271. MSG_ReadPos (&net_message, start);
  272. MSG_ReadPos (&net_message, end);
  273. // override any beam with the same entity
  274. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  275. if (b->entity == ent)
  276. {
  277. b->entity = ent;
  278. b->model = model;
  279. b->endtime = cl.time + 200;
  280. VectorCopy (start, b->start);
  281. VectorCopy (end, b->end);
  282. VectorClear (b->offset);
  283. return ent;
  284. }
  285. // find a free beam
  286. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  287. {
  288. if (!b->model || b->endtime < cl.time)
  289. {
  290. b->entity = ent;
  291. b->model = model;
  292. b->endtime = cl.time + 200;
  293. VectorCopy (start, b->start);
  294. VectorCopy (end, b->end);
  295. VectorClear (b->offset);
  296. return ent;
  297. }
  298. }
  299. Com_Printf ("beam list overflow!\n");
  300. return ent;
  301. }
  302. /*
  303. =================
  304. CL_ParseBeam2
  305. =================
  306. */
  307. int CL_ParseBeam2 (struct model_s *model)
  308. {
  309. int ent;
  310. vec3_t start, end, offset;
  311. beam_t *b;
  312. int i;
  313. ent = MSG_ReadShort (&net_message);
  314. MSG_ReadPos (&net_message, start);
  315. MSG_ReadPos (&net_message, end);
  316. MSG_ReadPos (&net_message, offset);
  317. // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
  318. // override any beam with the same entity
  319. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  320. if (b->entity == ent)
  321. {
  322. b->entity = ent;
  323. b->model = model;
  324. b->endtime = cl.time + 200;
  325. VectorCopy (start, b->start);
  326. VectorCopy (end, b->end);
  327. VectorCopy (offset, b->offset);
  328. return ent;
  329. }
  330. // find a free beam
  331. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  332. {
  333. if (!b->model || b->endtime < cl.time)
  334. {
  335. b->entity = ent;
  336. b->model = model;
  337. b->endtime = cl.time + 200;
  338. VectorCopy (start, b->start);
  339. VectorCopy (end, b->end);
  340. VectorCopy (offset, b->offset);
  341. return ent;
  342. }
  343. }
  344. Com_Printf ("beam list overflow!\n");
  345. return ent;
  346. }
  347. // ROGUE
  348. /*
  349. =================
  350. CL_ParsePlayerBeam
  351. - adds to the cl_playerbeam array instead of the cl_beams array
  352. =================
  353. */
  354. int CL_ParsePlayerBeam (struct model_s *model)
  355. {
  356. int ent;
  357. vec3_t start, end, offset;
  358. beam_t *b;
  359. int i;
  360. ent = MSG_ReadShort (&net_message);
  361. MSG_ReadPos (&net_message, start);
  362. MSG_ReadPos (&net_message, end);
  363. // PMM - network optimization
  364. if (model == cl_mod_heatbeam)
  365. VectorSet(offset, 2, 7, -3);
  366. else if (model == cl_mod_monster_heatbeam)
  367. {
  368. model = cl_mod_heatbeam;
  369. VectorSet(offset, 0, 0, 0);
  370. }
  371. else
  372. MSG_ReadPos (&net_message, offset);
  373. // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
  374. // override any beam with the same entity
  375. // PMM - For player beams, we only want one per player (entity) so..
  376. for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
  377. {
  378. if (b->entity == ent)
  379. {
  380. b->entity = ent;
  381. b->model = model;
  382. b->endtime = cl.time + 200;
  383. VectorCopy (start, b->start);
  384. VectorCopy (end, b->end);
  385. VectorCopy (offset, b->offset);
  386. return ent;
  387. }
  388. }
  389. // find a free beam
  390. for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
  391. {
  392. if (!b->model || b->endtime < cl.time)
  393. {
  394. b->entity = ent;
  395. b->model = model;
  396. b->endtime = cl.time + 100; // PMM - this needs to be 100 to prevent multiple heatbeams
  397. VectorCopy (start, b->start);
  398. VectorCopy (end, b->end);
  399. VectorCopy (offset, b->offset);
  400. return ent;
  401. }
  402. }
  403. Com_Printf ("beam list overflow!\n");
  404. return ent;
  405. }
  406. //rogue
  407. /*
  408. =================
  409. CL_ParseLightning
  410. =================
  411. */
  412. int CL_ParseLightning (struct model_s *model)
  413. {
  414. int srcEnt, destEnt;
  415. vec3_t start, end;
  416. beam_t *b;
  417. int i;
  418. srcEnt = MSG_ReadShort (&net_message);
  419. destEnt = MSG_ReadShort (&net_message);
  420. MSG_ReadPos (&net_message, start);
  421. MSG_ReadPos (&net_message, end);
  422. // override any beam with the same source AND destination entities
  423. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  424. if (b->entity == srcEnt && b->dest_entity == destEnt)
  425. {
  426. // Com_Printf("%d: OVERRIDE %d -> %d\n", cl.time, srcEnt, destEnt);
  427. b->entity = srcEnt;
  428. b->dest_entity = destEnt;
  429. b->model = model;
  430. b->endtime = cl.time + 200;
  431. VectorCopy (start, b->start);
  432. VectorCopy (end, b->end);
  433. VectorClear (b->offset);
  434. return srcEnt;
  435. }
  436. // find a free beam
  437. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  438. {
  439. if (!b->model || b->endtime < cl.time)
  440. {
  441. // Com_Printf("%d: NORMAL %d -> %d\n", cl.time, srcEnt, destEnt);
  442. b->entity = srcEnt;
  443. b->dest_entity = destEnt;
  444. b->model = model;
  445. b->endtime = cl.time + 200;
  446. VectorCopy (start, b->start);
  447. VectorCopy (end, b->end);
  448. VectorClear (b->offset);
  449. return srcEnt;
  450. }
  451. }
  452. Com_Printf ("beam list overflow!\n");
  453. return srcEnt;
  454. }
  455. /*
  456. =================
  457. CL_ParseLaser
  458. =================
  459. */
  460. void CL_ParseLaser (int colors)
  461. {
  462. vec3_t start;
  463. vec3_t end;
  464. laser_t *l;
  465. int i;
  466. MSG_ReadPos (&net_message, start);
  467. MSG_ReadPos (&net_message, end);
  468. for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
  469. {
  470. if (l->endtime < cl.time)
  471. {
  472. l->ent.flags = RF_TRANSLUCENT | RF_BEAM;
  473. VectorCopy (start, l->ent.origin);
  474. VectorCopy (end, l->ent.oldorigin);
  475. l->ent.alpha = 0.30;
  476. l->ent.skinnum = (colors >> ((rand() % 4)*8)) & 0xff;
  477. l->ent.model = NULL;
  478. l->ent.frame = 4;
  479. l->endtime = cl.time + 100;
  480. return;
  481. }
  482. }
  483. }
  484. //=============
  485. //ROGUE
  486. void CL_ParseSteam (void)
  487. {
  488. vec3_t pos, dir;
  489. int id, i;
  490. int r;
  491. int cnt;
  492. int color;
  493. int magnitude;
  494. cl_sustain_t *s, *free_sustain;
  495. id = MSG_ReadShort (&net_message); // an id of -1 is an instant effect
  496. if (id != -1) // sustains
  497. {
  498. // Com_Printf ("Sustain effect id %d\n", id);
  499. free_sustain = NULL;
  500. for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  501. {
  502. if (s->id == 0)
  503. {
  504. free_sustain = s;
  505. break;
  506. }
  507. }
  508. if (free_sustain)
  509. {
  510. s->id = id;
  511. s->count = MSG_ReadByte (&net_message);
  512. MSG_ReadPos (&net_message, s->org);
  513. MSG_ReadDir (&net_message, s->dir);
  514. r = MSG_ReadByte (&net_message);
  515. s->color = r & 0xff;
  516. s->magnitude = MSG_ReadShort (&net_message);
  517. s->endtime = cl.time + MSG_ReadLong (&net_message);
  518. s->think = CL_ParticleSteamEffect2;
  519. s->thinkinterval = 100;
  520. s->nextthink = cl.time;
  521. }
  522. else
  523. {
  524. // Com_Printf ("No free sustains!\n");
  525. // FIXME - read the stuff anyway
  526. cnt = MSG_ReadByte (&net_message);
  527. MSG_ReadPos (&net_message, pos);
  528. MSG_ReadDir (&net_message, dir);
  529. r = MSG_ReadByte (&net_message);
  530. magnitude = MSG_ReadShort (&net_message);
  531. magnitude = MSG_ReadLong (&net_message); // really interval
  532. }
  533. }
  534. else // instant
  535. {
  536. cnt = MSG_ReadByte (&net_message);
  537. MSG_ReadPos (&net_message, pos);
  538. MSG_ReadDir (&net_message, dir);
  539. r = MSG_ReadByte (&net_message);
  540. magnitude = MSG_ReadShort (&net_message);
  541. color = r & 0xff;
  542. CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
  543. // S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  544. }
  545. }
  546. void CL_ParseWidow (void)
  547. {
  548. vec3_t pos;
  549. int id, i;
  550. cl_sustain_t *s, *free_sustain;
  551. id = MSG_ReadShort (&net_message);
  552. free_sustain = NULL;
  553. for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  554. {
  555. if (s->id == 0)
  556. {
  557. free_sustain = s;
  558. break;
  559. }
  560. }
  561. if (free_sustain)
  562. {
  563. s->id = id;
  564. MSG_ReadPos (&net_message, s->org);
  565. s->endtime = cl.time + 2100;
  566. s->think = CL_Widowbeamout;
  567. s->thinkinterval = 1;
  568. s->nextthink = cl.time;
  569. }
  570. else // no free sustains
  571. {
  572. // FIXME - read the stuff anyway
  573. MSG_ReadPos (&net_message, pos);
  574. }
  575. }
  576. void CL_ParseNuke (void)
  577. {
  578. vec3_t pos;
  579. int i;
  580. cl_sustain_t *s, *free_sustain;
  581. free_sustain = NULL;
  582. for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
  583. {
  584. if (s->id == 0)
  585. {
  586. free_sustain = s;
  587. break;
  588. }
  589. }
  590. if (free_sustain)
  591. {
  592. s->id = 21000;
  593. MSG_ReadPos (&net_message, s->org);
  594. s->endtime = cl.time + 1000;
  595. s->think = CL_Nukeblast;
  596. s->thinkinterval = 1;
  597. s->nextthink = cl.time;
  598. }
  599. else // no free sustains
  600. {
  601. // FIXME - read the stuff anyway
  602. MSG_ReadPos (&net_message, pos);
  603. }
  604. }
  605. //ROGUE
  606. //=============
  607. /*
  608. =================
  609. CL_ParseTEnt
  610. =================
  611. */
  612. static byte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8};
  613. void CL_ParseTEnt (void)
  614. {
  615. int type;
  616. vec3_t pos, pos2, dir;
  617. explosion_t *ex;
  618. int cnt;
  619. int color;
  620. int r;
  621. int ent;
  622. int magnitude;
  623. type = MSG_ReadByte (&net_message);
  624. switch (type)
  625. {
  626. case TE_BLOOD: // bullet hitting flesh
  627. MSG_ReadPos (&net_message, pos);
  628. MSG_ReadDir (&net_message, dir);
  629. CL_ParticleEffect (pos, dir, 0xe8, 60);
  630. break;
  631. case TE_GUNSHOT: // bullet hitting wall
  632. case TE_SPARKS:
  633. case TE_BULLET_SPARKS:
  634. MSG_ReadPos (&net_message, pos);
  635. MSG_ReadDir (&net_message, dir);
  636. if (type == TE_GUNSHOT)
  637. CL_ParticleEffect (pos, dir, 0, 40);
  638. else
  639. CL_ParticleEffect (pos, dir, 0xe0, 6);
  640. if (type != TE_SPARKS)
  641. {
  642. CL_SmokeAndFlash(pos);
  643. // impact sound
  644. cnt = rand()&15;
  645. if (cnt == 1)
  646. S_StartSound (pos, 0, 0, cl_sfx_ric1, 1, ATTN_NORM, 0);
  647. else if (cnt == 2)
  648. S_StartSound (pos, 0, 0, cl_sfx_ric2, 1, ATTN_NORM, 0);
  649. else if (cnt == 3)
  650. S_StartSound (pos, 0, 0, cl_sfx_ric3, 1, ATTN_NORM, 0);
  651. }
  652. break;
  653. case TE_SCREEN_SPARKS:
  654. case TE_SHIELD_SPARKS:
  655. MSG_ReadPos (&net_message, pos);
  656. MSG_ReadDir (&net_message, dir);
  657. if (type == TE_SCREEN_SPARKS)
  658. CL_ParticleEffect (pos, dir, 0xd0, 40);
  659. else
  660. CL_ParticleEffect (pos, dir, 0xb0, 40);
  661. //FIXME : replace or remove this sound
  662. S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  663. break;
  664. case TE_SHOTGUN: // bullet hitting wall
  665. MSG_ReadPos (&net_message, pos);
  666. MSG_ReadDir (&net_message, dir);
  667. CL_ParticleEffect (pos, dir, 0, 20);
  668. CL_SmokeAndFlash(pos);
  669. break;
  670. case TE_SPLASH: // bullet hitting water
  671. cnt = MSG_ReadByte (&net_message);
  672. MSG_ReadPos (&net_message, pos);
  673. MSG_ReadDir (&net_message, dir);
  674. r = MSG_ReadByte (&net_message);
  675. if (r > 6)
  676. color = 0x00;
  677. else
  678. color = splash_color[r];
  679. CL_ParticleEffect (pos, dir, color, cnt);
  680. if (r == SPLASH_SPARKS)
  681. {
  682. r = rand() & 3;
  683. if (r == 0)
  684. S_StartSound (pos, 0, 0, cl_sfx_spark5, 1, ATTN_STATIC, 0);
  685. else if (r == 1)
  686. S_StartSound (pos, 0, 0, cl_sfx_spark6, 1, ATTN_STATIC, 0);
  687. else
  688. S_StartSound (pos, 0, 0, cl_sfx_spark7, 1, ATTN_STATIC, 0);
  689. }
  690. break;
  691. case TE_LASER_SPARKS:
  692. cnt = MSG_ReadByte (&net_message);
  693. MSG_ReadPos (&net_message, pos);
  694. MSG_ReadDir (&net_message, dir);
  695. color = MSG_ReadByte (&net_message);
  696. CL_ParticleEffect2 (pos, dir, color, cnt);
  697. break;
  698. // RAFAEL
  699. case TE_BLUEHYPERBLASTER:
  700. MSG_ReadPos (&net_message, pos);
  701. MSG_ReadPos (&net_message, dir);
  702. CL_BlasterParticles (pos, dir);
  703. break;
  704. case TE_BLASTER: // blaster hitting wall
  705. MSG_ReadPos (&net_message, pos);
  706. MSG_ReadDir (&net_message, dir);
  707. CL_BlasterParticles (pos, dir);
  708. ex = CL_AllocExplosion ();
  709. VectorCopy (pos, ex->ent.origin);
  710. ex->ent.angles[0] = acos(dir[2])/M_PI*180;
  711. // PMM - fixed to correct for pitch of 0
  712. if (dir[0])
  713. ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
  714. else if (dir[1] > 0)
  715. ex->ent.angles[1] = 90;
  716. else if (dir[1] < 0)
  717. ex->ent.angles[1] = 270;
  718. else
  719. ex->ent.angles[1] = 0;
  720. ex->type = ex_misc;
  721. ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
  722. ex->start = cl.frame.servertime - 100;
  723. ex->light = 150;
  724. ex->lightcolor[0] = 1;
  725. ex->lightcolor[1] = 1;
  726. ex->ent.model = cl_mod_explode;
  727. ex->frames = 4;
  728. S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  729. break;
  730. case TE_RAILTRAIL: // railgun effect
  731. MSG_ReadPos (&net_message, pos);
  732. MSG_ReadPos (&net_message, pos2);
  733. CL_RailTrail (pos, pos2);
  734. S_StartSound (pos2, 0, 0, cl_sfx_railg, 1, ATTN_NORM, 0);
  735. break;
  736. case TE_EXPLOSION2:
  737. case TE_GRENADE_EXPLOSION:
  738. case TE_GRENADE_EXPLOSION_WATER:
  739. MSG_ReadPos (&net_message, pos);
  740. ex = CL_AllocExplosion ();
  741. VectorCopy (pos, ex->ent.origin);
  742. ex->type = ex_poly;
  743. ex->ent.flags = RF_FULLBRIGHT;
  744. ex->start = cl.frame.servertime - 100;
  745. ex->light = 350;
  746. ex->lightcolor[0] = 1.0;
  747. ex->lightcolor[1] = 0.5;
  748. ex->lightcolor[2] = 0.5;
  749. ex->ent.model = cl_mod_explo4;
  750. ex->frames = 19;
  751. ex->baseframe = 30;
  752. ex->ent.angles[1] = rand() % 360;
  753. CL_ExplosionParticles (pos);
  754. if (type == TE_GRENADE_EXPLOSION_WATER)
  755. S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
  756. else
  757. S_StartSound (pos, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
  758. break;
  759. // RAFAEL
  760. case TE_PLASMA_EXPLOSION:
  761. MSG_ReadPos (&net_message, pos);
  762. ex = CL_AllocExplosion ();
  763. VectorCopy (pos, ex->ent.origin);
  764. ex->type = ex_poly;
  765. ex->ent.flags = RF_FULLBRIGHT;
  766. ex->start = cl.frame.servertime - 100;
  767. ex->light = 350;
  768. ex->lightcolor[0] = 1.0;
  769. ex->lightcolor[1] = 0.5;
  770. ex->lightcolor[2] = 0.5;
  771. ex->ent.angles[1] = rand() % 360;
  772. ex->ent.model = cl_mod_explo4;
  773. if (frand() < 0.5)
  774. ex->baseframe = 15;
  775. ex->frames = 15;
  776. CL_ExplosionParticles (pos);
  777. S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
  778. break;
  779. case TE_EXPLOSION1:
  780. case TE_EXPLOSION1_BIG: // PMM
  781. case TE_ROCKET_EXPLOSION:
  782. case TE_ROCKET_EXPLOSION_WATER:
  783. case TE_EXPLOSION1_NP: // PMM
  784. MSG_ReadPos (&net_message, pos);
  785. ex = CL_AllocExplosion ();
  786. VectorCopy (pos, ex->ent.origin);
  787. ex->type = ex_poly;
  788. ex->ent.flags = RF_FULLBRIGHT;
  789. ex->start = cl.frame.servertime - 100;
  790. ex->light = 350;
  791. ex->lightcolor[0] = 1.0;
  792. ex->lightcolor[1] = 0.5;
  793. ex->lightcolor[2] = 0.5;
  794. ex->ent.angles[1] = rand() % 360;
  795. if (type != TE_EXPLOSION1_BIG) // PMM
  796. ex->ent.model = cl_mod_explo4; // PMM
  797. else
  798. ex->ent.model = cl_mod_explo4_big;
  799. if (frand() < 0.5)
  800. ex->baseframe = 15;
  801. ex->frames = 15;
  802. if ((type != TE_EXPLOSION1_BIG) && (type != TE_EXPLOSION1_NP)) // PMM
  803. CL_ExplosionParticles (pos); // PMM
  804. if (type == TE_ROCKET_EXPLOSION_WATER)
  805. S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
  806. else
  807. S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
  808. break;
  809. case TE_BFG_EXPLOSION:
  810. MSG_ReadPos (&net_message, pos);
  811. ex = CL_AllocExplosion ();
  812. VectorCopy (pos, ex->ent.origin);
  813. ex->type = ex_poly;
  814. ex->ent.flags = RF_FULLBRIGHT;
  815. ex->start = cl.frame.servertime - 100;
  816. ex->light = 350;
  817. ex->lightcolor[0] = 0.0;
  818. ex->lightcolor[1] = 1.0;
  819. ex->lightcolor[2] = 0.0;
  820. ex->ent.model = cl_mod_bfg_explo;
  821. ex->ent.flags |= RF_TRANSLUCENT;
  822. ex->ent.alpha = 0.30;
  823. ex->frames = 4;
  824. break;
  825. case TE_BFG_BIGEXPLOSION:
  826. MSG_ReadPos (&net_message, pos);
  827. CL_BFGExplosionParticles (pos);
  828. break;
  829. case TE_BFG_LASER:
  830. CL_ParseLaser (0xd0d1d2d3);
  831. break;
  832. case TE_BUBBLETRAIL:
  833. MSG_ReadPos (&net_message, pos);
  834. MSG_ReadPos (&net_message, pos2);
  835. CL_BubbleTrail (pos, pos2);
  836. break;
  837. case TE_PARASITE_ATTACK:
  838. case TE_MEDIC_CABLE_ATTACK:
  839. ent = CL_ParseBeam (cl_mod_parasite_segment);
  840. break;
  841. case TE_BOSSTPORT: // boss teleporting to station
  842. MSG_ReadPos (&net_message, pos);
  843. CL_BigTeleportParticles (pos);
  844. S_StartSound (pos, 0, 0, S_RegisterSound ("misc/bigtele.wav"), 1, ATTN_NONE, 0);
  845. break;
  846. case TE_GRAPPLE_CABLE:
  847. ent = CL_ParseBeam2 (cl_mod_grapple_cable);
  848. break;
  849. // RAFAEL
  850. case TE_WELDING_SPARKS:
  851. cnt = MSG_ReadByte (&net_message);
  852. MSG_ReadPos (&net_message, pos);
  853. MSG_ReadDir (&net_message, dir);
  854. color = MSG_ReadByte (&net_message);
  855. CL_ParticleEffect2 (pos, dir, color, cnt);
  856. ex = CL_AllocExplosion ();
  857. VectorCopy (pos, ex->ent.origin);
  858. ex->type = ex_flash;
  859. // note to self
  860. // we need a better no draw flag
  861. ex->ent.flags = RF_BEAM;
  862. ex->start = cl.frame.servertime - 0.1;
  863. ex->light = 100 + (rand()%75);
  864. ex->lightcolor[0] = 1.0;
  865. ex->lightcolor[1] = 1.0;
  866. ex->lightcolor[2] = 0.3;
  867. ex->ent.model = cl_mod_flash;
  868. ex->frames = 2;
  869. break;
  870. case TE_GREENBLOOD:
  871. MSG_ReadPos (&net_message, pos);
  872. MSG_ReadDir (&net_message, dir);
  873. CL_ParticleEffect2 (pos, dir, 0xdf, 30);
  874. break;
  875. // RAFAEL
  876. case TE_TUNNEL_SPARKS:
  877. cnt = MSG_ReadByte (&net_message);
  878. MSG_ReadPos (&net_message, pos);
  879. MSG_ReadDir (&net_message, dir);
  880. color = MSG_ReadByte (&net_message);
  881. CL_ParticleEffect3 (pos, dir, color, cnt);
  882. break;
  883. //=============
  884. //PGM
  885. // PMM -following code integrated for flechette (different color)
  886. case TE_BLASTER2: // green blaster hitting wall
  887. case TE_FLECHETTE: // flechette
  888. MSG_ReadPos (&net_message, pos);
  889. MSG_ReadDir (&net_message, dir);
  890. // PMM
  891. if (type == TE_BLASTER2)
  892. CL_BlasterParticles2 (pos, dir, 0xd0);
  893. else
  894. CL_BlasterParticles2 (pos, dir, 0x6f); // 75
  895. ex = CL_AllocExplosion ();
  896. VectorCopy (pos, ex->ent.origin);
  897. ex->ent.angles[0] = acos(dir[2])/M_PI*180;
  898. // PMM - fixed to correct for pitch of 0
  899. if (dir[0])
  900. ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
  901. else if (dir[1] > 0)
  902. ex->ent.angles[1] = 90;
  903. else if (dir[1] < 0)
  904. ex->ent.angles[1] = 270;
  905. else
  906. ex->ent.angles[1] = 0;
  907. ex->type = ex_misc;
  908. ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
  909. // PMM
  910. if (type == TE_BLASTER2)
  911. ex->ent.skinnum = 1;
  912. else // flechette
  913. ex->ent.skinnum = 2;
  914. ex->start = cl.frame.servertime - 100;
  915. ex->light = 150;
  916. // PMM
  917. if (type == TE_BLASTER2)
  918. ex->lightcolor[1] = 1;
  919. else // flechette
  920. {
  921. ex->lightcolor[0] = 0.19;
  922. ex->lightcolor[1] = 0.41;
  923. ex->lightcolor[2] = 0.75;
  924. }
  925. ex->ent.model = cl_mod_explode;
  926. ex->frames = 4;
  927. S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  928. break;
  929. case TE_LIGHTNING:
  930. ent = CL_ParseLightning (cl_mod_lightning);
  931. S_StartSound (NULL, ent, CHAN_WEAPON, cl_sfx_lightning, 1, ATTN_NORM, 0);
  932. break;
  933. case TE_DEBUGTRAIL:
  934. MSG_ReadPos (&net_message, pos);
  935. MSG_ReadPos (&net_message, pos2);
  936. CL_DebugTrail (pos, pos2);
  937. break;
  938. case TE_PLAIN_EXPLOSION:
  939. MSG_ReadPos (&net_message, pos);
  940. ex = CL_AllocExplosion ();
  941. VectorCopy (pos, ex->ent.origin);
  942. ex->type = ex_poly;
  943. ex->ent.flags = RF_FULLBRIGHT;
  944. ex->start = cl.frame.servertime - 100;
  945. ex->light = 350;
  946. ex->lightcolor[0] = 1.0;
  947. ex->lightcolor[1] = 0.5;
  948. ex->lightcolor[2] = 0.5;
  949. ex->ent.angles[1] = rand() % 360;
  950. ex->ent.model = cl_mod_explo4;
  951. if (frand() < 0.5)
  952. ex->baseframe = 15;
  953. ex->frames = 15;
  954. if (type == TE_ROCKET_EXPLOSION_WATER)
  955. S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
  956. else
  957. S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
  958. break;
  959. case TE_FLASHLIGHT:
  960. MSG_ReadPos(&net_message, pos);
  961. ent = MSG_ReadShort(&net_message);
  962. CL_Flashlight(ent, pos);
  963. break;
  964. case TE_FORCEWALL:
  965. MSG_ReadPos(&net_message, pos);
  966. MSG_ReadPos(&net_message, pos2);
  967. color = MSG_ReadByte (&net_message);
  968. CL_ForceWall(pos, pos2, color);
  969. break;
  970. case TE_HEATBEAM:
  971. ent = CL_ParsePlayerBeam (cl_mod_heatbeam);
  972. break;
  973. case TE_MONSTER_HEATBEAM:
  974. ent = CL_ParsePlayerBeam (cl_mod_monster_heatbeam);
  975. break;
  976. case TE_HEATBEAM_SPARKS:
  977. // cnt = MSG_ReadByte (&net_message);
  978. cnt = 50;
  979. MSG_ReadPos (&net_message, pos);
  980. MSG_ReadDir (&net_message, dir);
  981. // r = MSG_ReadByte (&net_message);
  982. // magnitude = MSG_ReadShort (&net_message);
  983. r = 8;
  984. magnitude = 60;
  985. color = r & 0xff;
  986. CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
  987. S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  988. break;
  989. case TE_HEATBEAM_STEAM:
  990. // cnt = MSG_ReadByte (&net_message);
  991. cnt = 20;
  992. MSG_ReadPos (&net_message, pos);
  993. MSG_ReadDir (&net_message, dir);
  994. // r = MSG_ReadByte (&net_message);
  995. // magnitude = MSG_ReadShort (&net_message);
  996. // color = r & 0xff;
  997. color = 0xe0;
  998. magnitude = 60;
  999. CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
  1000. S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1001. break;
  1002. case TE_STEAM:
  1003. CL_ParseSteam();
  1004. break;
  1005. case TE_BUBBLETRAIL2:
  1006. // cnt = MSG_ReadByte (&net_message);
  1007. cnt = 8;
  1008. MSG_ReadPos (&net_message, pos);
  1009. MSG_ReadPos (&net_message, pos2);
  1010. CL_BubbleTrail2 (pos, pos2, cnt);
  1011. S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1012. break;
  1013. case TE_MOREBLOOD:
  1014. MSG_ReadPos (&net_message, pos);
  1015. MSG_ReadDir (&net_message, dir);
  1016. CL_ParticleEffect (pos, dir, 0xe8, 250);
  1017. break;
  1018. case TE_CHAINFIST_SMOKE:
  1019. dir[0]=0; dir[1]=0; dir[2]=1;
  1020. MSG_ReadPos(&net_message, pos);
  1021. CL_ParticleSmokeEffect (pos, dir, 0, 20, 20);
  1022. break;
  1023. case TE_ELECTRIC_SPARKS:
  1024. MSG_ReadPos (&net_message, pos);
  1025. MSG_ReadDir (&net_message, dir);
  1026. // CL_ParticleEffect (pos, dir, 109, 40);
  1027. CL_ParticleEffect (pos, dir, 0x75, 40);
  1028. //FIXME : replace or remove this sound
  1029. S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
  1030. break;
  1031. case TE_TRACKER_EXPLOSION:
  1032. MSG_ReadPos (&net_message, pos);
  1033. CL_ColorFlash (pos, 0, 150, -1, -1, -1);
  1034. CL_ColorExplosionParticles (pos, 0, 1);
  1035. // CL_Tracker_Explode (pos);
  1036. S_StartSound (pos, 0, 0, cl_sfx_disrexp, 1, ATTN_NORM, 0);
  1037. break;
  1038. case TE_TELEPORT_EFFECT:
  1039. case TE_DBALL_GOAL:
  1040. MSG_ReadPos (&net_message, pos);
  1041. CL_TeleportParticles (pos);
  1042. break;
  1043. case TE_WIDOWBEAMOUT:
  1044. CL_ParseWidow ();
  1045. break;
  1046. case TE_NUKEBLAST:
  1047. CL_ParseNuke ();
  1048. break;
  1049. case TE_WIDOWSPLASH:
  1050. MSG_ReadPos (&net_message, pos);
  1051. CL_WidowSplash (pos);
  1052. break;
  1053. //PGM
  1054. //==============
  1055. default:
  1056. Com_Error (ERR_DROP, "CL_ParseTEnt: bad type");
  1057. }
  1058. }
  1059. /*
  1060. =================
  1061. CL_AddBeams
  1062. =================
  1063. */
  1064. void CL_AddBeams (void)
  1065. {
  1066. int i,j;
  1067. beam_t *b;
  1068. vec3_t dist, org;
  1069. float d;
  1070. entity_t ent;
  1071. float yaw, pitch;
  1072. float forward;
  1073. float len, steps;
  1074. float model_length;
  1075. // update beams
  1076. for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
  1077. {
  1078. if (!b->model || b->endtime < cl.time)
  1079. continue;
  1080. // if coming from the player, update the start position
  1081. if (b->entity == cl.playernum+1) // entity 0 is the world
  1082. {
  1083. VectorCopy (cl.refdef.vieworg, b->start);
  1084. b->start[2] -= 22; // adjust for view height
  1085. }
  1086. VectorAdd (b->start, b->offset, org);
  1087. // calculate pitch and yaw
  1088. VectorSubtract (b->end, org, dist);
  1089. if (dist[1] == 0 && dist[0] == 0)
  1090. {
  1091. yaw = 0;
  1092. if (dist[2] > 0)
  1093. pitch = 90;
  1094. else
  1095. pitch = 270;
  1096. }
  1097. else
  1098. {
  1099. // PMM - fixed to correct for pitch of 0
  1100. if (dist[0])
  1101. yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
  1102. else if (dist[1] > 0)
  1103. yaw = 90;
  1104. else
  1105. yaw = 270;
  1106. if (yaw < 0)
  1107. yaw += 360;
  1108. forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
  1109. pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
  1110. if (pitch < 0)
  1111. pitch += 360.0;
  1112. }
  1113. // add new entities for the beams
  1114. d = VectorNormalize(dist);
  1115. memset (&ent, 0, sizeof(ent));
  1116. if (b->model == cl_mod_lightning)
  1117. {
  1118. model_length = 35.0;
  1119. d-= 20.0; // correction so it doesn't end in middle of tesla
  1120. }
  1121. else
  1122. {
  1123. model_length = 30.0;
  1124. }
  1125. steps = ceil(d/model_length);
  1126. len = (d-model_length)/(steps-1);
  1127. // PMM - special case for lightning model .. if the real length is shorter than the model,
  1128. // flip it around & draw it from the end to the start. This prevents the model from going
  1129. // through the tesla mine (instead it goes through the target)
  1130. if ((b->model == cl_mod_lightning) && (d <= model_length))
  1131. {
  1132. // Com_Printf ("special case\n");
  1133. VectorCopy (b->end, ent.origin);
  1134. // offset to push beam outside of tesla model (negative because dist is from end to start
  1135. // for this beam)
  1136. // for (j=0 ; j<3 ; j++)
  1137. // ent.origin[j] -= dist[j]*10.0;
  1138. ent.model = b->model;
  1139. ent.flags = RF_FULLBRIGHT;
  1140. ent.angles[0] = pitch;
  1141. ent.angles[1] = yaw;
  1142. ent.angles[2] = rand()%360;
  1143. V_AddEntity (&ent);
  1144. return;
  1145. }
  1146. while (d > 0)
  1147. {
  1148. VectorCopy (org, ent.origin);
  1149. ent.model = b->model;
  1150. if (b->model == cl_mod_lightning)
  1151. {
  1152. ent.flags = RF_FULLBRIGHT;
  1153. ent.angles[0] = -pitch;
  1154. ent.angles[1] = yaw + 180.0;
  1155. ent.angles[2] = rand()%360;
  1156. }
  1157. else
  1158. {
  1159. ent.angles[0] = pitch;
  1160. ent.angles[1] = yaw;
  1161. ent.angles[2] = rand()%360;
  1162. }
  1163. // Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
  1164. V_AddEntity (&ent);
  1165. for (j=0 ; j<3 ; j++)
  1166. org[j] += dist[j]*len;
  1167. d -= model_length;
  1168. }
  1169. }
  1170. }
  1171. /*
  1172. // Com_Printf ("Endpoint: %f %f %f\n", b->end[0], b->end[1], b->end[2]);
  1173. // Com_Printf ("Pred View Angles: %f %f %f\n", cl.predicted_angles[0], cl.predicted_angles[1], cl.predicted_angles[2]);
  1174. // Com_Printf ("Act View Angles: %f %f %f\n", cl.refdef.viewangles[0], cl.refdef.viewangles[1], cl.refdef.viewangles[2]);
  1175. // VectorCopy (cl.predicted_origin, b->start);
  1176. // b->start[2] += 22; // adjust for view height
  1177. // if (fabs(cl.refdef.vieworg[2] - b->start[2]) >= 10) {
  1178. // b->start[2] = cl.refdef.vieworg[2];
  1179. // }
  1180. // Com_Printf ("Time: %d %d %f\n", cl.time, cls.realtime, cls.frametime);
  1181. */
  1182. extern cvar_t *hand;
  1183. /*
  1184. =================
  1185. ROGUE - draw player locked beams
  1186. CL_AddPlayerBeams
  1187. =================
  1188. */
  1189. void CL_AddPlayerBeams (void)
  1190. {
  1191. int i,j;
  1192. beam_t *b;
  1193. vec3_t dist, org;
  1194. float d;
  1195. entity_t ent;
  1196. float yaw, pitch;
  1197. float forward;
  1198. float len, steps;
  1199. int framenum;
  1200. float model_length;
  1201. float hand_multiplier;
  1202. frame_t *oldframe;
  1203. player_state_t *ps, *ops;
  1204. //PMM
  1205. if (hand)
  1206. {
  1207. if (hand->value == 2)
  1208. hand_multiplier = 0;
  1209. else if (hand->value == 1)
  1210. hand_multiplier = -1;
  1211. else
  1212. hand_multiplier = 1;
  1213. }
  1214. else
  1215. {
  1216. hand_multiplier = 1;
  1217. }
  1218. //PMM
  1219. // update beams
  1220. for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
  1221. {
  1222. vec3_t f,r,u;
  1223. if (!b->model || b->endtime < cl.time)
  1224. continue;
  1225. if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
  1226. {
  1227. // if coming from the player, update the start position
  1228. if (b->entity == cl.playernum+1) // entity 0 is the world
  1229. {
  1230. // set up gun position
  1231. // code straight out of CL_AddViewWeapon
  1232. ps = &cl.frame.playerstate;
  1233. j = (cl.frame.serverframe - 1) & UPDATE_MASK;
  1234. oldframe = &cl.frames[j];
  1235. if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
  1236. oldframe = &cl.frame; // previous frame was dropped or involid
  1237. ops = &oldframe->playerstate;
  1238. for (j=0 ; j<3 ; j++)
  1239. {
  1240. b->start[j] = cl.refdef.vieworg[j] + ops->gunoffset[j]
  1241. + cl.lerpfrac * (ps->gunoffset[j] - ops->gunoffset[j]);
  1242. }
  1243. VectorMA (b->start, (hand_multiplier * b->offset[0]), cl.v_right, org);
  1244. VectorMA ( org, b->offset[1], cl.v_forward, org);
  1245. VectorMA ( org, b->offset[2], cl.v_up, org);
  1246. if ((hand) && (hand->value == 2)) {
  1247. VectorMA (org, -1, cl.v_up, org);
  1248. }
  1249. // FIXME - take these out when final
  1250. VectorCopy (cl.v_right, r);
  1251. VectorCopy (cl.v_forward, f);
  1252. VectorCopy (cl.v_up, u);
  1253. }
  1254. else
  1255. VectorCopy (b->start, org);
  1256. }
  1257. else
  1258. {
  1259. // if coming from the player, update the start position
  1260. if (b->entity == cl.playernum+1) // entity 0 is the world
  1261. {
  1262. VectorCopy (cl.refdef.vieworg, b->start);
  1263. b->start[2] -= 22; // adjust for view height
  1264. }
  1265. VectorAdd (b->start, b->offset, org);
  1266. }
  1267. // calculate pitch and yaw
  1268. VectorSubtract (b->end, org, dist);
  1269. //PMM
  1270. if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1))
  1271. {
  1272. vec_t len;
  1273. len = VectorLength (dist);
  1274. VectorScale (f, len, dist);
  1275. VectorMA (dist, (hand_multiplier * b->offset[0]), r, dist);
  1276. VectorMA (dist, b->offset[1], f, dist);
  1277. VectorMA (dist, b->offset[2], u, dist);
  1278. if ((hand) && (hand->value == 2)) {
  1279. VectorMA (org, -1, cl.v_up, org);
  1280. }
  1281. }
  1282. //PMM
  1283. if (dist[1] == 0 && dist[0] == 0)
  1284. {
  1285. yaw = 0;
  1286. if (dist[2] > 0)
  1287. pitch = 90;
  1288. else
  1289. pitch = 270;
  1290. }
  1291. else
  1292. {
  1293. // PMM - fixed to correct for pitch of 0
  1294. if (dist[0])
  1295. yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
  1296. else if (dist[1] > 0)
  1297. yaw = 90;
  1298. else
  1299. yaw = 270;
  1300. if (yaw < 0)
  1301. yaw += 360;
  1302. forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
  1303. pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
  1304. if (pitch < 0)
  1305. pitch += 360.0;
  1306. }
  1307. if (cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
  1308. {
  1309. if (b->entity != cl.playernum+1)
  1310. {
  1311. framenum = 2;
  1312. // Com_Printf ("Third person\n");
  1313. ent.angles[0] = -pitch;
  1314. ent.angles[1] = yaw + 180.0;
  1315. ent.angles[2] = 0;
  1316. // Com_Printf ("%f %f - %f %f %f\n", -pitch, yaw+180.0, b->offset[0], b->offset[1], b->offset[2]);
  1317. AngleVectors(ent.angles, f, r, u);
  1318. // if it's a non-origin offset, it's a player, so use the hardcoded player offset
  1319. if (!VectorCompare (b->offset, vec3_origin))
  1320. {
  1321. VectorMA (org, -(b->offset[0])+1, r, org);
  1322. VectorMA (org, -(b->offset[1]), f, org);
  1323. VectorMA (org, -(b->offset[2])-10, u, org);
  1324. }
  1325. else
  1326. {
  1327. // if it's a monster, do the particle effect
  1328. CL_MonsterPlasma_Shell(b->start);
  1329. }
  1330. }
  1331. else
  1332. {
  1333. framenum = 1;
  1334. }
  1335. }
  1336. // if it's the heatbeam, draw the particle effect
  1337. if ((cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1)))
  1338. {
  1339. CL_Heatbeam (org, dist);
  1340. }
  1341. // add new entities for the beams
  1342. d = VectorNormalize(dist);
  1343. memset (&ent, 0, sizeof(ent));
  1344. if (b->model == cl_mod_heatbeam)
  1345. {
  1346. model_length = 32.0;
  1347. }
  1348. else if (b->model == cl_mod_lightning)
  1349. {
  1350. model_length = 35.0;
  1351. d-= 20.0; // correction so it doesn't end in middle of tesla
  1352. }
  1353. else
  1354. {
  1355. model_length = 30.0;
  1356. }
  1357. steps = ceil(d/model_length);
  1358. len = (d-model_length)/(steps-1);
  1359. // PMM - special case for lightning model .. if the real length is shorter than the model,
  1360. // flip it around & draw it from the end to the start. This prevents the model from going
  1361. // through the tesla mine (instead it goes through the target)
  1362. if ((b->model == cl_mod_lightning) && (d <= model_length))
  1363. {
  1364. // Com_Printf ("special case\n");
  1365. VectorCopy (b->end, ent.origin);
  1366. // offset to push beam outside of tesla model (negative because dist is from end to start
  1367. // for this beam)
  1368. // for (j=0 ; j<3 ; j++)
  1369. // ent.origin[j] -= dist[j]*10.0;
  1370. ent.model = b->model;
  1371. ent.flags = RF_FULLBRIGHT;
  1372. ent.angles[0] = pitch;
  1373. ent.angles[1] = yaw;
  1374. ent.angles[2] = rand()%360;
  1375. V_AddEntity (&ent);
  1376. return;
  1377. }
  1378. while (d > 0)
  1379. {
  1380. VectorCopy (org, ent.origin);
  1381. ent.model = b->model;
  1382. if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
  1383. {
  1384. // ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
  1385. // ent.alpha = 0.3;
  1386. ent.flags = RF_FULLBRIGHT;
  1387. ent.angles[0] = -pitch;
  1388. ent.angles[1] = yaw + 180.0;
  1389. ent.angles[2] = (cl.time) % 360;
  1390. // ent.angles[2] = rand()%360;
  1391. ent.frame = framenum;
  1392. }
  1393. else if (b->model == cl_mod_lightning)
  1394. {
  1395. ent.flags = RF_FULLBRIGHT;
  1396. ent.angles[0] = -pitch;
  1397. ent.angles[1] = yaw + 180.0;
  1398. ent.angles[2] = rand()%360;
  1399. }
  1400. else
  1401. {
  1402. ent.angles[0] = pitch;
  1403. ent.angles[1] = yaw;
  1404. ent.angles[2] = rand()%360;
  1405. }
  1406. // Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
  1407. V_AddEntity (&ent);
  1408. for (j=0 ; j<3 ; j++)
  1409. org[j] += dist[j]*len;
  1410. d -= model_length;
  1411. }
  1412. }
  1413. }
  1414. /*
  1415. =================
  1416. CL_AddExplosions
  1417. =================
  1418. */
  1419. void CL_AddExplosions (void)
  1420. {
  1421. entity_t *ent;
  1422. int i;
  1423. explosion_t *ex;
  1424. float frac;
  1425. int f;
  1426. memset (&ent, 0, sizeof(ent));
  1427. for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++)
  1428. {
  1429. if (ex->type == ex_free)
  1430. continue;
  1431. frac = (cl.time - ex->start)/100.0;
  1432. f = floor(frac);
  1433. ent = &ex->ent;
  1434. switch (ex->type)
  1435. {
  1436. case ex_mflash:
  1437. if (f >= ex->frames-1)
  1438. ex->type = ex_free;
  1439. break;
  1440. case ex_misc:
  1441. if (f >= ex->frames-1)
  1442. {
  1443. ex->type = ex_free;
  1444. break;
  1445. }
  1446. ent->alpha = 1.0 - frac/(ex->frames-1);
  1447. break;
  1448. case ex_flash:
  1449. if (f >= 1)
  1450. {
  1451. ex->type = ex_free;
  1452. break;
  1453. }
  1454. ent->alpha = 1.0;
  1455. break;
  1456. case ex_poly:
  1457. if (f >= ex->frames-1)
  1458. {
  1459. ex->type = ex_free;
  1460. break;
  1461. }
  1462. ent->alpha = (16.0 - (float)f)/16.0;
  1463. if (f < 10)
  1464. {
  1465. ent->skinnum = (f>>1);
  1466. if (ent->skinnum < 0)
  1467. ent->skinnum = 0;
  1468. }
  1469. else
  1470. {
  1471. ent->flags |= RF_TRANSLUCENT;
  1472. if (f < 13)
  1473. ent->skinnum = 5;
  1474. else
  1475. ent->skinnum = 6;
  1476. }
  1477. break;
  1478. case ex_poly2:
  1479. if (f >= ex->frames-1)
  1480. {
  1481. ex->type = ex_free;
  1482. break;
  1483. }
  1484. ent->alpha = (5.0 - (float)f)/5.0;
  1485. ent->skinnum = 0;
  1486. ent->flags |= RF_TRANSLUCENT;
  1487. break;
  1488. }
  1489. if (ex->type == ex_free)
  1490. continue;
  1491. if (ex->light)
  1492. {
  1493. V_AddLight (ent->origin, ex->light*ent->alpha,
  1494. ex->lightcolor[0], ex->lightcolor[1], ex->lightcolor[2]);
  1495. }
  1496. VectorCopy (ent->origin, ent->oldorigin);
  1497. if (f < 0)
  1498. f = 0;
  1499. ent->frame = ex->baseframe + f + 1;
  1500. ent->oldframe = ex->baseframe + f;
  1501. ent->backlerp = 1.0 - cl.lerpfrac;
  1502. V_AddEntity (ent);
  1503. }
  1504. }
  1505. /*
  1506. =================
  1507. CL_AddLasers
  1508. =================
  1509. */
  1510. void CL_AddLasers (void)
  1511. {
  1512. laser_t *l;
  1513. int i;
  1514. for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
  1515. {
  1516. if (l->endtime >= cl.time)
  1517. V_AddEntity (&l->ent);
  1518. }
  1519. }
  1520. /* PMM - CL_Sustains */
  1521. void CL_ProcessSustain ()
  1522. {
  1523. cl_sustain_t *s;
  1524. int i;
  1525. for (i=0, s=cl_sustains; i< MAX_SUSTAINS; i++, s++)
  1526. {
  1527. if (s->id)
  1528. if ((s->endtime >= cl.time) && (cl.time >= s->nextthink))
  1529. {
  1530. // Com_Printf ("think %d %d %d\n", cl.time, s->nextthink, s->thinkinterval);
  1531. s->think (s);
  1532. }
  1533. else if (s->endtime < cl.time)
  1534. s->id = 0;
  1535. }
  1536. }
  1537. /*
  1538. =================
  1539. CL_AddTEnts
  1540. =================
  1541. */
  1542. void CL_AddTEnts (void)
  1543. {
  1544. CL_AddBeams ();
  1545. // PMM - draw plasma beams
  1546. CL_AddPlayerBeams ();
  1547. CL_AddExplosions ();
  1548. CL_AddLasers ();
  1549. // PMM - set up sustain
  1550. CL_ProcessSustain();
  1551. }