00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "cg_local.h"
00025
00026
00027
00028
00029
00030
00031 static void CG_MachineGunEjectBrass( centity_t *cent ) {
00032 localEntity_t *le;
00033 refEntity_t *re;
00034 vec3_t velocity, xvelocity;
00035 vec3_t offset, xoffset;
00036 float waterScale = 1.0f;
00037 vec3_t v[3];
00038
00039 if ( cg_brassTime.integer <= 0 ) {
00040 return;
00041 }
00042
00043 le = CG_AllocLocalEntity();
00044 re = &le->refEntity;
00045
00046 velocity[0] = 0;
00047 velocity[1] = -50 + 40 * crandom();
00048 velocity[2] = 100 + 50 * crandom();
00049
00050 le->leType = LE_FRAGMENT;
00051 le->startTime = cg.time;
00052 le->endTime = le->startTime + cg_brassTime.integer + ( cg_brassTime.integer / 4 ) * random();
00053
00054 le->pos.trType = TR_GRAVITY;
00055 le->pos.trTime = cg.time - (rand()&15);
00056
00057 AnglesToAxis( cent->lerpAngles, v );
00058
00059 offset[0] = 8;
00060 offset[1] = -4;
00061 offset[2] = 24;
00062
00063 xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
00064 xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
00065 xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
00066 VectorAdd( cent->lerpOrigin, xoffset, re->origin );
00067
00068 VectorCopy( re->origin, le->pos.trBase );
00069
00070 if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
00071 waterScale = 0.10f;
00072 }
00073
00074 xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
00075 xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
00076 xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
00077 VectorScale( xvelocity, waterScale, le->pos.trDelta );
00078
00079 AxisCopy( axisDefault, re->axis );
00080 re->hModel = cgs.media.machinegunBrassModel;
00081
00082 le->bounceFactor = 0.4 * waterScale;
00083
00084 le->angles.trType = TR_LINEAR;
00085 le->angles.trTime = cg.time;
00086 le->angles.trBase[0] = rand()&31;
00087 le->angles.trBase[1] = rand()&31;
00088 le->angles.trBase[2] = rand()&31;
00089 le->angles.trDelta[0] = 2;
00090 le->angles.trDelta[1] = 1;
00091 le->angles.trDelta[2] = 0;
00092
00093 le->leFlags = LEF_TUMBLE;
00094 le->leBounceSoundType = LEBS_BRASS;
00095 le->leMarkType = LEMT_NONE;
00096 }
00097
00098
00099
00100
00101
00102
00103 static void CG_ShotgunEjectBrass( centity_t *cent ) {
00104 localEntity_t *le;
00105 refEntity_t *re;
00106 vec3_t velocity, xvelocity;
00107 vec3_t offset, xoffset;
00108 vec3_t v[3];
00109 int i;
00110
00111 if ( cg_brassTime.integer <= 0 ) {
00112 return;
00113 }
00114
00115 for ( i = 0; i < 2; i++ ) {
00116 float waterScale = 1.0f;
00117
00118 le = CG_AllocLocalEntity();
00119 re = &le->refEntity;
00120
00121 velocity[0] = 60 + 60 * crandom();
00122 if ( i == 0 ) {
00123 velocity[1] = 40 + 10 * crandom();
00124 } else {
00125 velocity[1] = -40 + 10 * crandom();
00126 }
00127 velocity[2] = 100 + 50 * crandom();
00128
00129 le->leType = LE_FRAGMENT;
00130 le->startTime = cg.time;
00131 le->endTime = le->startTime + cg_brassTime.integer*3 + cg_brassTime.integer * random();
00132
00133 le->pos.trType = TR_GRAVITY;
00134 le->pos.trTime = cg.time;
00135
00136 AnglesToAxis( cent->lerpAngles, v );
00137
00138 offset[0] = 8;
00139 offset[1] = 0;
00140 offset[2] = 24;
00141
00142 xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
00143 xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
00144 xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
00145 VectorAdd( cent->lerpOrigin, xoffset, re->origin );
00146 VectorCopy( re->origin, le->pos.trBase );
00147 if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
00148 waterScale = 0.10f;
00149 }
00150
00151 xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
00152 xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
00153 xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
00154 VectorScale( xvelocity, waterScale, le->pos.trDelta );
00155
00156 AxisCopy( axisDefault, re->axis );
00157 re->hModel = cgs.media.shotgunBrassModel;
00158 le->bounceFactor = 0.3f;
00159
00160 le->angles.trType = TR_LINEAR;
00161 le->angles.trTime = cg.time;
00162 le->angles.trBase[0] = rand()&31;
00163 le->angles.trBase[1] = rand()&31;
00164 le->angles.trBase[2] = rand()&31;
00165 le->angles.trDelta[0] = 1;
00166 le->angles.trDelta[1] = 0.5;
00167 le->angles.trDelta[2] = 0;
00168
00169 le->leFlags = LEF_TUMBLE;
00170 le->leBounceSoundType = LEBS_BRASS;
00171 le->leMarkType = LEMT_NONE;
00172 }
00173 }
00174
00175
00176 #ifdef MISSIONPACK
00177
00178
00179
00180
00181
00182 static void CG_NailgunEjectBrass( centity_t *cent ) {
00183 localEntity_t *smoke;
00184 vec3_t origin;
00185 vec3_t v[3];
00186 vec3_t offset;
00187 vec3_t xoffset;
00188 vec3_t up;
00189
00190 AnglesToAxis( cent->lerpAngles, v );
00191
00192 offset[0] = 0;
00193 offset[1] = -12;
00194 offset[2] = 24;
00195
00196 xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
00197 xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
00198 xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
00199 VectorAdd( cent->lerpOrigin, xoffset, origin );
00200
00201 VectorSet( up, 0, 0, 64 );
00202
00203 smoke = CG_SmokePuff( origin, up, 32, 1, 1, 1, 0.33f, 700, cg.time, 0, 0, cgs.media.smokePuffShader );
00204
00205 smoke->leType = LE_SCALE_FADE;
00206 }
00207 #endif
00208
00209
00210
00211
00212
00213
00214
00215 void CG_RailTrail (clientInfo_t *ci, vec3_t start, vec3_t end) {
00216 vec3_t axis[36], move, move2, next_move, vec, temp;
00217 float len;
00218 int i, j, skip;
00219
00220 localEntity_t *le;
00221 refEntity_t *re;
00222
00223 #define RADIUS 4
00224 #define ROTATION 1
00225 #define SPACING 5
00226
00227 start[2] -= 4;
00228 VectorCopy (start, move);
00229 VectorSubtract (end, start, vec);
00230 len = VectorNormalize (vec);
00231 PerpendicularVector(temp, vec);
00232 for (i = 0 ; i < 36; i++) {
00233 RotatePointAroundVector(axis[i], vec, temp, i * 10);
00234 }
00235
00236 le = CG_AllocLocalEntity();
00237 re = &le->refEntity;
00238
00239 le->leType = LE_FADE_RGB;
00240 le->startTime = cg.time;
00241 le->endTime = cg.time + cg_railTrailTime.value;
00242 le->lifeRate = 1.0 / (le->endTime - le->startTime);
00243
00244 re->shaderTime = cg.time / 1000.0f;
00245 re->reType = RT_RAIL_CORE;
00246 re->customShader = cgs.media.railCoreShader;
00247
00248 VectorCopy(start, re->origin);
00249 VectorCopy(end, re->oldorigin);
00250
00251 re->shaderRGBA[0] = ci->color1[0] * 255;
00252 re->shaderRGBA[1] = ci->color1[1] * 255;
00253 re->shaderRGBA[2] = ci->color1[2] * 255;
00254 re->shaderRGBA[3] = 255;
00255
00256 le->color[0] = ci->color1[0] * 0.75;
00257 le->color[1] = ci->color1[1] * 0.75;
00258 le->color[2] = ci->color1[2] * 0.75;
00259 le->color[3] = 1.0f;
00260
00261 AxisClear( re->axis );
00262
00263 VectorMA(move, 20, vec, move);
00264 VectorCopy(move, next_move);
00265 VectorScale (vec, SPACING, vec);
00266
00267 if (cg_oldRail.integer != 0) {
00268
00269 re->origin[2] -= 8;
00270 re->oldorigin[2] -= 8;
00271 return;
00272 }
00273 skip = -1;
00274
00275 j = 18;
00276 for (i = 0; i < len; i += SPACING) {
00277 if (i != skip) {
00278 skip = i + SPACING;
00279 le = CG_AllocLocalEntity();
00280 re = &le->refEntity;
00281 le->leFlags = LEF_PUFF_DONT_SCALE;
00282 le->leType = LE_MOVE_SCALE_FADE;
00283 le->startTime = cg.time;
00284 le->endTime = cg.time + (i>>1) + 600;
00285 le->lifeRate = 1.0 / (le->endTime - le->startTime);
00286
00287 re->shaderTime = cg.time / 1000.0f;
00288 re->reType = RT_SPRITE;
00289 re->radius = 1.1f;
00290 re->customShader = cgs.media.railRingsShader;
00291
00292 re->shaderRGBA[0] = ci->color2[0] * 255;
00293 re->shaderRGBA[1] = ci->color2[1] * 255;
00294 re->shaderRGBA[2] = ci->color2[2] * 255;
00295 re->shaderRGBA[3] = 255;
00296
00297 le->color[0] = ci->color2[0] * 0.75;
00298 le->color[1] = ci->color2[1] * 0.75;
00299 le->color[2] = ci->color2[2] * 0.75;
00300 le->color[3] = 1.0f;
00301
00302 le->pos.trType = TR_LINEAR;
00303 le->pos.trTime = cg.time;
00304
00305 VectorCopy( move, move2);
00306 VectorMA(move2, RADIUS , axis[j], move2);
00307 VectorCopy(move2, le->pos.trBase);
00308
00309 le->pos.trDelta[0] = axis[j][0]*6;
00310 le->pos.trDelta[1] = axis[j][1]*6;
00311 le->pos.trDelta[2] = axis[j][2]*6;
00312 }
00313
00314 VectorAdd (move, vec, move);
00315
00316 j = j + ROTATION < 36 ? j + ROTATION : (j + ROTATION) % 36;
00317 }
00318 }
00319
00320
00321
00322
00323
00324
00325 static void CG_RocketTrail( centity_t *ent, const weaponInfo_t *wi ) {
00326 int step;
00327 vec3_t origin, lastPos;
00328 int t;
00329 int startTime, contents;
00330 int lastContents;
00331 entityState_t *es;
00332 vec3_t up;
00333 localEntity_t *smoke;
00334
00335 if ( cg_noProjectileTrail.integer ) {
00336 return;
00337 }
00338
00339 up[0] = 0;
00340 up[1] = 0;
00341 up[2] = 0;
00342
00343 step = 50;
00344
00345 es = &ent->currentState;
00346 startTime = ent->trailTime;
00347 t = step * ( (startTime + step) / step );
00348
00349 BG_EvaluateTrajectory( &es->pos, cg.time, origin );
00350 contents = CG_PointContents( origin, -1 );
00351
00352
00353 if ( es->pos.trType == TR_STATIONARY ) {
00354 ent->trailTime = cg.time;
00355 return;
00356 }
00357
00358 BG_EvaluateTrajectory( &es->pos, ent->trailTime, lastPos );
00359 lastContents = CG_PointContents( lastPos, -1 );
00360
00361 ent->trailTime = cg.time;
00362
00363 if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) {
00364 if ( contents & lastContents & CONTENTS_WATER ) {
00365 CG_BubbleTrail( lastPos, origin, 8 );
00366 }
00367 return;
00368 }
00369
00370 for ( ; t <= ent->trailTime ; t += step ) {
00371 BG_EvaluateTrajectory( &es->pos, t, lastPos );
00372
00373 smoke = CG_SmokePuff( lastPos, up,
00374 wi->trailRadius,
00375 1, 1, 1, 0.33f,
00376 wi->wiTrailTime,
00377 t,
00378 0,
00379 0,
00380 cgs.media.smokePuffShader );
00381
00382 smoke->leType = LE_SCALE_FADE;
00383 }
00384
00385 }
00386
00387 #ifdef MISSIONPACK
00388
00389
00390
00391
00392
00393 static void CG_NailTrail( centity_t *ent, const weaponInfo_t *wi ) {
00394 int step;
00395 vec3_t origin, lastPos;
00396 int t;
00397 int startTime, contents;
00398 int lastContents;
00399 entityState_t *es;
00400 vec3_t up;
00401 localEntity_t *smoke;
00402
00403 if ( cg_noProjectileTrail.integer ) {
00404 return;
00405 }
00406
00407 up[0] = 0;
00408 up[1] = 0;
00409 up[2] = 0;
00410
00411 step = 50;
00412
00413 es = &ent->currentState;
00414 startTime = ent->trailTime;
00415 t = step * ( (startTime + step) / step );
00416
00417 BG_EvaluateTrajectory( &es->pos, cg.time, origin );
00418 contents = CG_PointContents( origin, -1 );
00419
00420
00421 if ( es->pos.trType == TR_STATIONARY ) {
00422 ent->trailTime = cg.time;
00423 return;
00424 }
00425
00426 BG_EvaluateTrajectory( &es->pos, ent->trailTime, lastPos );
00427 lastContents = CG_PointContents( lastPos, -1 );
00428
00429 ent->trailTime = cg.time;
00430
00431 if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) {
00432 if ( contents & lastContents & CONTENTS_WATER ) {
00433 CG_BubbleTrail( lastPos, origin, 8 );
00434 }
00435 return;
00436 }
00437
00438 for ( ; t <= ent->trailTime ; t += step ) {
00439 BG_EvaluateTrajectory( &es->pos, t, lastPos );
00440
00441 smoke = CG_SmokePuff( lastPos, up,
00442 wi->trailRadius,
00443 1, 1, 1, 0.33f,
00444 wi->wiTrailTime,
00445 t,
00446 0,
00447 0,
00448 cgs.media.nailPuffShader );
00449
00450 smoke->leType = LE_SCALE_FADE;
00451 }
00452
00453 }
00454 #endif
00455
00456
00457
00458
00459
00460
00461 static void CG_PlasmaTrail( centity_t *cent, const weaponInfo_t *wi ) {
00462 localEntity_t *le;
00463 refEntity_t *re;
00464 entityState_t *es;
00465 vec3_t velocity, xvelocity, origin;
00466 vec3_t offset, xoffset;
00467 vec3_t v[3];
00468 int t, startTime, step;
00469
00470 float waterScale = 1.0f;
00471
00472 if ( cg_noProjectileTrail.integer || cg_oldPlasma.integer ) {
00473 return;
00474 }
00475
00476 step = 50;
00477
00478 es = ¢->currentState;
00479 startTime = cent->trailTime;
00480 t = step * ( (startTime + step) / step );
00481
00482 BG_EvaluateTrajectory( &es->pos, cg.time, origin );
00483
00484 le = CG_AllocLocalEntity();
00485 re = &le->refEntity;
00486
00487 velocity[0] = 60 - 120 * crandom();
00488 velocity[1] = 40 - 80 * crandom();
00489 velocity[2] = 100 - 200 * crandom();
00490
00491 le->leType = LE_MOVE_SCALE_FADE;
00492 le->leFlags = LEF_TUMBLE;
00493 le->leBounceSoundType = LEBS_NONE;
00494 le->leMarkType = LEMT_NONE;
00495
00496 le->startTime = cg.time;
00497 le->endTime = le->startTime + 600;
00498
00499 le->pos.trType = TR_GRAVITY;
00500 le->pos.trTime = cg.time;
00501
00502 AnglesToAxis( cent->lerpAngles, v );
00503
00504 offset[0] = 2;
00505 offset[1] = 2;
00506 offset[2] = 2;
00507
00508 xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
00509 xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
00510 xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
00511
00512 VectorAdd( origin, xoffset, re->origin );
00513 VectorCopy( re->origin, le->pos.trBase );
00514
00515 if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
00516 waterScale = 0.10f;
00517 }
00518
00519 xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
00520 xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
00521 xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
00522 VectorScale( xvelocity, waterScale, le->pos.trDelta );
00523
00524 AxisCopy( axisDefault, re->axis );
00525 re->shaderTime = cg.time / 1000.0f;
00526 re->reType = RT_SPRITE;
00527 re->radius = 0.25f;
00528 re->customShader = cgs.media.railRingsShader;
00529 le->bounceFactor = 0.3f;
00530
00531 re->shaderRGBA[0] = wi->flashDlightColor[0] * 63;
00532 re->shaderRGBA[1] = wi->flashDlightColor[1] * 63;
00533 re->shaderRGBA[2] = wi->flashDlightColor[2] * 63;
00534 re->shaderRGBA[3] = 63;
00535
00536 le->color[0] = wi->flashDlightColor[0] * 0.2;
00537 le->color[1] = wi->flashDlightColor[1] * 0.2;
00538 le->color[2] = wi->flashDlightColor[2] * 0.2;
00539 le->color[3] = 0.25f;
00540
00541 le->angles.trType = TR_LINEAR;
00542 le->angles.trTime = cg.time;
00543 le->angles.trBase[0] = rand()&31;
00544 le->angles.trBase[1] = rand()&31;
00545 le->angles.trBase[2] = rand()&31;
00546 le->angles.trDelta[0] = 1;
00547 le->angles.trDelta[1] = 0.5;
00548 le->angles.trDelta[2] = 0;
00549
00550 }
00551
00552
00553
00554
00555
00556 void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi ) {
00557 vec3_t origin;
00558 entityState_t *es;
00559 vec3_t forward, up;
00560 refEntity_t beam;
00561
00562 es = &ent->currentState;
00563
00564 BG_EvaluateTrajectory( &es->pos, cg.time, origin );
00565 ent->trailTime = cg.time;
00566
00567 memset( &beam, 0, sizeof( beam ) );
00568
00569 VectorCopy ( cg_entities[ ent->currentState.otherEntityNum ].lerpOrigin, beam.origin );
00570 beam.origin[2] += 26;
00571 AngleVectors( cg_entities[ ent->currentState.otherEntityNum ].lerpAngles, forward, NULL, up );
00572 VectorMA( beam.origin, -6, up, beam.origin );
00573 VectorCopy( origin, beam.oldorigin );
00574
00575 if (Distance( beam.origin, beam.oldorigin ) < 64 )
00576 return;
00577
00578 beam.reType = RT_LIGHTNING;
00579 beam.customShader = cgs.media.lightningShader;
00580
00581 AxisClear( beam.axis );
00582 beam.shaderRGBA[0] = 0xff;
00583 beam.shaderRGBA[1] = 0xff;
00584 beam.shaderRGBA[2] = 0xff;
00585 beam.shaderRGBA[3] = 0xff;
00586 trap_R_AddRefEntityToScene( &beam );
00587 }
00588
00589
00590
00591
00592
00593
00594 static void CG_GrenadeTrail( centity_t *ent, const weaponInfo_t *wi ) {
00595 CG_RocketTrail( ent, wi );
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 void CG_RegisterWeapon( int weaponNum ) {
00607 weaponInfo_t *weaponInfo;
00608 gitem_t *item, *ammo;
00609 char path[MAX_QPATH];
00610 vec3_t mins, maxs;
00611 int i;
00612
00613 weaponInfo = &cg_weapons[weaponNum];
00614
00615 if ( weaponNum == 0 ) {
00616 return;
00617 }
00618
00619 if ( weaponInfo->registered ) {
00620 return;
00621 }
00622
00623 memset( weaponInfo, 0, sizeof( *weaponInfo ) );
00624 weaponInfo->registered = qtrue;
00625
00626 for ( item = bg_itemlist + 1 ; item->classname ; item++ ) {
00627 if ( item->giType == IT_WEAPON && item->giTag == weaponNum ) {
00628 weaponInfo->item = item;
00629 break;
00630 }
00631 }
00632 if ( !item->classname ) {
00633 CG_Error( "Couldn't find weapon %i", weaponNum );
00634 }
00635 CG_RegisterItemVisuals( item - bg_itemlist );
00636
00637
00638 weaponInfo->weaponModel = trap_R_RegisterModel( item->world_model[0] );
00639
00640
00641 trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs );
00642 for ( i = 0 ; i < 3 ; i++ ) {
00643 weaponInfo->weaponMidpoint[i] = mins[i] + 0.5 * ( maxs[i] - mins[i] );
00644 }
00645
00646 weaponInfo->weaponIcon = trap_R_RegisterShader( item->icon );
00647 weaponInfo->ammoIcon = trap_R_RegisterShader( item->icon );
00648
00649 for ( ammo = bg_itemlist + 1 ; ammo->classname ; ammo++ ) {
00650 if ( ammo->giType == IT_AMMO && ammo->giTag == weaponNum ) {
00651 break;
00652 }
00653 }
00654 if ( ammo->classname && ammo->world_model[0] ) {
00655 weaponInfo->ammoModel = trap_R_RegisterModel( ammo->world_model[0] );
00656 }
00657
00658 strcpy( path, item->world_model[0] );
00659 COM_StripExtension( path, path );
00660 strcat( path, "_flash.md3" );
00661 weaponInfo->flashModel = trap_R_RegisterModel( path );
00662
00663 strcpy( path, item->world_model[0] );
00664 COM_StripExtension( path, path );
00665 strcat( path, "_barrel.md3" );
00666 weaponInfo->barrelModel = trap_R_RegisterModel( path );
00667
00668 strcpy( path, item->world_model[0] );
00669 COM_StripExtension( path, path );
00670 strcat( path, "_hand.md3" );
00671 weaponInfo->handsModel = trap_R_RegisterModel( path );
00672
00673 if ( !weaponInfo->handsModel ) {
00674 weaponInfo->handsModel = trap_R_RegisterModel( "models/weapons2/shotgun/shotgun_hand.md3" );
00675 }
00676
00677 weaponInfo->loopFireSound = qfalse;
00678
00679 switch ( weaponNum ) {
00680 case WP_GAUNTLET:
00681 MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
00682 weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/melee/fstrun.wav", qfalse );
00683 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse );
00684 break;
00685
00686 case WP_LIGHTNING:
00687 MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
00688 weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/melee/fsthum.wav", qfalse );
00689 weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/lightning/lg_hum.wav", qfalse );
00690
00691 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/lightning/lg_fire.wav", qfalse );
00692 cgs.media.lightningShader = trap_R_RegisterShader( "lightningBoltNew");
00693 cgs.media.lightningExplosionModel = trap_R_RegisterModel( "models/weaphits/crackle.md3" );
00694 cgs.media.sfx_lghit1 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit.wav", qfalse );
00695 cgs.media.sfx_lghit2 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit2.wav", qfalse );
00696 cgs.media.sfx_lghit3 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit3.wav", qfalse );
00697
00698 break;
00699
00700 case WP_GRAPPLING_HOOK:
00701 MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
00702 weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/rocket/rocket.md3" );
00703 weaponInfo->missileTrailFunc = CG_GrappleTrail;
00704 weaponInfo->missileDlight = 200;
00705 weaponInfo->wiTrailTime = 2000;
00706 weaponInfo->trailRadius = 64;
00707 MAKERGB( weaponInfo->missileDlightColor, 1, 0.75f, 0 );
00708 weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/melee/fsthum.wav", qfalse );
00709 weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/melee/fstrun.wav", qfalse );
00710 break;
00711
00712 #ifdef MISSIONPACK
00713 case WP_CHAINGUN:
00714 weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/vulcan/wvulfire.wav", qfalse );
00715 weaponInfo->loopFireSound = qtrue;
00716 MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
00717 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf1b.wav", qfalse );
00718 weaponInfo->flashSound[1] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf2b.wav", qfalse );
00719 weaponInfo->flashSound[2] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf3b.wav", qfalse );
00720 weaponInfo->flashSound[3] = trap_S_RegisterSound( "sound/weapons/vulcan/vulcanf4b.wav", qfalse );
00721 weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
00722 cgs.media.bulletExplosionShader = trap_R_RegisterShader( "bulletExplosion" );
00723 break;
00724 #endif
00725
00726 case WP_MACHINEGUN:
00727 MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
00728 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf1b.wav", qfalse );
00729 weaponInfo->flashSound[1] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf2b.wav", qfalse );
00730 weaponInfo->flashSound[2] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf3b.wav", qfalse );
00731 weaponInfo->flashSound[3] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf4b.wav", qfalse );
00732 weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
00733 cgs.media.bulletExplosionShader = trap_R_RegisterShader( "bulletExplosion" );
00734 break;
00735
00736 case WP_SHOTGUN:
00737 MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
00738 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/shotgun/sshotf1b.wav", qfalse );
00739 weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass;
00740 break;
00741
00742 case WP_ROCKET_LAUNCHER:
00743 weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/rocket/rocket.md3" );
00744 weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/rocket/rockfly.wav", qfalse );
00745 weaponInfo->missileTrailFunc = CG_RocketTrail;
00746 weaponInfo->missileDlight = 200;
00747 weaponInfo->wiTrailTime = 2000;
00748 weaponInfo->trailRadius = 64;
00749
00750 MAKERGB( weaponInfo->missileDlightColor, 1, 0.75f, 0 );
00751 MAKERGB( weaponInfo->flashDlightColor, 1, 0.75f, 0 );
00752
00753 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/rocket/rocklf1a.wav", qfalse );
00754 cgs.media.rocketExplosionShader = trap_R_RegisterShader( "rocketExplosion" );
00755 break;
00756
00757 #ifdef MISSIONPACK
00758 case WP_PROX_LAUNCHER:
00759 weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/proxmine.md3" );
00760 weaponInfo->missileTrailFunc = CG_GrenadeTrail;
00761 weaponInfo->wiTrailTime = 700;
00762 weaponInfo->trailRadius = 32;
00763 MAKERGB( weaponInfo->flashDlightColor, 1, 0.70f, 0 );
00764 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/proxmine/wstbfire.wav", qfalse );
00765 cgs.media.grenadeExplosionShader = trap_R_RegisterShader( "grenadeExplosion" );
00766 break;
00767 #endif
00768
00769 case WP_GRENADE_LAUNCHER:
00770 weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/grenade1.md3" );
00771 weaponInfo->missileTrailFunc = CG_GrenadeTrail;
00772 weaponInfo->wiTrailTime = 700;
00773 weaponInfo->trailRadius = 32;
00774 MAKERGB( weaponInfo->flashDlightColor, 1, 0.70f, 0 );
00775 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/grenade/grenlf1a.wav", qfalse );
00776 cgs.media.grenadeExplosionShader = trap_R_RegisterShader( "grenadeExplosion" );
00777 break;
00778
00779 #ifdef MISSIONPACK
00780 case WP_NAILGUN:
00781 weaponInfo->ejectBrassFunc = CG_NailgunEjectBrass;
00782 weaponInfo->missileTrailFunc = CG_NailTrail;
00783
00784 weaponInfo->trailRadius = 16;
00785 weaponInfo->wiTrailTime = 250;
00786 weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/nail.md3" );
00787 MAKERGB( weaponInfo->flashDlightColor, 1, 0.75f, 0 );
00788 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/nailgun/wnalfire.wav", qfalse );
00789 break;
00790 #endif
00791
00792 case WP_PLASMAGUN:
00793
00794 weaponInfo->missileTrailFunc = CG_PlasmaTrail;
00795 weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/plasma/lasfly.wav", qfalse );
00796 MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
00797 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/plasma/hyprbf1a.wav", qfalse );
00798 cgs.media.plasmaExplosionShader = trap_R_RegisterShader( "plasmaExplosion" );
00799 cgs.media.railRingsShader = trap_R_RegisterShader( "railDisc" );
00800 break;
00801
00802 case WP_RAILGUN:
00803 weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/railgun/rg_hum.wav", qfalse );
00804 MAKERGB( weaponInfo->flashDlightColor, 1, 0.5f, 0 );
00805 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/railgun/railgf1a.wav", qfalse );
00806 cgs.media.railExplosionShader = trap_R_RegisterShader( "railExplosion" );
00807 cgs.media.railRingsShader = trap_R_RegisterShader( "railDisc" );
00808 cgs.media.railCoreShader = trap_R_RegisterShader( "railCore" );
00809 break;
00810
00811 case WP_BFG:
00812 weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/bfg/bfg_hum.wav", qfalse );
00813 MAKERGB( weaponInfo->flashDlightColor, 1, 0.7f, 1 );
00814 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/bfg/bfg_fire.wav", qfalse );
00815 cgs.media.bfgExplosionShader = trap_R_RegisterShader( "bfgExplosion" );
00816 weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/bfg.md3" );
00817 weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/rocket/rockfly.wav", qfalse );
00818 break;
00819
00820 default:
00821 MAKERGB( weaponInfo->flashDlightColor, 1, 1, 1 );
00822 weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/rocket/rocklf1a.wav", qfalse );
00823 break;
00824 }
00825 }
00826
00827
00828
00829
00830
00831
00832
00833
00834 void CG_RegisterItemVisuals( int itemNum ) {
00835 itemInfo_t *itemInfo;
00836 gitem_t *item;
00837
00838 if ( itemNum < 0 || itemNum >= bg_numItems ) {
00839 CG_Error( "CG_RegisterItemVisuals: itemNum %d out of range [0-%d]", itemNum, bg_numItems-1 );
00840 }
00841
00842 itemInfo = &cg_items[ itemNum ];
00843 if ( itemInfo->registered ) {
00844 return;
00845 }
00846
00847 item = &bg_itemlist[ itemNum ];
00848
00849 memset( itemInfo, 0, sizeof( &itemInfo ) );
00850 itemInfo->registered = qtrue;
00851
00852 itemInfo->models[0] = trap_R_RegisterModel( item->world_model[0] );
00853
00854 itemInfo->icon = trap_R_RegisterShader( item->icon );
00855
00856 if ( item->giType == IT_WEAPON ) {
00857 CG_RegisterWeapon( item->giTag );
00858 }
00859
00860
00861
00862
00863 if ( item->giType == IT_POWERUP || item->giType == IT_HEALTH ||
00864 item->giType == IT_ARMOR || item->giType == IT_HOLDABLE ) {
00865 if ( item->world_model[1] ) {
00866 itemInfo->models[1] = trap_R_RegisterModel( item->world_model[1] );
00867 }
00868 }
00869 }
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886 static int CG_MapTorsoToWeaponFrame( clientInfo_t *ci, int frame ) {
00887
00888
00889 if ( frame >= ci->animations[TORSO_DROP].firstFrame
00890 && frame < ci->animations[TORSO_DROP].firstFrame + 9 ) {
00891 return frame - ci->animations[TORSO_DROP].firstFrame + 6;
00892 }
00893
00894
00895 if ( frame >= ci->animations[TORSO_ATTACK].firstFrame
00896 && frame < ci->animations[TORSO_ATTACK].firstFrame + 6 ) {
00897 return 1 + frame - ci->animations[TORSO_ATTACK].firstFrame;
00898 }
00899
00900
00901 if ( frame >= ci->animations[TORSO_ATTACK2].firstFrame
00902 && frame < ci->animations[TORSO_ATTACK2].firstFrame + 6 ) {
00903 return 1 + frame - ci->animations[TORSO_ATTACK2].firstFrame;
00904 }
00905
00906 return 0;
00907 }
00908
00909
00910
00911
00912
00913
00914
00915 static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
00916 float scale;
00917 int delta;
00918 float fracsin;
00919
00920 VectorCopy( cg.refdef.vieworg, origin );
00921 VectorCopy( cg.refdefViewAngles, angles );
00922
00923
00924 if ( cg.bobcycle & 1 ) {
00925 scale = -cg.xyspeed;
00926 } else {
00927 scale = cg.xyspeed;
00928 }
00929
00930
00931 angles[ROLL] += scale * cg.bobfracsin * 0.005;
00932 angles[YAW] += scale * cg.bobfracsin * 0.01;
00933 angles[PITCH] += cg.xyspeed * cg.bobfracsin * 0.005;
00934
00935
00936 delta = cg.time - cg.landTime;
00937 if ( delta < LAND_DEFLECT_TIME ) {
00938 origin[2] += cg.landChange*0.25 * delta / LAND_DEFLECT_TIME;
00939 } else if ( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME ) {
00940 origin[2] += cg.landChange*0.25 *
00941 (LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta) / LAND_RETURN_TIME;
00942 }
00943
00944 #if 0
00945
00946 delta = cg.time - cg.stepTime;
00947 if ( delta < STEP_TIME/2 ) {
00948 origin[2] -= cg.stepChange*0.25 * delta / (STEP_TIME/2);
00949 } else if ( delta < STEP_TIME ) {
00950 origin[2] -= cg.stepChange*0.25 * (STEP_TIME - delta) / (STEP_TIME/2);
00951 }
00952 #endif
00953
00954
00955 scale = cg.xyspeed + 40;
00956 fracsin = sin( cg.time * 0.001 );
00957 angles[ROLL] += scale * fracsin * 0.01;
00958 angles[YAW] += scale * fracsin * 0.01;
00959 angles[PITCH] += scale * fracsin * 0.01;
00960 }
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974 static void CG_LightningBolt( centity_t *cent, vec3_t origin ) {
00975 trace_t trace;
00976 refEntity_t beam;
00977 vec3_t forward;
00978 vec3_t muzzlePoint, endPoint;
00979
00980 if (cent->currentState.weapon != WP_LIGHTNING) {
00981 return;
00982 }
00983
00984 memset( &beam, 0, sizeof( beam ) );
00985
00986
00987 if ((cent->currentState.number == cg.predictedPlayerState.clientNum) && (cg_trueLightning.value != 0)) {
00988 vec3_t angle;
00989 int i;
00990
00991 for (i = 0; i < 3; i++) {
00992 float a = cent->lerpAngles[i] - cg.refdefViewAngles[i];
00993 if (a > 180) {
00994 a -= 360;
00995 }
00996 if (a < -180) {
00997 a += 360;
00998 }
00999
01000 angle[i] = cg.refdefViewAngles[i] + a * (1.0 - cg_trueLightning.value);
01001 if (angle[i] < 0) {
01002 angle[i] += 360;
01003 }
01004 if (angle[i] > 360) {
01005 angle[i] -= 360;
01006 }
01007 }
01008
01009 AngleVectors(angle, forward, NULL, NULL );
01010 VectorCopy(cent->lerpOrigin, muzzlePoint );
01011
01012 } else {
01013
01014 AngleVectors( cent->lerpAngles, forward, NULL, NULL );
01015 VectorCopy(cent->lerpOrigin, muzzlePoint );
01016 }
01017
01018
01019 muzzlePoint[2] += DEFAULT_VIEWHEIGHT;
01020
01021 VectorMA( muzzlePoint, 14, forward, muzzlePoint );
01022
01023
01024 VectorMA( muzzlePoint, LIGHTNING_RANGE, forward, endPoint );
01025
01026
01027 CG_Trace( &trace, muzzlePoint, vec3_origin, vec3_origin, endPoint,
01028 cent->currentState.number, MASK_SHOT );
01029
01030
01031 VectorCopy( trace.endpos, beam.oldorigin );
01032
01033
01034
01035 VectorCopy( origin, beam.origin );
01036
01037 beam.reType = RT_LIGHTNING;
01038 beam.customShader = cgs.media.lightningShader;
01039 trap_R_AddRefEntityToScene( &beam );
01040
01041
01042 if ( trace.fraction < 1.0 ) {
01043 vec3_t angles;
01044 vec3_t dir;
01045
01046 VectorSubtract( beam.oldorigin, beam.origin, dir );
01047 VectorNormalize( dir );
01048
01049 memset( &beam, 0, sizeof( beam ) );
01050 beam.hModel = cgs.media.lightningExplosionModel;
01051
01052 VectorMA( trace.endpos, -16, dir, beam.origin );
01053
01054
01055 angles[0] = rand() % 360;
01056 angles[1] = rand() % 360;
01057 angles[2] = rand() % 360;
01058 AnglesToAxis( angles, beam.axis );
01059 trap_R_AddRefEntityToScene( &beam );
01060 }
01061 }
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134 static void CG_SpawnRailTrail( centity_t *cent, vec3_t origin ) {
01135 clientInfo_t *ci;
01136
01137 if ( cent->currentState.weapon != WP_RAILGUN ) {
01138 return;
01139 }
01140 if ( !cent->pe.railgunFlash ) {
01141 return;
01142 }
01143 cent->pe.railgunFlash = qtrue;
01144 ci = &cgs.clientinfo[ cent->currentState.clientNum ];
01145 CG_RailTrail( ci, origin, cent->pe.railgunImpact );
01146 }
01147
01148
01149
01150
01151
01152
01153
01154 #define SPIN_SPEED 0.9
01155 #define COAST_TIME 1000
01156 static float CG_MachinegunSpinAngle( centity_t *cent ) {
01157 int delta;
01158 float angle;
01159 float speed;
01160
01161 delta = cg.time - cent->pe.barrelTime;
01162 if ( cent->pe.barrelSpinning ) {
01163 angle = cent->pe.barrelAngle + delta * SPIN_SPEED;
01164 } else {
01165 if ( delta > COAST_TIME ) {
01166 delta = COAST_TIME;
01167 }
01168
01169 speed = 0.5 * ( SPIN_SPEED + (float)( COAST_TIME - delta ) / COAST_TIME );
01170 angle = cent->pe.barrelAngle + delta * speed;
01171 }
01172
01173 if ( cent->pe.barrelSpinning == !(cent->currentState.eFlags & EF_FIRING) ) {
01174 cent->pe.barrelTime = cg.time;
01175 cent->pe.barrelAngle = AngleMod( angle );
01176 cent->pe.barrelSpinning = !!(cent->currentState.eFlags & EF_FIRING);
01177 #ifdef MISSIONPACK
01178 if ( cent->currentState.weapon == WP_CHAINGUN && !cent->pe.barrelSpinning ) {
01179 trap_S_StartSound( NULL, cent->currentState.number, CHAN_WEAPON, trap_S_RegisterSound( "sound/weapons/vulcan/wvulwind.wav", qfalse ) );
01180 }
01181 #endif
01182 }
01183
01184 return angle;
01185 }
01186
01187
01188
01189
01190
01191
01192
01193 static void CG_AddWeaponWithPowerups( refEntity_t *gun, int powerups ) {
01194
01195 if ( powerups & ( 1 << PW_INVIS ) ) {
01196 gun->customShader = cgs.media.invisShader;
01197 trap_R_AddRefEntityToScene( gun );
01198 } else {
01199 trap_R_AddRefEntityToScene( gun );
01200
01201 if ( powerups & ( 1 << PW_BATTLESUIT ) ) {
01202 gun->customShader = cgs.media.battleWeaponShader;
01203 trap_R_AddRefEntityToScene( gun );
01204 }
01205 if ( powerups & ( 1 << PW_QUAD ) ) {
01206 gun->customShader = cgs.media.quadWeaponShader;
01207 trap_R_AddRefEntityToScene( gun );
01208 }
01209 }
01210 }
01211
01212
01213
01214
01215
01216
01217
01218