00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "cg_local.h"
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 void CG_BubbleTrail( vec3_t start, vec3_t end, float spacing ) {
00037 vec3_t move;
00038 vec3_t vec;
00039 float len;
00040 int i;
00041
00042 if ( cg_noProjectileTrail.integer ) {
00043 return;
00044 }
00045
00046 VectorCopy (start, move);
00047 VectorSubtract (end, start, vec);
00048 len = VectorNormalize (vec);
00049
00050
00051 i = rand() % (int)spacing;
00052 VectorMA( move, i, vec, move );
00053
00054 VectorScale (vec, spacing, vec);
00055
00056 for ( ; i < len; i += spacing ) {
00057 localEntity_t *le;
00058 refEntity_t *re;
00059
00060 le = CG_AllocLocalEntity();
00061 le->leFlags = LEF_PUFF_DONT_SCALE;
00062 le->leType = LE_MOVE_SCALE_FADE;
00063 le->startTime = cg.time;
00064 le->endTime = cg.time + 1000 + random() * 250;
00065 le->lifeRate = 1.0 / ( le->endTime - le->startTime );
00066
00067 re = &le->refEntity;
00068 re->shaderTime = cg.time / 1000.0f;
00069
00070 re->reType = RT_SPRITE;
00071 re->rotation = 0;
00072 re->radius = 3;
00073 re->customShader = cgs.media.waterBubbleShader;
00074 re->shaderRGBA[0] = 0xff;
00075 re->shaderRGBA[1] = 0xff;
00076 re->shaderRGBA[2] = 0xff;
00077 re->shaderRGBA[3] = 0xff;
00078
00079 le->color[3] = 1.0;
00080
00081 le->pos.trType = TR_LINEAR;
00082 le->pos.trTime = cg.time;
00083 VectorCopy( move, le->pos.trBase );
00084 le->pos.trDelta[0] = crandom()*5;
00085 le->pos.trDelta[1] = crandom()*5;
00086 le->pos.trDelta[2] = crandom()*5 + 6;
00087
00088 VectorAdd (move, vec, move);
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097
00098
00099 localEntity_t *CG_SmokePuff( const vec3_t p, const vec3_t vel,
00100 float radius,
00101 float r, float g, float b, float a,
00102 float duration,
00103 int startTime,
00104 int fadeInTime,
00105 int leFlags,
00106 qhandle_t hShader ) {
00107 static int seed = 0x92;
00108 localEntity_t *le;
00109 refEntity_t *re;
00110
00111
00112 le = CG_AllocLocalEntity();
00113 le->leFlags = leFlags;
00114 le->radius = radius;
00115
00116 re = &le->refEntity;
00117 re->rotation = Q_random( &seed ) * 360;
00118 re->radius = radius;
00119 re->shaderTime = startTime / 1000.0f;
00120
00121 le->leType = LE_MOVE_SCALE_FADE;
00122 le->startTime = startTime;
00123 le->fadeInTime = fadeInTime;
00124 le->endTime = startTime + duration;
00125 if ( fadeInTime > startTime ) {
00126 le->lifeRate = 1.0 / ( le->endTime - le->fadeInTime );
00127 }
00128 else {
00129 le->lifeRate = 1.0 / ( le->endTime - le->startTime );
00130 }
00131 le->color[0] = r;
00132 le->color[1] = g;
00133 le->color[2] = b;
00134 le->color[3] = a;
00135
00136
00137 le->pos.trType = TR_LINEAR;
00138 le->pos.trTime = startTime;
00139 VectorCopy( vel, le->pos.trDelta );
00140 VectorCopy( p, le->pos.trBase );
00141
00142 VectorCopy( p, re->origin );
00143 re->customShader = hShader;
00144
00145
00146 if ( cgs.glconfig.hardwareType == GLHW_RAGEPRO ) {
00147 re->customShader = cgs.media.smokePuffRageProShader;
00148 re->shaderRGBA[0] = 0xff;
00149 re->shaderRGBA[1] = 0xff;
00150 re->shaderRGBA[2] = 0xff;
00151 re->shaderRGBA[3] = 0xff;
00152 } else {
00153 re->shaderRGBA[0] = le->color[0] * 0xff;
00154 re->shaderRGBA[1] = le->color[1] * 0xff;
00155 re->shaderRGBA[2] = le->color[2] * 0xff;
00156 re->shaderRGBA[3] = 0xff;
00157 }
00158
00159 re->reType = RT_SPRITE;
00160 re->radius = le->radius;
00161
00162 return le;
00163 }
00164
00165
00166
00167
00168
00169
00170
00171
00172 void CG_SpawnEffect( vec3_t org ) {
00173 localEntity_t *le;
00174 refEntity_t *re;
00175
00176 le = CG_AllocLocalEntity();
00177 le->leFlags = 0;
00178 le->leType = LE_FADE_RGB;
00179 le->startTime = cg.time;
00180 le->endTime = cg.time + 500;
00181 le->lifeRate = 1.0 / ( le->endTime - le->startTime );
00182
00183 le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
00184
00185 re = &le->refEntity;
00186
00187 re->reType = RT_MODEL;
00188 re->shaderTime = cg.time / 1000.0f;
00189
00190 #ifndef MISSIONPACK
00191 re->customShader = cgs.media.teleportEffectShader;
00192 #endif
00193 re->hModel = cgs.media.teleportEffectModel;
00194 AxisClear( re->axis );
00195
00196 VectorCopy( org, re->origin );
00197 #ifdef MISSIONPACK
00198 re->origin[2] += 16;
00199 #else
00200 re->origin[2] -= 24;
00201 #endif
00202 }
00203
00204
00205 #ifdef MISSIONPACK
00206
00207
00208
00209
00210
00211 void CG_LightningBoltBeam( vec3_t start, vec3_t end ) {
00212 localEntity_t *le;
00213 refEntity_t *beam;
00214
00215 le = CG_AllocLocalEntity();
00216 le->leFlags = 0;
00217 le->leType = LE_SHOWREFENTITY;
00218 le->startTime = cg.time;
00219 le->endTime = cg.time + 50;
00220
00221 beam = &le->refEntity;
00222
00223 VectorCopy( start, beam->origin );
00224
00225 VectorCopy( end, beam->oldorigin );
00226
00227 beam->reType = RT_LIGHTNING;
00228 beam->customShader = cgs.media.lightningShader;
00229 }
00230
00231
00232
00233
00234
00235
00236 void CG_KamikazeEffect( vec3_t org ) {
00237 localEntity_t *le;
00238 refEntity_t *re;
00239
00240 le = CG_AllocLocalEntity();
00241 le->leFlags = 0;
00242 le->leType = LE_KAMIKAZE;
00243 le->startTime = cg.time;
00244 le->endTime = cg.time + 3000;
00245 le->lifeRate = 1.0 / ( le->endTime - le->startTime );
00246
00247 le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
00248
00249 VectorClear(le->angles.trBase);
00250
00251 re = &le->refEntity;
00252
00253 re->reType = RT_MODEL;
00254 re->shaderTime = cg.time / 1000.0f;
00255
00256 re->hModel = cgs.media.kamikazeEffectModel;
00257
00258 VectorCopy( org, re->origin );
00259
00260 }
00261
00262
00263
00264
00265
00266
00267 void CG_ObeliskExplode( vec3_t org, int entityNum ) {
00268 localEntity_t *le;
00269 vec3_t origin;
00270
00271
00272 VectorCopy( org, origin );
00273 origin[2] += 64;
00274 le = CG_MakeExplosion( origin, vec3_origin,
00275 cgs.media.dishFlashModel,
00276 cgs.media.rocketExplosionShader,
00277 600, qtrue );
00278 le->light = 300;
00279 le->lightColor[0] = 1;
00280 le->lightColor[1] = 0.75;
00281 le->lightColor[2] = 0.0;
00282 }
00283
00284
00285
00286
00287
00288
00289 void CG_ObeliskPain( vec3_t org ) {
00290 float r;
00291 sfxHandle_t sfx;
00292
00293
00294 r = rand() & 3;
00295 if ( r < 2 ) {
00296 sfx = cgs.media.obeliskHitSound1;
00297 } else if ( r == 2 ) {
00298 sfx = cgs.media.obeliskHitSound2;
00299 } else {
00300 sfx = cgs.media.obeliskHitSound3;
00301 }
00302 trap_S_StartSound ( org, ENTITYNUM_NONE, CHAN_BODY, sfx );
00303 }
00304
00305
00306
00307
00308
00309
00310
00311 void CG_InvulnerabilityImpact( vec3_t org, vec3_t angles ) {
00312 localEntity_t *le;
00313 refEntity_t *re;
00314 int r;
00315 sfxHandle_t sfx;
00316
00317 le = CG_AllocLocalEntity();
00318 le->leFlags = 0;
00319 le->leType = LE_INVULIMPACT;
00320 le->startTime = cg.time;
00321 le->endTime = cg.time + 1000;
00322 le->lifeRate = 1.0 / ( le->endTime - le->startTime );
00323
00324 le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
00325
00326 re = &le->refEntity;
00327
00328 re->reType = RT_MODEL;
00329 re->shaderTime = cg.time / 1000.0f;
00330
00331 re->hModel = cgs.media.invulnerabilityImpactModel;
00332
00333 VectorCopy( org, re->origin );
00334 AnglesToAxis( angles, re->axis );
00335
00336 r = rand() & 3;
00337 if ( r < 2 ) {
00338 sfx = cgs.media.invulnerabilityImpactSound1;
00339 } else if ( r == 2 ) {
00340 sfx = cgs.media.invulnerabilityImpactSound2;
00341 } else {
00342 sfx = cgs.media.invulnerabilityImpactSound3;
00343 }
00344 trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, sfx );
00345 }
00346
00347
00348
00349
00350
00351
00352 void CG_InvulnerabilityJuiced( vec3_t org ) {
00353 localEntity_t *le;
00354 refEntity_t *re;
00355 vec3_t angles;
00356
00357 le = CG_AllocLocalEntity();
00358 le->leFlags = 0;
00359 le->leType = LE_INVULJUICED;
00360 le->startTime = cg.time;
00361 le->endTime = cg.time + 10000;
00362 le->lifeRate = 1.0 / ( le->endTime - le->startTime );
00363
00364 le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
00365
00366 re = &le->refEntity;
00367
00368 re->reType = RT_MODEL;
00369 re->shaderTime = cg.time / 1000.0f;
00370
00371 re->hModel = cgs.media.invulnerabilityJuicedModel;
00372
00373 VectorCopy( org, re->origin );
00374 VectorClear(angles);
00375 AnglesToAxis( angles, re->axis );
00376
00377 trap_S_StartSound (org, ENTITYNUM_NONE, CHAN_BODY, cgs.media.invulnerabilityJuicedSound );
00378 }
00379
00380 #endif
00381
00382
00383
00384
00385
00386
00387 void CG_ScorePlum( int client, vec3_t org, int score ) {
00388 localEntity_t *le;
00389 refEntity_t *re;
00390 vec3_t angles;
00391 static vec3_t lastPos;
00392
00393
00394 if (client != cg.predictedPlayerState.clientNum || cg_scorePlum.integer == 0) {
00395 return;
00396 }
00397
00398 le = CG_AllocLocalEntity();
00399 le->leFlags = 0;
00400 le->leType = LE_SCOREPLUM;
00401 le->startTime = cg.time;
00402 le->endTime = cg.time + 4000;
00403 le->lifeRate = 1.0 / ( le->endTime - le->startTime );
00404
00405
00406 le->color[0] = le->color[1] = le->color[2] = le->color[3] = 1.0;
00407 le->radius = score;
00408
00409 VectorCopy( org, le->pos.trBase );
00410 if (org[2] >= lastPos[2] - 20 && org[2] <= lastPos[2] + 20) {
00411 le->pos.trBase[2] -= 20;
00412 }
00413
00414
00415 VectorCopy(org, lastPos);
00416
00417
00418 re = &le->refEntity;
00419
00420 re->reType = RT_SPRITE;
00421 re->radius = 16;
00422
00423 VectorClear(angles);
00424 AnglesToAxis( angles, re->axis );
00425 }
00426
00427
00428
00429
00430
00431
00432
00433 localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir,
00434 qhandle_t hModel, qhandle_t shader,
00435 int msec, qboolean isSprite ) {
00436 float ang;
00437 localEntity_t *ex;
00438 int offset;
00439 vec3_t tmpVec, newOrigin;
00440
00441 if ( msec <= 0 ) {
00442 CG_Error( "CG_MakeExplosion: msec = %i", msec );
00443 }
00444
00445
00446 offset = rand() & 63;
00447
00448 ex = CG_AllocLocalEntity();
00449 if ( isSprite ) {
00450 ex->leType = LE_SPRITE_EXPLOSION;
00451
00452
00453 ex->refEntity.rotation = rand() % 360;
00454 VectorScale( dir, 16, tmpVec );
00455 VectorAdd( tmpVec, origin, newOrigin );
00456 } else {
00457 ex->leType = LE_EXPLOSION;
00458 VectorCopy( origin, newOrigin );
00459
00460
00461 if ( !dir ) {
00462 AxisClear( ex->refEntity.axis );
00463 } else {
00464 ang = rand() % 360;
00465 VectorCopy( dir, ex->refEntity.axis[0] );
00466 RotateAroundDirection( ex->refEntity.axis, ang );
00467 }
00468 }
00469
00470 ex->startTime = cg.time - offset;
00471 ex->endTime = ex->startTime + msec;
00472
00473
00474 ex->refEntity.shaderTime = ex->startTime / 1000.0f;
00475
00476 ex->refEntity.hModel = hModel;
00477 ex->refEntity.customShader = shader;
00478
00479
00480 VectorCopy( newOrigin, ex->refEntity.origin );
00481 VectorCopy( newOrigin, ex->refEntity.oldorigin );
00482
00483 ex->color[0] = ex->color[1] = ex->color[2] = 1.0;
00484
00485 return ex;
00486 }
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496 void CG_Bleed( vec3_t origin, int entityNum ) {
00497 localEntity_t *ex;
00498
00499 if ( !cg_blood.integer ) {
00500 return;
00501 }
00502
00503 ex = CG_AllocLocalEntity();
00504 ex->leType = LE_EXPLOSION;
00505
00506 ex->startTime = cg.time;
00507 ex->endTime = ex->startTime + 500;
00508
00509 VectorCopy ( origin, ex->refEntity.origin);
00510 ex->refEntity.reType = RT_SPRITE;
00511 ex->refEntity.rotation = rand() % 360;
00512 ex->refEntity.radius = 24;
00513
00514 ex->refEntity.customShader = cgs.media.bloodExplosionShader;
00515
00516
00517 if ( entityNum == cg.snap->ps.clientNum ) {
00518 ex->refEntity.renderfx |= RF_THIRD_PERSON;
00519 }
00520 }
00521
00522
00523
00524
00525
00526
00527
00528
00529 void CG_LaunchGib( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
00530 localEntity_t *le;
00531 refEntity_t *re;
00532
00533 le = CG_AllocLocalEntity();
00534 re = &le->refEntity;
00535
00536 le->leType = LE_FRAGMENT;
00537 le->startTime = cg.time;
00538 le->endTime = le->startTime + 5000 + random() * 3000;
00539
00540 VectorCopy( origin, re->origin );
00541 AxisCopy( axisDefault, re->axis );
00542 re->hModel = hModel;
00543
00544 le->pos.trType = TR_GRAVITY;
00545 VectorCopy( origin, le->pos.trBase );
00546 VectorCopy( velocity, le->pos.trDelta );
00547 le->pos.trTime = cg.time;
00548
00549 le->bounceFactor = 0.6f;
00550
00551 le->leBounceSoundType = LEBS_BLOOD;
00552 le->leMarkType = LEMT_BLOOD;
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562 #define GIB_VELOCITY 250
00563 #define GIB_JUMP 250
00564 void CG_GibPlayer( vec3_t playerOrigin ) {
00565 vec3_t origin, velocity;
00566
00567 if ( !cg_blood.integer ) {
00568 return;
00569 }
00570
00571 VectorCopy( playerOrigin, origin );
00572 velocity[0] = crandom()*GIB_VELOCITY;
00573 velocity[1] = crandom()*GIB_VELOCITY;
00574 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00575 if ( rand() & 1 ) {
00576 CG_LaunchGib( origin, velocity, cgs.media.gibSkull );
00577 } else {
00578 CG_LaunchGib( origin, velocity, cgs.media.gibBrain );
00579 }
00580
00581
00582 if ( !cg_gibs.integer ) {
00583 return;
00584 }
00585
00586 VectorCopy( playerOrigin, origin );
00587 velocity[0] = crandom()*GIB_VELOCITY;
00588 velocity[1] = crandom()*GIB_VELOCITY;
00589 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00590 CG_LaunchGib( origin, velocity, cgs.media.gibAbdomen );
00591
00592 VectorCopy( playerOrigin, origin );
00593 velocity[0] = crandom()*GIB_VELOCITY;
00594 velocity[1] = crandom()*GIB_VELOCITY;
00595 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00596 CG_LaunchGib( origin, velocity, cgs.media.gibArm );
00597
00598 VectorCopy( playerOrigin, origin );
00599 velocity[0] = crandom()*GIB_VELOCITY;
00600 velocity[1] = crandom()*GIB_VELOCITY;
00601 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00602 CG_LaunchGib( origin, velocity, cgs.media.gibChest );
00603
00604 VectorCopy( playerOrigin, origin );
00605 velocity[0] = crandom()*GIB_VELOCITY;
00606 velocity[1] = crandom()*GIB_VELOCITY;
00607 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00608 CG_LaunchGib( origin, velocity, cgs.media.gibFist );
00609
00610 VectorCopy( playerOrigin, origin );
00611 velocity[0] = crandom()*GIB_VELOCITY;
00612 velocity[1] = crandom()*GIB_VELOCITY;
00613 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00614 CG_LaunchGib( origin, velocity, cgs.media.gibFoot );
00615
00616 VectorCopy( playerOrigin, origin );
00617 velocity[0] = crandom()*GIB_VELOCITY;
00618 velocity[1] = crandom()*GIB_VELOCITY;
00619 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00620 CG_LaunchGib( origin, velocity, cgs.media.gibForearm );
00621
00622 VectorCopy( playerOrigin, origin );
00623 velocity[0] = crandom()*GIB_VELOCITY;
00624 velocity[1] = crandom()*GIB_VELOCITY;
00625 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00626 CG_LaunchGib( origin, velocity, cgs.media.gibIntestine );
00627
00628 VectorCopy( playerOrigin, origin );
00629 velocity[0] = crandom()*GIB_VELOCITY;
00630 velocity[1] = crandom()*GIB_VELOCITY;
00631 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00632 CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
00633
00634 VectorCopy( playerOrigin, origin );
00635 velocity[0] = crandom()*GIB_VELOCITY;
00636 velocity[1] = crandom()*GIB_VELOCITY;
00637 velocity[2] = GIB_JUMP + crandom()*GIB_VELOCITY;
00638 CG_LaunchGib( origin, velocity, cgs.media.gibLeg );
00639 }
00640
00641
00642
00643
00644
00645
00646 void CG_LaunchExplode( vec3_t origin, vec3_t velocity, qhandle_t hModel ) {
00647 localEntity_t *le;
00648 refEntity_t *re;
00649
00650 le = CG_AllocLocalEntity();
00651 re = &le->refEntity;
00652
00653 le->leType = LE_FRAGMENT;
00654 le->startTime = cg.time;
00655 le->endTime = le->startTime + 10000 + random() * 6000;
00656
00657 VectorCopy( origin, re->origin );
00658 AxisCopy( axisDefault, re->axis );
00659 re->hModel = hModel;
00660
00661 le->pos.trType = TR_GRAVITY;
00662 VectorCopy( origin, le->pos.trBase );
00663 VectorCopy( velocity, le->pos.trDelta );
00664 le->pos.trTime = cg.time;
00665
00666 le->bounceFactor = 0.1f;
00667
00668 le->leBounceSoundType = LEBS_BRASS;
00669 le->leMarkType = LEMT_NONE;
00670 }
00671
00672 #define EXP_VELOCITY 100
00673 #define EXP_JUMP 150
00674
00675
00676
00677
00678
00679
00680
00681 void CG_BigExplode( vec3_t playerOrigin ) {
00682 vec3_t origin, velocity;
00683
00684 if ( !cg_blood.integer ) {
00685 return;
00686 }
00687
00688 VectorCopy( playerOrigin, origin );
00689 velocity[0] = crandom()*EXP_VELOCITY;
00690 velocity[1] = crandom()*EXP_VELOCITY;
00691 velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
00692 CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
00693
00694 VectorCopy( playerOrigin, origin );
00695 velocity[0] = crandom()*EXP_VELOCITY;
00696 velocity[1] = crandom()*EXP_VELOCITY;
00697 velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
00698 CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
00699
00700 VectorCopy( playerOrigin, origin );
00701 velocity[0] = crandom()*EXP_VELOCITY*1.5;
00702 velocity[1] = crandom()*EXP_VELOCITY*1.5;
00703 velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
00704 CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
00705
00706 VectorCopy( playerOrigin, origin );
00707 velocity[0] = crandom()*EXP_VELOCITY*2.0;
00708 velocity[1] = crandom()*EXP_VELOCITY*2.0;
00709 velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
00710 CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
00711
00712 VectorCopy( playerOrigin, origin );
00713 velocity[0] = crandom()*EXP_VELOCITY*2.5;
00714 velocity[1] = crandom()*EXP_VELOCITY*2.5;
00715 velocity[2] = EXP_JUMP + crandom()*EXP_VELOCITY;
00716 CG_LaunchExplode( origin, velocity, cgs.media.smoke2 );
00717 }
00718