|
|
1.1 ! root 1: // cl_tent.c -- client side temporary entities ! 2: ! 3: #include "client.h" ! 4: ! 5: typedef enum ! 6: { ! 7: ex_free, ex_explosion, ex_misc, ex_flash, ex_mflash, ex_poly ! 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; ! 32: struct model_s *model; ! 33: int endtime; ! 34: vec3_t offset; ! 35: vec3_t start, end; ! 36: } beam_t; ! 37: beam_t cl_beams[MAX_BEAMS]; ! 38: ! 39: ! 40: #define MAX_LASERS 32 ! 41: typedef struct ! 42: { ! 43: entity_t ent; ! 44: int endtime; ! 45: } laser_t; ! 46: laser_t cl_lasers[MAX_LASERS]; ! 47: ! 48: ! 49: void CL_BlasterParticles (vec3_t org, vec3_t dir); ! 50: void CL_ExplosionParticles (vec3_t org); ! 51: void CL_BFGExplosionParticles (vec3_t org); ! 52: ! 53: struct sfx_s *cl_sfx_ric1; ! 54: struct sfx_s *cl_sfx_ric2; ! 55: struct sfx_s *cl_sfx_ric3; ! 56: struct sfx_s *cl_sfx_lashit; ! 57: struct sfx_s *cl_sfx_spark5; ! 58: struct sfx_s *cl_sfx_spark6; ! 59: struct sfx_s *cl_sfx_spark7; ! 60: struct sfx_s *cl_sfx_railg; ! 61: struct sfx_s *cl_sfx_rockexp; ! 62: struct sfx_s *cl_sfx_grenexp; ! 63: struct sfx_s *cl_sfx_watrexp; ! 64: ! 65: struct sfx_s *cl_sfx_footsteps[4]; ! 66: ! 67: struct model_s *cl_mod_explode; ! 68: struct model_s *cl_mod_smoke; ! 69: struct model_s *cl_mod_flash; ! 70: struct model_s *cl_mod_parasite_segment; ! 71: struct model_s *cl_mod_grapple_cable; ! 72: struct model_s *cl_mod_parasite_tip; ! 73: struct model_s *cl_mod_explo4; ! 74: struct model_s *cl_mod_bfg_explo; ! 75: struct model_s *cl_mod_powerscreen; ! 76: ! 77: /* ! 78: ================= ! 79: CL_RegisterTEntSounds ! 80: ================= ! 81: */ ! 82: void CL_RegisterTEntSounds (void) ! 83: { ! 84: int i; ! 85: char name[MAX_QPATH]; ! 86: ! 87: cl_sfx_ric1 = S_RegisterSound ("world/ric1.wav"); ! 88: cl_sfx_ric2 = S_RegisterSound ("world/ric2.wav"); ! 89: cl_sfx_ric3 = S_RegisterSound ("world/ric3.wav"); ! 90: cl_sfx_lashit = S_RegisterSound("weapons/lashit.wav"); ! 91: cl_sfx_spark5 = S_RegisterSound ("world/spark5.wav"); ! 92: cl_sfx_spark6 = S_RegisterSound ("world/spark6.wav"); ! 93: cl_sfx_spark7 = S_RegisterSound ("world/spark7.wav"); ! 94: cl_sfx_railg = S_RegisterSound ("weapons/railgf1a.wav"); ! 95: cl_sfx_rockexp = S_RegisterSound ("weapons/rocklx1a.wav"); ! 96: cl_sfx_grenexp = S_RegisterSound ("weapons/grenlx1a.wav"); ! 97: cl_sfx_watrexp = S_RegisterSound ("weapons/xpld_wat.wav"); ! 98: ! 99: S_RegisterSound ("player/land1.wav"); ! 100: ! 101: S_RegisterSound ("player/fall2.wav"); ! 102: S_RegisterSound ("player/fall1.wav"); ! 103: ! 104: for (i=0 ; i<4 ; i++) ! 105: { ! 106: Com_sprintf (name, sizeof(name), "player/step%i.wav", i+1); ! 107: cl_sfx_footsteps[i] = S_RegisterSound (name); ! 108: } ! 109: } ! 110: ! 111: /* ! 112: ================= ! 113: CL_RegisterTEntModels ! 114: ================= ! 115: */ ! 116: void CL_RegisterTEntModels (void) ! 117: { ! 118: cl_mod_explode = re.RegisterModel ("models/objects/explode/tris.md2"); ! 119: cl_mod_smoke = re.RegisterModel ("models/objects/smoke/tris.md2"); ! 120: cl_mod_flash = re.RegisterModel ("models/objects/flash/tris.md2"); ! 121: cl_mod_parasite_segment = re.RegisterModel ("models/monsters/parasite/segment/tris.md2"); ! 122: cl_mod_grapple_cable = re.RegisterModel ("models/ctf/segment/tris.md2"); ! 123: cl_mod_parasite_tip = re.RegisterModel ("models/monsters/parasite/tip/tris.md2"); ! 124: cl_mod_explo4 = re.RegisterModel ("models/objects/r_explode/tris.md2"); ! 125: cl_mod_bfg_explo = re.RegisterModel ("sprites/s_bfg2.sp2"); ! 126: cl_mod_powerscreen = re.RegisterModel ("models/items/armor/effect/tris.md2"); ! 127: ! 128: re.RegisterModel ("models/objects/laser/tris.md2"); ! 129: re.RegisterModel ("models/objects/grenade2/tris.md2"); ! 130: re.RegisterModel ("models/weapons/v_machn/tris.md2"); ! 131: re.RegisterModel ("models/weapons/v_handgr/tris.md2"); ! 132: re.RegisterModel ("models/weapons/v_shotg2/tris.md2"); ! 133: re.RegisterModel ("models/objects/gibs/bone/tris.md2"); ! 134: re.RegisterModel ("models/objects/gibs/sm_meat/tris.md2"); ! 135: re.RegisterModel ("models/objects/gibs/bone2/tris.md2"); ! 136: ! 137: re.RegisterPic ("w_machinegun"); ! 138: re.RegisterPic ("a_bullets"); ! 139: re.RegisterPic ("i_health"); ! 140: re.RegisterPic ("a_grenades"); ! 141: } ! 142: ! 143: /* ! 144: ================= ! 145: CL_ClearTEnts ! 146: ================= ! 147: */ ! 148: void CL_ClearTEnts (void) ! 149: { ! 150: memset (cl_beams, 0, sizeof(cl_beams)); ! 151: memset (cl_explosions, 0, sizeof(cl_explosions)); ! 152: memset (cl_lasers, 0, sizeof(cl_lasers)); ! 153: } ! 154: ! 155: /* ! 156: ================= ! 157: CL_AllocExplosion ! 158: ================= ! 159: */ ! 160: explosion_t *CL_AllocExplosion (void) ! 161: { ! 162: int i; ! 163: int time; ! 164: int index; ! 165: ! 166: for (i=0 ; i<MAX_EXPLOSIONS ; i++) ! 167: { ! 168: if (cl_explosions[i].type == ex_free) ! 169: { ! 170: memset (&cl_explosions[i], 0, sizeof (cl_explosions[i])); ! 171: return &cl_explosions[i]; ! 172: } ! 173: } ! 174: // find the oldest explosion ! 175: time = cl.time; ! 176: index = 0; ! 177: ! 178: for (i=0 ; i<MAX_EXPLOSIONS ; i++) ! 179: if (cl_explosions[i].start < time) ! 180: { ! 181: time = cl_explosions[i].start; ! 182: index = i; ! 183: } ! 184: memset (&cl_explosions[index], 0, sizeof (cl_explosions[index])); ! 185: return &cl_explosions[index]; ! 186: } ! 187: ! 188: /* ! 189: ================= ! 190: CL_SmokeAndFlash ! 191: ================= ! 192: */ ! 193: void CL_SmokeAndFlash(vec3_t origin) ! 194: { ! 195: explosion_t *ex; ! 196: ! 197: ex = CL_AllocExplosion (); ! 198: VectorCopy (origin, ex->ent.origin); ! 199: ex->type = ex_misc; ! 200: ex->frames = 4; ! 201: ex->ent.flags = RF_TRANSLUCENT; ! 202: ex->start = cl.frame.servertime - 100; ! 203: ex->ent.model = cl_mod_smoke; ! 204: ! 205: ex = CL_AllocExplosion (); ! 206: VectorCopy (origin, ex->ent.origin); ! 207: ex->type = ex_flash; ! 208: ex->ent.flags = RF_FULLBRIGHT; ! 209: ex->frames = 2; ! 210: ex->start = cl.frame.servertime - 100; ! 211: ex->ent.model = cl_mod_flash; ! 212: } ! 213: ! 214: /* ! 215: ================= ! 216: CL_ParseParticles ! 217: ================= ! 218: */ ! 219: void CL_ParseParticles (void) ! 220: { ! 221: int color, count; ! 222: vec3_t pos, dir; ! 223: ! 224: MSG_ReadPos (&net_message, pos); ! 225: MSG_ReadDir (&net_message, dir); ! 226: ! 227: color = MSG_ReadByte (&net_message); ! 228: ! 229: count = MSG_ReadByte (&net_message); ! 230: ! 231: CL_ParticleEffect (pos, dir, color, count); ! 232: } ! 233: ! 234: /* ! 235: ================= ! 236: CL_ParseBeam ! 237: ================= ! 238: */ ! 239: int CL_ParseBeam (struct model_s *model) ! 240: { ! 241: int ent; ! 242: vec3_t start, end; ! 243: beam_t *b; ! 244: int i; ! 245: ! 246: ent = MSG_ReadShort (&net_message); ! 247: ! 248: MSG_ReadPos (&net_message, start); ! 249: MSG_ReadPos (&net_message, end); ! 250: ! 251: // override any beam with the same entity ! 252: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) ! 253: if (b->entity == ent) ! 254: { ! 255: b->entity = ent; ! 256: b->model = model; ! 257: b->endtime = cl.time + 200; ! 258: VectorCopy (start, b->start); ! 259: VectorCopy (end, b->end); ! 260: VectorClear (b->offset); ! 261: return ent; ! 262: } ! 263: ! 264: // find a free beam ! 265: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) ! 266: { ! 267: if (!b->model || b->endtime < cl.time) ! 268: { ! 269: b->entity = ent; ! 270: b->model = model; ! 271: b->endtime = cl.time + 200; ! 272: VectorCopy (start, b->start); ! 273: VectorCopy (end, b->end); ! 274: VectorClear (b->offset); ! 275: return ent; ! 276: } ! 277: } ! 278: Com_Printf ("beam list overflow!\n"); ! 279: return ent; ! 280: } ! 281: ! 282: /* ! 283: ================= ! 284: CL_ParseBeam2 ! 285: ================= ! 286: */ ! 287: int CL_ParseBeam2 (struct model_s *model) ! 288: { ! 289: int ent; ! 290: vec3_t start, end, offset; ! 291: beam_t *b; ! 292: int i; ! 293: ! 294: ent = MSG_ReadShort (&net_message); ! 295: ! 296: MSG_ReadPos (&net_message, start); ! 297: MSG_ReadPos (&net_message, end); ! 298: MSG_ReadPos (&net_message, offset); ! 299: ! 300: // override any beam with the same entity ! 301: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) ! 302: if (b->entity == ent) ! 303: { ! 304: b->entity = ent; ! 305: b->model = model; ! 306: b->endtime = cl.time + 200; ! 307: VectorCopy (start, b->start); ! 308: VectorCopy (end, b->end); ! 309: VectorCopy (offset, b->offset); ! 310: return ent; ! 311: } ! 312: ! 313: // find a free beam ! 314: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) ! 315: { ! 316: if (!b->model || b->endtime < cl.time) ! 317: { ! 318: b->entity = ent; ! 319: b->model = model; ! 320: b->endtime = cl.time + 200; ! 321: VectorCopy (start, b->start); ! 322: VectorCopy (end, b->end); ! 323: VectorCopy (offset, b->offset); ! 324: return ent; ! 325: } ! 326: } ! 327: Com_Printf ("beam list overflow!\n"); ! 328: return ent; ! 329: } ! 330: ! 331: /* ! 332: ================= ! 333: CL_ParseLaser ! 334: ================= ! 335: */ ! 336: void CL_ParseLaser (int colors) ! 337: { ! 338: vec3_t start; ! 339: vec3_t end; ! 340: laser_t *l; ! 341: int i; ! 342: ! 343: MSG_ReadPos (&net_message, start); ! 344: MSG_ReadPos (&net_message, end); ! 345: ! 346: for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++) ! 347: { ! 348: if (l->endtime < cl.time) ! 349: { ! 350: l->ent.flags = RF_TRANSLUCENT | RF_BEAM; ! 351: VectorCopy (start, l->ent.origin); ! 352: VectorCopy (end, l->ent.oldorigin); ! 353: l->ent.alpha = 0.30; ! 354: l->ent.skinnum = (colors >> ((rand() % 4)*8)) & 0xff; ! 355: l->ent.model = NULL; ! 356: l->ent.frame = 4; ! 357: l->endtime = cl.time + 100; ! 358: return; ! 359: } ! 360: } ! 361: } ! 362: ! 363: ! 364: /* ! 365: ================= ! 366: CL_ParseTEnt ! 367: ================= ! 368: */ ! 369: static byte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8}; ! 370: ! 371: void CL_ParseTEnt (void) ! 372: { ! 373: int type; ! 374: vec3_t pos, pos2, dir; ! 375: explosion_t *ex; ! 376: int cnt; ! 377: int color; ! 378: int r; ! 379: int ent; ! 380: ! 381: type = MSG_ReadByte (&net_message); ! 382: ! 383: switch (type) ! 384: { ! 385: case TE_BLOOD: // bullet hitting flesh ! 386: MSG_ReadPos (&net_message, pos); ! 387: MSG_ReadDir (&net_message, dir); ! 388: CL_ParticleEffect (pos, dir, 0xe8, 60); ! 389: break; ! 390: ! 391: case TE_GUNSHOT: // bullet hitting wall ! 392: case TE_SPARKS: ! 393: case TE_BULLET_SPARKS: ! 394: MSG_ReadPos (&net_message, pos); ! 395: MSG_ReadDir (&net_message, dir); ! 396: if (type == TE_GUNSHOT) ! 397: CL_ParticleEffect (pos, dir, 0, 40); ! 398: else ! 399: CL_ParticleEffect (pos, dir, 0xe0, 6); ! 400: ! 401: if (type != TE_SPARKS) ! 402: { ! 403: CL_SmokeAndFlash(pos); ! 404: ! 405: // impact sound ! 406: cnt = rand()&15; ! 407: if (cnt == 1) ! 408: S_StartSound (pos, 0, 0, cl_sfx_ric1, 1, ATTN_NORM, 0); ! 409: else if (cnt == 2) ! 410: S_StartSound (pos, 0, 0, cl_sfx_ric2, 1, ATTN_NORM, 0); ! 411: else if (cnt == 3) ! 412: S_StartSound (pos, 0, 0, cl_sfx_ric3, 1, ATTN_NORM, 0); ! 413: } ! 414: ! 415: break; ! 416: ! 417: case TE_SCREEN_SPARKS: ! 418: case TE_SHIELD_SPARKS: ! 419: MSG_ReadPos (&net_message, pos); ! 420: MSG_ReadDir (&net_message, dir); ! 421: if (type == TE_SCREEN_SPARKS) ! 422: CL_ParticleEffect (pos, dir, 0xd0, 40); ! 423: else ! 424: CL_ParticleEffect (pos, dir, 0xb0, 40); ! 425: //FIXME : replace or remove this sound ! 426: S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); ! 427: break; ! 428: ! 429: case TE_SHOTGUN: // bullet hitting wall ! 430: MSG_ReadPos (&net_message, pos); ! 431: MSG_ReadDir (&net_message, dir); ! 432: CL_ParticleEffect (pos, dir, 0, 20); ! 433: CL_SmokeAndFlash(pos); ! 434: break; ! 435: ! 436: case TE_SPLASH: // bullet hitting water ! 437: cnt = MSG_ReadByte (&net_message); ! 438: MSG_ReadPos (&net_message, pos); ! 439: MSG_ReadDir (&net_message, dir); ! 440: r = MSG_ReadByte (&net_message); ! 441: if (r > 6) ! 442: color = 0x00; ! 443: else ! 444: color = splash_color[r]; ! 445: CL_ParticleEffect (pos, dir, color, cnt); ! 446: ! 447: if (r == SPLASH_SPARKS) ! 448: { ! 449: r = rand() & 3; ! 450: if (r == 0) ! 451: S_StartSound (pos, 0, 0, cl_sfx_spark5, 1, ATTN_STATIC, 0); ! 452: else if (r == 1) ! 453: S_StartSound (pos, 0, 0, cl_sfx_spark6, 1, ATTN_STATIC, 0); ! 454: else ! 455: S_StartSound (pos, 0, 0, cl_sfx_spark7, 1, ATTN_STATIC, 0); ! 456: } ! 457: break; ! 458: ! 459: case TE_LASER_SPARKS: ! 460: cnt = MSG_ReadByte (&net_message); ! 461: MSG_ReadPos (&net_message, pos); ! 462: MSG_ReadDir (&net_message, dir); ! 463: color = MSG_ReadByte (&net_message); ! 464: CL_ParticleEffect2 (pos, dir, color, cnt); ! 465: break; ! 466: ! 467: case TE_BLASTER: // blaster hitting wall ! 468: MSG_ReadPos (&net_message, pos); ! 469: MSG_ReadDir (&net_message, dir); ! 470: CL_BlasterParticles (pos, dir); ! 471: ! 472: ex = CL_AllocExplosion (); ! 473: VectorCopy (pos, ex->ent.origin); ! 474: ex->ent.angles[0] = acos(dir[2])/M_PI*180; ! 475: ex->ent.angles[2] = atan2(dir[1], dir[0])/M_PI*180; ! 476: ex->type = ex_misc; ! 477: ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT; ! 478: ex->start = cl.frame.servertime - 100; ! 479: ex->light = 150; ! 480: ex->lightcolor[0] = 1; ! 481: ex->lightcolor[1] = 1; ! 482: ex->ent.model = cl_mod_explode; ! 483: ex->frames = 4; ! 484: S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0); ! 485: break; ! 486: ! 487: case TE_RAILTRAIL: // railgun effect ! 488: MSG_ReadPos (&net_message, pos); ! 489: MSG_ReadPos (&net_message, pos2); ! 490: CL_RailTrail (pos, pos2); ! 491: S_StartSound (pos2, 0, 0, cl_sfx_railg, 1, ATTN_NORM, 0); ! 492: break; ! 493: ! 494: case TE_PLASMATRAIL: ! 495: MSG_ReadPos (&net_message, pos); ! 496: MSG_ReadPos (&net_message, pos2); ! 497: CL_PlasmaTrail (pos, pos2); ! 498: S_StartSound (pos2, 0, 0, cl_sfx_railg, 1, ATTN_NORM, 0); ! 499: break; ! 500: ! 501: case TE_EXPLOSION2: ! 502: case TE_GRENADE_EXPLOSION: ! 503: case TE_GRENADE_EXPLOSION_WATER: ! 504: MSG_ReadPos (&net_message, pos); ! 505: ! 506: ex = CL_AllocExplosion (); ! 507: VectorCopy (pos, ex->ent.origin); ! 508: ex->type = ex_poly; ! 509: ex->ent.flags = RF_FULLBRIGHT; ! 510: ex->start = cl.frame.servertime - 100; ! 511: ex->light = 350; ! 512: ex->lightcolor[0] = 1.0; ! 513: ex->lightcolor[1] = 0.5; ! 514: ex->lightcolor[2] = 0.5; ! 515: ex->ent.model = cl_mod_explo4; ! 516: ex->frames = 19; ! 517: ex->baseframe = 30; ! 518: ex->ent.angles[1] = rand() % 360; ! 519: CL_ExplosionParticles (pos); ! 520: if (type == TE_GRENADE_EXPLOSION_WATER) ! 521: S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0); ! 522: else ! 523: S_StartSound (pos, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0); ! 524: break; ! 525: ! 526: case TE_EXPLOSION1: ! 527: case TE_ROCKET_EXPLOSION: ! 528: case TE_ROCKET_EXPLOSION_WATER: ! 529: MSG_ReadPos (&net_message, pos); ! 530: ! 531: ex = CL_AllocExplosion (); ! 532: VectorCopy (pos, ex->ent.origin); ! 533: ex->type = ex_poly; ! 534: ex->ent.flags = RF_FULLBRIGHT; ! 535: ex->start = cl.frame.servertime - 100; ! 536: ex->light = 350; ! 537: ex->lightcolor[0] = 1.0; ! 538: ex->lightcolor[1] = 0.5; ! 539: ex->lightcolor[2] = 0.5; ! 540: ex->ent.angles[1] = rand() % 360; ! 541: ex->ent.model = cl_mod_explo4; ! 542: if (frand() < 0.5) ! 543: ex->baseframe = 15; ! 544: ex->frames = 15; ! 545: CL_ExplosionParticles (pos); ! 546: if (type == TE_ROCKET_EXPLOSION_WATER) ! 547: S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0); ! 548: else ! 549: S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0); ! 550: break; ! 551: ! 552: case TE_BFG_EXPLOSION: ! 553: MSG_ReadPos (&net_message, pos); ! 554: ex = CL_AllocExplosion (); ! 555: VectorCopy (pos, ex->ent.origin); ! 556: ex->type = ex_poly; ! 557: ex->ent.flags = RF_FULLBRIGHT; ! 558: ex->start = cl.frame.servertime - 100; ! 559: ex->light = 350; ! 560: ex->lightcolor[0] = 0.0; ! 561: ex->lightcolor[1] = 1.0; ! 562: ex->lightcolor[2] = 0.0; ! 563: ex->ent.model = cl_mod_bfg_explo; ! 564: ex->ent.flags |= RF_TRANSLUCENT; ! 565: ex->ent.alpha = 0.30; ! 566: ex->frames = 4; ! 567: break; ! 568: ! 569: case TE_BFG_BIGEXPLOSION: ! 570: MSG_ReadPos (&net_message, pos); ! 571: CL_BFGExplosionParticles (pos); ! 572: break; ! 573: ! 574: case TE_BFG_LASER: ! 575: CL_ParseLaser (0xd0d1d2d3); ! 576: break; ! 577: ! 578: case TE_BUBBLETRAIL: ! 579: MSG_ReadPos (&net_message, pos); ! 580: MSG_ReadPos (&net_message, pos2); ! 581: CL_BubbleTrail (pos, pos2); ! 582: break; ! 583: ! 584: case TE_PARASITE_ATTACK: ! 585: case TE_MEDIC_CABLE_ATTACK: ! 586: ent = CL_ParseBeam (cl_mod_parasite_segment); ! 587: break; ! 588: ! 589: case TE_BOSSTPORT: // boss teleporting to station ! 590: MSG_ReadPos (&net_message, pos); ! 591: CL_BigTeleportParticles (pos); ! 592: S_StartSound (pos, 0, 0, S_RegisterSound ("misc/bigtele.wav"), 1, ATTN_NONE, 0); ! 593: break; ! 594: ! 595: case TE_GRAPPLE_CABLE: ! 596: ent = CL_ParseBeam2 (cl_mod_grapple_cable); ! 597: break; ! 598: ! 599: case TE_WELDING_SPARKS: ! 600: cnt = MSG_ReadByte (&net_message); ! 601: MSG_ReadPos (&net_message, pos); ! 602: MSG_ReadDir (&net_message, dir); ! 603: color = MSG_ReadByte (&net_message); ! 604: CL_ParticleEffect2 (pos, dir, color, cnt); ! 605: ! 606: ex = CL_AllocExplosion (); ! 607: VectorCopy (pos, ex->ent.origin); ! 608: ex->type = ex_flash; ! 609: // note to self ! 610: // we need a better no draw flag ! 611: ex->ent.flags = RF_BEAM; ! 612: ex->start = cl.frame.servertime - 0.1; ! 613: ex->light = 100 + (rand()%75); ! 614: ex->lightcolor[0] = 1.0; ! 615: ex->lightcolor[1] = 1.0; ! 616: ex->lightcolor[2] = 0.3; ! 617: ex->ent.model = cl_mod_flash; ! 618: ex->frames = 2; ! 619: break; ! 620: ! 621: case TE_GREENBLOOD: ! 622: MSG_ReadPos (&net_message, pos); ! 623: MSG_ReadDir (&net_message, dir); ! 624: CL_ParticleEffect2 (pos, dir, 0xc0, 30); ! 625: break; ! 626: ! 627: default: ! 628: Com_Error (ERR_DROP, "CL_ParseTEnt: bad type"); ! 629: } ! 630: } ! 631: ! 632: /* ! 633: ================= ! 634: CL_AddBeams ! 635: ================= ! 636: */ ! 637: void CL_AddBeams (void) ! 638: { ! 639: int i,j; ! 640: beam_t *b; ! 641: vec3_t dist, org; ! 642: float d; ! 643: entity_t ent; ! 644: float yaw, pitch; ! 645: float forward; ! 646: ! 647: // update beams ! 648: for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) ! 649: { ! 650: if (!b->model || b->endtime < cl.time) ! 651: continue; ! 652: ! 653: // if coming from the player, update the start position ! 654: if (b->entity == cl.playernum+1) // entity 0 is the world ! 655: { ! 656: VectorCopy (cl.refdef.vieworg, b->start); ! 657: b->start[2] -= 22; // adjust for view height ! 658: } ! 659: ! 660: VectorAdd (b->start, b->offset, org); ! 661: ! 662: // calculate pitch and yaw ! 663: VectorSubtract (b->end, org, dist); ! 664: ! 665: if (dist[1] == 0 && dist[0] == 0) ! 666: { ! 667: yaw = 0; ! 668: if (dist[2] > 0) ! 669: pitch = 90; ! 670: else ! 671: pitch = 270; ! 672: } ! 673: else ! 674: { ! 675: yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI); ! 676: if (yaw < 0) ! 677: yaw += 360; ! 678: ! 679: forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]); ! 680: pitch = (int) (atan2(dist[2], forward) * -180 / M_PI); ! 681: if (pitch < 0) ! 682: pitch += 360; ! 683: } ! 684: ! 685: // add new entities for the beams ! 686: d = VectorNormalize(dist); ! 687: memset (&ent, 0, sizeof(ent)); ! 688: while (d > 0) ! 689: { ! 690: VectorCopy (org, ent.origin); ! 691: ent.model = b->model; ! 692: ent.angles[0] = pitch; ! 693: ent.angles[1] = yaw; ! 694: ent.angles[2] = rand()%360; ! 695: ! 696: V_AddEntity (&ent); ! 697: ! 698: for (j=0 ; j<3 ; j++) ! 699: org[j] += dist[j]*30; ! 700: d -= 30; ! 701: } ! 702: } ! 703: ! 704: } ! 705: ! 706: /* ! 707: ================= ! 708: CL_AddExplosions ! 709: ================= ! 710: */ ! 711: void CL_AddExplosions (void) ! 712: { ! 713: entity_t *ent; ! 714: int i; ! 715: explosion_t *ex; ! 716: float frac; ! 717: int f; ! 718: ! 719: memset (&ent, 0, sizeof(ent)); ! 720: ! 721: for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++) ! 722: { ! 723: if (ex->type == ex_free) ! 724: continue; ! 725: frac = (cl.time - ex->start)/100.0; ! 726: f = floor(frac); ! 727: ! 728: ent = &ex->ent; ! 729: ! 730: switch (ex->type) ! 731: { ! 732: case ex_mflash: ! 733: if (f >= ex->frames-1) ! 734: ex->type = ex_free; ! 735: break; ! 736: case ex_misc: ! 737: if (f >= ex->frames-1) ! 738: { ! 739: ex->type = ex_free; ! 740: break; ! 741: } ! 742: ent->alpha = 1.0 - frac/(ex->frames-1); ! 743: break; ! 744: case ex_flash: ! 745: if (f >= 1) ! 746: { ! 747: ex->type = ex_free; ! 748: break; ! 749: } ! 750: ent->alpha = 1.0; ! 751: break; ! 752: case ex_poly: ! 753: if (f >= ex->frames-1) ! 754: { ! 755: ex->type = ex_free; ! 756: break; ! 757: } ! 758: ! 759: ent->alpha = (16.0 - (float)f)/16.0; ! 760: ! 761: if (f < 10) ! 762: { ! 763: ent->skinnum = (f>>1); ! 764: if (ent->skinnum < 0) ! 765: ent->skinnum = 0; ! 766: } ! 767: else ! 768: { ! 769: ent->flags |= RF_TRANSLUCENT; ! 770: if (f < 13) ! 771: ent->skinnum = 5; ! 772: else ! 773: ent->skinnum = 6; ! 774: } ! 775: break; ! 776: } ! 777: ! 778: if (ex->type == ex_free) ! 779: continue; ! 780: if (ex->light) ! 781: { ! 782: V_AddLight (ent->origin, ex->light*ent->alpha, ! 783: ex->lightcolor[0], ex->lightcolor[1], ex->lightcolor[2]); ! 784: } ! 785: ! 786: VectorCopy (ent->origin, ent->oldorigin); ! 787: ! 788: if (f < 0) ! 789: f = 0; ! 790: ent->frame = ex->baseframe + f + 1; ! 791: ent->oldframe = ex->baseframe + f; ! 792: ent->backlerp = 1.0 - cl.lerpfrac; ! 793: ! 794: V_AddEntity (ent); ! 795: } ! 796: } ! 797: ! 798: ! 799: /* ! 800: ================= ! 801: CL_AddLasers ! 802: ================= ! 803: */ ! 804: void CL_AddLasers (void) ! 805: { ! 806: laser_t *l; ! 807: int i; ! 808: ! 809: for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++) ! 810: { ! 811: if (l->endtime >= cl.time) ! 812: V_AddEntity (&l->ent); ! 813: } ! 814: } ! 815: ! 816: ! 817: /* ! 818: ================= ! 819: CL_AddTEnts ! 820: ================= ! 821: */ ! 822: void CL_AddTEnts (void) ! 823: { ! 824: CL_AddBeams (); ! 825: CL_AddExplosions (); ! 826: CL_AddLasers (); ! 827: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.