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