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