diff options
author | Tim Angus <tim@ngus.net> | 2005-11-24 19:00:52 +0000 |
---|---|---|
committer | Tim Angus <tim@ngus.net> | 2005-11-24 19:00:52 +0000 |
commit | 63f0272dd145b10c349163ba465fcbcf5ac48e0d (patch) | |
tree | 0c34ea6411a1056213f2b0923d771a2726901313 /src/cgame | |
parent | e80ad4bf122eb05a5ed0c920e36cf656f98dc6e5 (diff) |
* 3D particles
* Brass ejections now done via particle system
* static_tranform particle move type
* thirdPersonOnly particle and trail system property
* Trail jitter now done in two dimensions
Diffstat (limited to 'src/cgame')
-rw-r--r-- | src/cgame/cg_animmapobj.c | 93 | ||||
-rw-r--r-- | src/cgame/cg_attachment.c | 53 | ||||
-rw-r--r-- | src/cgame/cg_ents.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_event.c | 2 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 110 | ||||
-rw-r--r-- | src/cgame/cg_main.c | 7 | ||||
-rw-r--r-- | src/cgame/cg_particles.c | 351 | ||||
-rw-r--r-- | src/cgame/cg_players.c | 20 | ||||
-rw-r--r-- | src/cgame/cg_trails.c | 102 | ||||
-rw-r--r-- | src/cgame/cg_weapons.c | 171 |
10 files changed, 505 insertions, 406 deletions
diff --git a/src/cgame/cg_animmapobj.c b/src/cgame/cg_animmapobj.c index 18f49b53..f0e964bf 100644 --- a/src/cgame/cg_animmapobj.c +++ b/src/cgame/cg_animmapobj.c @@ -13,93 +13,6 @@ #include "cg_local.h" -/* -=============== -CG_RunAMOLerpFrame - -Sets cg.snap, cg.oldFrame, and cg.backlerp -cg.time should be between oldFrameTime and frameTime after exit -=============== -*/ -static void CG_RunAMOLerpFrame( lerpFrame_t *lf ) -{ - int f, numFrames; - animation_t *anim; - - // debugging tool to get no animations - if( cg_animSpeed.integer == 0 ) - { - lf->oldFrame = lf->frame = lf->backlerp = 0; - return; - } - - // if we have passed the current frame, move it to - // oldFrame and calculate a new frame - if( cg.time >= lf->frameTime ) - { - lf->oldFrame = lf->frame; - lf->oldFrameTime = lf->frameTime; - - // get the next frame based on the animation - anim = lf->animation; - if( !anim->frameLerp ) - return; // shouldn't happen - - if( cg.time < lf->animationTime ) - lf->frameTime = lf->animationTime; // initial lerp - else - lf->frameTime = lf->oldFrameTime + anim->frameLerp; - - f = ( lf->frameTime - lf->animationTime ) / anim->frameLerp; - numFrames = anim->numFrames; - if( anim->flipflop ) - numFrames *= 2; - - if( f >= numFrames ) - { - f -= numFrames; - if( anim->loopFrames ) - { - f %= anim->loopFrames; - f += anim->numFrames - anim->loopFrames; - } - else - { - f = numFrames - 1; - // the animation is stuck at the end, so it - // can immediately transition to another sequence - lf->frameTime = cg.time; - } - } - - if( anim->reversed ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - f; - else if( anim->flipflop && f >= anim->numFrames ) - lf->frame = anim->firstFrame + anim->numFrames - 1 - ( f % anim->numFrames ); - else - lf->frame = anim->firstFrame + f; - - if( cg.time > lf->frameTime ) - { - lf->frameTime = cg.time; - if( cg_debugAnim.integer ) - CG_Printf( "Clamp lf->frameTime\n" ); - } - } - - if( lf->frameTime > cg.time + 200 ) - lf->frameTime = cg.time; - - if( lf->oldFrameTime > cg.time ) - lf->oldFrameTime = cg.time; - - // calculate current lerp value - if( lf->frameTime == lf->oldFrameTime ) - lf->backlerp = 0; - else - lf->backlerp = 1.0 - (float)( cg.time - lf->oldFrameTime ) / ( lf->frameTime - lf->oldFrameTime ); -} - /* =============== @@ -108,7 +21,7 @@ CG_DoorAnimation */ static void CG_DoorAnimation( centity_t *cent, int *old, int *now, float *backLerp ) { - CG_RunAMOLerpFrame( ¢->lerpFrame ); + CG_RunLerpFrame( ¢->lerpFrame ); *old = cent->lerpFrame.oldFrame; *now = cent->lerpFrame.frame; @@ -194,7 +107,7 @@ static void CG_AMOAnimation( centity_t *cent, int *old, int *now, float *backLer cent->lerpFrame.frameTime += delta; } - CG_RunAMOLerpFrame( ¢->lerpFrame ); + CG_RunLerpFrame( ¢->lerpFrame ); cent->miscTime = cg.time; } @@ -209,7 +122,7 @@ static void CG_AMOAnimation( centity_t *cent, int *old, int *now, float *backLer CG_animMapObj ================== */ -void CG_animMapObj( centity_t *cent ) +void CG_AnimMapObj( centity_t *cent ) { refEntity_t ent; entityState_t *es; diff --git a/src/cgame/cg_attachment.c b/src/cgame/cg_attachment.c index d8f20d90..a256318b 100644 --- a/src/cgame/cg_attachment.c +++ b/src/cgame/cg_attachment.c @@ -29,6 +29,9 @@ qboolean CG_AttachmentPoint( attachment_t *a, vec3_t v ) if( !a ) return qfalse; + // if it all breaks, then use the last point we know was correct + VectorCopy( a->lastValidAttachmentPoint, v ); + switch( a->type ) { case AT_STATIC: @@ -85,6 +88,8 @@ qboolean CG_AttachmentPoint( attachment_t *a, vec3_t v ) if( a->hasOffset ) VectorAdd( v, a->offset, v ); + VectorCopy( v, a->lastValidAttachmentPoint ); + return qtrue; } @@ -106,7 +111,6 @@ qboolean CG_AttachmentDir( attachment_t *a, vec3_t v ) switch( a->type ) { case AT_STATIC: - //FIXME: hmmmmmmm return qfalse; break; @@ -150,6 +154,53 @@ qboolean CG_AttachmentDir( attachment_t *a, vec3_t v ) /* =============== +CG_AttachmentAxis + +Return the attachment axis +=============== +*/ +qboolean CG_AttachmentAxis( attachment_t *a, vec3_t axis[ 3 ] ) +{ + centity_t *cent; + + if( !a ) + return qfalse; + + switch( a->type ) + { + case AT_STATIC: + return qfalse; + break; + + case AT_TAG: + if( !a->tagValid ) + return qfalse; + + AxisCopy( a->re.axis, axis ); + break; + + case AT_CENT: + if( !a->centValid ) + return qfalse; + + cent = &cg_entities[ a->centNum ]; + AnglesToAxis( cent->lerpAngles, axis ); + break; + + case AT_PARTICLE: + return qfalse; + break; + + default: + CG_Printf( S_COLOR_RED "ERROR: Invalid attachmentType_t in attachment\n" ); + break; + } + + return qtrue; +} + +/* +=============== CG_AttachmentVelocity If the attachment can have velocity, return it diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c index 8c047e27..b622d2f3 100644 --- a/src/cgame/cg_ents.c +++ b/src/cgame/cg_ents.c @@ -1087,7 +1087,7 @@ static void CG_AddCEntity( centity_t *cent ) break; case ET_ANIMMAPOBJ: - CG_animMapObj( cent ); + CG_AnimMapObj( cent ); break; case ET_MODELDOOR: diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index 9273922f..dfafc18e 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -744,7 +744,6 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) centity_t *source = &cg_entities[ es->generic1 ]; centity_t *target = &cg_entities[ es->clientNum ]; vec3_t sourceOffset = { 0.0f, 0.0f, 28.0f }; - vec3_t targetOffset = { 0.0f, 0.0f, -2.0f }; if( !CG_IsTrailSystemValid( &source->muzzleTS ) ) { @@ -757,7 +756,6 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) CG_AttachToCent( &source->muzzleTS->frontAttachment ); CG_AttachToCent( &source->muzzleTS->backAttachment ); CG_SetAttachmentOffset( &source->muzzleTS->frontAttachment, sourceOffset ); - CG_SetAttachmentOffset( &source->muzzleTS->backAttachment, targetOffset ); source->muzzleTSDeathTime = cg.time + cg_teslaTrailTime.integer; } diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 069dd604..8b619648 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -113,6 +113,30 @@ typedef enum //====================================================================== +// when changing animation, set animationTime to frameTime + lerping time +// The current lerp will finish out, then it will lerp to the new animation +typedef struct +{ + int oldFrame; + int oldFrameTime; // time when ->oldFrame was exactly on + + int frame; + int frameTime; // time when ->frame will be exactly on + + float backlerp; + + float yawAngle; + qboolean yawing; + float pitchAngle; + qboolean pitching; + + int animationNumber; // may include ANIM_TOGGLEBIT + animation_t *animation; + int animationTime; // time when the first frame of the animation will be exact +} lerpFrame_t; + +//====================================================================== + //attachment system typedef enum { @@ -138,6 +162,8 @@ typedef struct attachment_s qboolean hasOffset; vec3_t offset; + vec3_t lastValidAttachmentPoint; + //AT_STATIC vec3_t origin; @@ -157,7 +183,8 @@ typedef struct attachment_s //====================================================================== //particle system stuff -#define MAX_SHADER_FRAMES 32 +#define MAX_PS_SHADER_FRAMES 32 +#define MAX_PS_MODELS 8 #define MAX_EJECTORS_PER_SYSTEM 4 #define MAX_PARTICLES_PER_EJECTOR 4 @@ -172,17 +199,11 @@ typedef struct attachment_s #define PARTICLES_INFINITE -1 #define PARTICLES_SAME_AS_INITIAL -2 -/* -=============== - -COMPILE TIME STRUCTURES - -=============== -*/ - +//COMPILE TIME STRUCTURES typedef enum { PMT_STATIC, + PMT_STATIC_TRANSFORM, PMT_TAG, PMT_CENT_ANGLES, PMT_NORMAL @@ -257,12 +278,20 @@ typedef struct baseParticle_s char onDeathSystemName[ MAX_QPATH ]; qhandle_t onDeathSystemHandle; + char childTrailSystemName[ MAX_QPATH ]; + qhandle_t childTrailSystemHandle; + //particle invariant stuff - char shaderNames[ MAX_QPATH ][ MAX_SHADER_FRAMES ]; - qhandle_t shaders[ MAX_SHADER_FRAMES ]; + char shaderNames[ MAX_PS_SHADER_FRAMES ][ MAX_QPATH ]; + qhandle_t shaders[ MAX_PS_SHADER_FRAMES ]; int numFrames; float framerate; + char modelNames[ MAX_PS_MODELS ][ MAX_QPATH ]; + qhandle_t models[ MAX_PS_MODELS ]; + int numModels; + animation_t modelAnimation; + qboolean overdrawProtection; qboolean realLight; qboolean cullOnStartSolid; @@ -289,18 +318,12 @@ typedef struct baseParticleSystem_s baseParticleEjector_t *ejectors[ MAX_EJECTORS_PER_SYSTEM ]; int numEjectors; + qboolean thirdPersonOnly; qboolean registered; //whether or not the assets for this particle have been loaded } baseParticleSystem_t; -/* -=============== - -RUN TIME STRUCTURES - -=============== -*/ - +//RUN TIME STRUCTURES typedef struct particleSystem_s { baseParticleSystem_t *class; @@ -341,6 +364,8 @@ typedef struct particle_s int birthTime; int lifeTime; + qboolean atRest; + vec3_t origin; vec3_t velocity; @@ -355,6 +380,10 @@ typedef struct particle_s pLerpValues_t alpha; pLerpValues_t rotation; + qhandle_t model; + lerpFrame_t lf; + vec3_t lastAxis[ 3 ]; + qboolean valid; int frameWhenInvalidated; @@ -432,6 +461,7 @@ typedef struct baseTrailSystem_s baseTrailBeam_t *beams[ MAX_BEAMS_PER_SYSTEM ]; int numBeams; + qboolean thirdPersonOnly; qboolean registered; //whether or not the assets for this trail have been loaded } baseTrailSystem_t; @@ -458,9 +488,8 @@ typedef struct trailBeamNode_s byte alpha; byte color[ 3 ]; - float jitters[ MAX_TRAIL_BEAM_JITTERS ]; - float jitter; - + vec2_t jitters[ MAX_TRAIL_BEAM_JITTERS ]; + struct trailBeamNode_s *prev; struct trailBeamNode_s *next; @@ -476,7 +505,7 @@ typedef struct trailBeam_s trailBeamNode_t *nodes; int lastEvalTime; - + qboolean valid; int nextJitterTimes[ MAX_TRAIL_BEAM_JITTERS ]; @@ -491,28 +520,6 @@ typedef struct trailBeam_s // because corpses after respawn are outside the normal // client numbering range -// when changing animation, set animationTime to frameTime + lerping time -// The current lerp will finish out, then it will lerp to the new animation -typedef struct -{ - int oldFrame; - int oldFrameTime; // time when ->oldFrame was exactly on - - int frame; - int frameTime; // time when ->frame will be exactly on - - float backlerp; - - float yawAngle; - qboolean yawing; - float pitchAngle; - qboolean pitching; - - int animationNumber; // may include ANIM_TOGGLEBIT - animation_t *animation; - int animationTime; // time when the first frame of the animation will be exact -} lerpFrame_t; - //TA: smoothing of view and model for WW transitions #define MAXSMOOTHS 32 @@ -866,8 +873,6 @@ typedef struct weaponInfo_s qhandle_t crossHair; int crossHairSize; - void (*ejectBrassFunc)( centity_t * ); - sfxHandle_t readySound; qboolean disableIn3rdPerson; @@ -1207,9 +1212,6 @@ typedef struct qhandle_t gibSpark1; qhandle_t gibSpark2; - qhandle_t machinegunBrassModel; - qhandle_t shotgunBrassModel; - qhandle_t level2ZapTS; qhandle_t friendShader; @@ -1712,9 +1714,14 @@ void CG_HumanBuildableExplosion( vec3_t origin, vec3_t dir ); void CG_AlienBuildableExplosion( vec3_t origin, vec3_t dir ); // +// cg_animation.c +// +void CG_RunLerpFrame( lerpFrame_t *lf ); + +// // cg_animmapobj.c // -void CG_animMapObj( centity_t *cent ); +void CG_AnimMapObj( centity_t *cent ); void CG_ModelDoor( centity_t *cent ); // @@ -1869,6 +1876,7 @@ void CG_DefragmentMemory( void ); // qboolean CG_AttachmentPoint( attachment_t *a, vec3_t v ); qboolean CG_AttachmentDir( attachment_t *a, vec3_t v ); +qboolean CG_AttachmentAxis( attachment_t *a, vec3_t axis[ 3 ] ); qboolean CG_AttachmentVelocity( attachment_t *a, vec3_t v ); int CG_AttachmentCentNum( attachment_t *a ); diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index 663ace40..dbb2b1ea 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -796,9 +796,6 @@ static void CG_RegisterGraphics( void ) cgs.media.upgradeClassIconShader = trap_R_RegisterShader( "icons/icona_upgrade.tga" ); - cgs.media.machinegunBrassModel = trap_R_RegisterModel( "models/weapons/shells/rifle_shell.md3" ); - cgs.media.shotgunBrassModel = trap_R_RegisterModel( "models/weapons/shells/shotgun_shell.md3" ); - cgs.media.gibAbdomen = trap_R_RegisterModel( "models/gibs/abdomen.md3" ); cgs.media.gibArm = trap_R_RegisterModel( "models/gibs/arm.md3" ); cgs.media.gibChest = trap_R_RegisterModel( "models/gibs/chest.md3" ); @@ -1800,10 +1797,10 @@ void CG_Init( int serverMessageNum, int serverCommandSequence, int clientNum ) cg.loading = qtrue; // force players to load instead of defer - CG_LoadParticleSystems( ); + CG_LoadTrailSystems( ); CG_UpdateMediaFraction( 0.05f ); - CG_LoadTrailSystems( ); + CG_LoadParticleSystems( ); CG_UpdateMediaFraction( 0.05f ); CG_RegisterSounds( ); diff --git a/src/cgame/cg_particles.c b/src/cgame/cg_particles.c index a6ef99e5..02d4b5f8 100644 --- a/src/cgame/cg_particles.c +++ b/src/cgame/cg_particles.c @@ -93,7 +93,7 @@ static void CG_DestroyParticle( particle_t *p, vec3_t impactNormal ) { particleSystem_t *ps; - ps = CG_SpawnNewParticleSystem( p->class->childSystemHandle ); + ps = CG_SpawnNewParticleSystem( p->class->onDeathSystemHandle ); if( CG_IsParticleSystemValid( &ps ) ) { @@ -126,6 +126,7 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p particleEjector_t *pe = parent; particleSystem_t *ps = parent->parent; vec3_t attachmentPoint, attachmentVelocity; + vec3_t transform[ 3 ]; for( i = 0; i < MAX_PARTICLES; i++ ) { @@ -155,11 +156,31 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p p->rotation.initial = CG_RandomiseValue( bp->rotation.initial, bp->rotation.initialRandFrac ); p->rotation.final = CG_RandomiseValue( bp->rotation.final, bp->rotation.finalRandFrac ); + if( bp->numModels ) + { + p->model = bp->models[ rand( ) % bp->numModels ]; + + if( bp->modelAnimation.frameLerp < 0 ) + { + bp->modelAnimation.frameLerp = p->lifeTime / bp->modelAnimation.numFrames; + bp->modelAnimation.initialLerp = p->lifeTime / bp->modelAnimation.numFrames; + } + } + if( !CG_AttachmentPoint( &ps->attachment, attachmentPoint ) ) return NULL; VectorCopy( attachmentPoint, p->origin ); - VectorAdd( p->origin, bp->displacement, p->origin ); + + if( CG_AttachmentAxis( &ps->attachment, transform ) ) + { + vec3_t transDisplacement; + + VectorMatrixMultiply( bp->displacement, transform, transDisplacement ); + VectorAdd( p->origin, transDisplacement, p->origin ); + } + else + VectorAdd( p->origin, bp->displacement, p->origin ); for( j = 0; j <= 2; j++ ) p->origin[ j ] += ( crandom( ) * bp->randDisplacement ); @@ -173,6 +194,26 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p VectorCopy( bp->velMoveValues.dir, p->velocity ); break; + case PMT_STATIC_TRANSFORM: + if( !CG_AttachmentAxis( &ps->attachment, transform ) ) + { + CG_Printf( S_COLOR_RED "ERROR: a particle with velocityType " + "static_transform is not attached to something which can " + "provide a transformation\n" ); + return NULL; + } + + if( bp->velMoveValues.dirType == PMD_POINT ) + { + vec3_t transPoint; + + VectorMatrixMultiply( bp->velMoveValues.point, transform, transPoint ); + VectorSubtract( transPoint, p->origin, p->velocity ); + } + else if( bp->velMoveValues.dirType == PMD_LINEAR ) + VectorMatrixMultiply( bp->velMoveValues.dir, transform, p->velocity ); + break; + case PMT_TAG: case PMT_CENT_ANGLES: if( bp->velMoveValues.dirType == PMD_POINT ) @@ -186,7 +227,11 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p case PMT_NORMAL: if( !ps->normalValid ) + { + CG_Printf( S_COLOR_RED "ERROR: a particle with velocityType " + "normal has no normal\n" ); return NULL; + } VectorCopy( ps->normal, p->velocity ); @@ -225,6 +270,18 @@ static particle_t *CG_SpawnNewParticle( baseParticle_t *bp, particleEjector_t *p } } + //this particle has a child trail system attached + if( bp->childTrailSystemName[ 0 ] != '\0' ) + { + trailSystem_t *ts = CG_SpawnNewTrailSystem( bp->childTrailSystemHandle ); + + if( CG_IsTrailSystemValid( &ts ) ) + { + CG_SetAttachmentParticle( &ts->frontAttachment, p ); + CG_AttachToParticle( &ts->frontAttachment ); + } + } + break; } } @@ -415,11 +472,11 @@ qhandle_t CG_RegisterParticleSystem( char *name ) baseParticleEjector_t *bpe; baseParticle_t *bp; - for( i = 0; i < MAX_PARTICLE_SYSTEMS; i++ ) + for( i = 0; i < MAX_BASEPARTICLE_SYSTEMS; i++ ) { bps = &baseParticleSystems[ i ]; - if( !strcmp( bps->name, name ) ) + if( !Q_stricmpn( bps->name, name, MAX_QPATH ) ) { //already registered if( bps->registered ) @@ -436,6 +493,9 @@ qhandle_t CG_RegisterParticleSystem( char *name ) for( k = 0; k < bp->numFrames; k++ ) bp->shaders[ k ] = trap_R_RegisterShader( bp->shaderNames[ k ] ); + for( k = 0; k < bp->numModels; k++ ) + bp->models[ k ] = trap_R_RegisterModel( bp->modelNames[ k ] ); + //recursively register any children if( bp->childSystemName[ 0 ] != '\0' ) { @@ -450,6 +510,9 @@ qhandle_t CG_RegisterParticleSystem( char *name ) //the system deals with it CG_RegisterParticleSystem( bp->onDeathSystemName ); } + + if( bp->childTrailSystemName[ 0 ] != '\0' ) + bp->childTrailSystemHandle = CG_RegisterTrailSystem( bp->childTrailSystemName ); } } @@ -571,6 +634,13 @@ static qboolean CG_ParseParticle( baseParticle_t *bp, char **text_p ) } else if( !Q_stricmp( token, "shader" ) ) { + if( bp->numModels > 0 ) + { + CG_Printf( S_COLOR_RED "ERROR: 'shader' not allowed in " + "conjunction with 'model'\n", token ); + break; + } + token = COM_Parse( text_p ); if( !token ) break; @@ -581,15 +651,86 @@ static qboolean CG_ParseParticle( baseParticle_t *bp, char **text_p ) bp->framerate = atof_neg( token, qfalse ); token = COM_ParseExt( text_p, qfalse ); + if( !*token ) + break; - while( token && token[ 0 ] != 0 ) + while( *token && bp->numFrames < MAX_PS_SHADER_FRAMES ) { Q_strncpyz( bp->shaderNames[ bp->numFrames++ ], token, MAX_QPATH ); token = COM_ParseExt( text_p, qfalse ); } - if( !token ) + continue; + } + else if( !Q_stricmp( token, "model" ) ) + { + if( bp->numFrames > 0 ) + { + CG_Printf( S_COLOR_RED "ERROR: 'model' not allowed in " + "conjunction with 'shader'\n", token ); break; + } + + token = COM_ParseExt( text_p, qfalse ); + if( !*token ) + break; + + while( *token && bp->numModels < MAX_PS_MODELS ) + { + Q_strncpyz( bp->modelNames[ bp->numModels++ ], token, MAX_QPATH ); + token = COM_ParseExt( text_p, qfalse ); + } + + continue; + } + else if( !Q_stricmp( token, "modelAnimation" ) ) + { + token = COM_Parse( text_p ); + if( !*token ) + break; + + bp->modelAnimation.firstFrame = atoi_neg( token, qfalse ); + + token = COM_Parse( text_p ); + if( !*token ) + break; + + bp->modelAnimation.numFrames = atoi( token ); + bp->modelAnimation.reversed = qfalse; + bp->modelAnimation.flipflop = qfalse; + + // if numFrames is negative the animation is reversed + if( bp->modelAnimation.numFrames < 0 ) + { + bp->modelAnimation.numFrames = -bp->modelAnimation.numFrames; + bp->modelAnimation.reversed = qtrue; + } + + token = COM_Parse( text_p ); + if( !*token ) + break; + + bp->modelAnimation.loopFrames = atoi( token ); + + token = COM_Parse( text_p ); + if( !*token ) + break; + + if( !Q_stricmp( token, "sync" ) ) + { + bp->modelAnimation.frameLerp = -1; + bp->modelAnimation.initialLerp = -1; + } + else + { + float fps = atof_neg( token, qfalse ); + + if( fps == 0.0f ) + fps = 1.0f; + + bp->modelAnimation.frameLerp = 1000 / fps; + bp->modelAnimation.initialLerp = 1000 / fps; + } continue; } @@ -602,6 +743,8 @@ static qboolean CG_ParseParticle( baseParticle_t *bp, char **text_p ) if( !Q_stricmp( token, "static" ) ) bp->velMoveType = PMT_STATIC; + else if( !Q_stricmp( token, "static_transform" ) ) + bp->velMoveType = PMT_STATIC_TRANSFORM; else if( !Q_stricmp( token, "tag" ) ) bp->velMoveType = PMT_TAG; else if( !Q_stricmp( token, "cent" ) ) @@ -701,6 +844,8 @@ static qboolean CG_ParseParticle( baseParticle_t *bp, char **text_p ) if( !Q_stricmp( token, "static" ) ) bp->accMoveType = PMT_STATIC; + else if( !Q_stricmp( token, "static_transform" ) ) + bp->accMoveType = PMT_STATIC_TRANSFORM; else if( !Q_stricmp( token, "tag" ) ) bp->accMoveType = PMT_TAG; else if( !Q_stricmp( token, "cent" ) ) @@ -978,6 +1123,16 @@ static qboolean CG_ParseParticle( baseParticle_t *bp, char **text_p ) continue; } + else if( !Q_stricmp( token, "childTrailSystem" ) ) + { + token = COM_Parse( text_p ); + if( !token ) + break; + + Q_strncpyz( bp->childTrailSystemName, token, MAX_QPATH ); + + continue; + } else if( !Q_stricmp( token, "}" ) ) return qtrue; //reached the end of this particle else @@ -1176,6 +1331,8 @@ static qboolean CG_ParseParticleSystem( baseParticleSystem_t *bps, char **text_p } continue; } + else if( !Q_stricmp( token, "thirdPersonOnly" ) ) + bps->thirdPersonOnly = qtrue; else if( !Q_stricmp( token, "ejector" ) ) //acceptable text continue; else if( !Q_stricmp( token, "}" ) ) @@ -1609,6 +1766,13 @@ static void CG_EvaluateParticlePhysics( particle_t *p ) vec3_t mins, maxs; float deltaTime, bounce, radius, dot; trace_t trace; + vec3_t transform[ 3 ]; + + if( p->atRest ) + { + VectorClear( p->velocity ); + return; + } switch( bp->accMoveType ) { @@ -1620,6 +1784,26 @@ static void CG_EvaluateParticlePhysics( particle_t *p ) break; + case PMT_STATIC_TRANSFORM: + if( !CG_AttachmentAxis( &ps->attachment, transform ) ) + { + CG_Printf( S_COLOR_RED "ERROR: a particle with accelerationType " + "static_transform is not attached to something which can " + "provide a transformation\n" ); + return; + } + + if( bp->accMoveValues.dirType == PMD_POINT ) + { + vec3_t transPoint; + + VectorMatrixMultiply( bp->accMoveValues.point, transform, transPoint ); + VectorSubtract( transPoint, p->origin, acceleration ); + } + else if( bp->accMoveValues.dirType == PMD_LINEAR ) + VectorMatrixMultiply( bp->accMoveValues.dir, transform, acceleration ); + break; + case PMT_TAG: case PMT_CENT_ANGLES: if( bp->accMoveValues.dirType == PMD_POINT ) @@ -1720,6 +1904,11 @@ static void CG_EvaluateParticlePhysics( particle_t *p ) VectorScale( p->velocity, bounce, p->velocity ); + if( trace.plane.normal[ 2 ] > 0.0f && + ( p->velocity[ 2 ] < 40.0f || + p->velocity[ 2 ] < -cg.frametime * p->velocity[ 2 ] ) ) + p->atRest = qtrue; + VectorCopy( trace.endpos, p->origin ); } @@ -1827,71 +2016,129 @@ Actually render a particle */ static void CG_RenderParticle( particle_t *p ) { - refEntity_t re; - float timeFrac; - int index; - baseParticle_t *bp = p->class; - vec3_t alight, dlight, lightdir; - int i; + refEntity_t re; + float timeFrac, scale; + int index; + baseParticle_t *bp = p->class; + particleSystem_t *ps = p->parent->parent; + baseParticleSystem_t *bps = ps->class; + vec3_t alight, dlight, lightdir; + int i; + vec3_t up = { 0.0f, 0.0f, 1.0f }; memset( &re, 0, sizeof( refEntity_t ) ); - for( i = 0; i <= 3; re.shaderRGBA[ i++ ] = 0xFF ); - timeFrac = CG_CalculateTimeFrac( p->birthTime, p->lifeTime, 0 ); - re.reType = RT_SPRITE; - re.shaderTime = p->birthTime / 1000.0f; //FIXME: allow user to change? - - re.shaderRGBA[ 3 ] = (byte)( (float)0xFF * - CG_LerpValues( p->alpha.initial, - p->alpha.final, - CG_CalculateTimeFrac( p->birthTime, - p->lifeTime, - p->alpha.delay ) ) ); - - re.radius = CG_LerpValues( p->radius.initial, + scale = CG_LerpValues( p->radius.initial, p->radius.final, CG_CalculateTimeFrac( p->birthTime, p->lifeTime, p->radius.delay ) ); - re.rotation = CG_LerpValues( p->rotation.initial, - p->rotation.final, - CG_CalculateTimeFrac( p->birthTime, - p->lifeTime, - p->rotation.delay ) ); + if( bp->numFrames ) //shader based + { + re.reType = RT_SPRITE; - // if the view would be "inside" the sprite, kill the sprite - // so it doesn't add too much overdraw - if( Distance( p->origin, cg.refdef.vieworg ) < re.radius && bp->overdrawProtection ) - return; + re.shaderTime = p->birthTime / 1000.0f; //FIXME: allow user to change? - //apply environmental lighting to the particle - if( bp->realLight ) - { - trap_R_LightForPoint( p->origin, alight, dlight, lightdir ); - for( i = 0; i <= 2; i++ ) - re.shaderRGBA[ i ] = (int)alight[ i ]; - } + //apply environmental lighting to the particle + if( bp->realLight ) + { + trap_R_LightForPoint( p->origin, alight, dlight, lightdir ); + for( i = 0; i <= 2; i++ ) + re.shaderRGBA[ i ] = (int)alight[ i ]; + } + else + for( i = 0; i <= 3; re.shaderRGBA[ i++ ] = 0xFF ); - if( bp->framerate == 0.0f ) - { - //sync animation time to lifeTime of particle - index = (int)( timeFrac * ( bp->numFrames + 1 ) ); + re.shaderRGBA[ 3 ] = (byte)( (float)0xFF * + CG_LerpValues( p->alpha.initial, + p->alpha.final, + CG_CalculateTimeFrac( p->birthTime, + p->lifeTime, + p->alpha.delay ) ) ); + + re.radius = scale; + + re.rotation = CG_LerpValues( p->rotation.initial, + p->rotation.final, + CG_CalculateTimeFrac( p->birthTime, + p->lifeTime, + p->rotation.delay ) ); - if( index >= bp->numFrames ) - index = bp->numFrames - 1; + // if the view would be "inside" the sprite, kill the sprite + // so it doesn't add too much overdraw + if( Distance( p->origin, cg.refdef.vieworg ) < re.radius && bp->overdrawProtection ) + return; + + if( bp->framerate == 0.0f ) + { + //sync animation time to lifeTime of particle + index = (int)( timeFrac * ( bp->numFrames + 1 ) ); + + if( index >= bp->numFrames ) + index = bp->numFrames - 1; + + re.customShader = bp->shaders[ index ]; + } + else + { + //looping animation + index = (int)( bp->framerate * timeFrac * p->lifeTime * 0.001 ) % bp->numFrames; + re.customShader = bp->shaders[ index ]; + } - re.customShader = bp->shaders[ index ]; } - else + else if( bp->numModels ) //model based { - //looping animation - index = (int)( bp->framerate * timeFrac * p->lifeTime * 0.001 ) % bp->numFrames; - re.customShader = bp->shaders[ index ]; + re.reType = RT_MODEL; + + re.hModel = p->model; + + if( p->atRest ) + AxisCopy( p->lastAxis, re.axis ); + else + { + // convert direction of travel into axis + VectorNormalize2( p->velocity, re.axis[ 0 ] ); + + if( re.axis[ 0 ][ 0 ] == 0.0f && re.axis[ 0 ][ 1 ] == 0.0f ) + AxisCopy( axisDefault, re.axis ); + else + { + ProjectPointOnPlane( re.axis[ 2 ], up, re.axis[ 0 ] ); + VectorNormalize( re.axis[ 2 ] ); + CrossProduct( re.axis[ 2 ], re.axis[ 0 ], re.axis[ 1 ] ); + } + + AxisCopy( re.axis, p->lastAxis ); + } + + if( scale != 1.0f ) + { + VectorScale( re.axis[ 0 ], scale, re.axis[ 0 ] ); + VectorScale( re.axis[ 1 ], scale, re.axis[ 1 ] ); + VectorScale( re.axis[ 2 ], scale, re.axis[ 2 ] ); + re.nonNormalizedAxes = qtrue; + } + else + re.nonNormalizedAxes = qfalse; + + p->lf.animation = &bp->modelAnimation; + + //run animation + CG_RunLerpFrame( &p->lf ); + + re.oldframe = p->lf.oldFrame; + re.frame = p->lf.frame; + re.backlerp = p->lf.backlerp; } + if( bps->thirdPersonOnly && + CG_AttachmentCentNum( &ps->attachment ) == cg.snap->ps.clientNum ) + re.renderfx |= RF_THIRD_PERSON; + VectorCopy( p->origin, re.origin ); trap_R_AddRefEntityToScene( &re ); diff --git a/src/cgame/cg_players.c b/src/cgame/cg_players.c index 1ef18f8b..dce04324 100644 --- a/src/cgame/cg_players.c +++ b/src/cgame/cg_players.c @@ -903,13 +903,13 @@ static void CG_SetLerpFrameAnimation( clientInfo_t *ci, lerpFrame_t *lf, int new /* =============== -CG_RunLerpFrame +CG_RunPlayerLerpFrame Sets cg.snap, cg.oldFrame, and cg.backlerp cg.time should be between oldFrameTime and frameTime after exit =============== */ -static void CG_RunLerpFrame( clientInfo_t *ci, lerpFrame_t *lf, int newAnimation, float speedScale ) +static void CG_RunPlayerLerpFrame( clientInfo_t *ci, lerpFrame_t *lf, int newAnimation, float speedScale ) { int f, numFrames; animation_t *anim; @@ -1035,15 +1035,15 @@ static void CG_PlayerAnimation( centity_t *cent, int *legsOld, int *legs, float // do the shuffle turn frames locally if( cent->pe.legs.yawing && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == LEGS_IDLE ) - CG_RunLerpFrame( ci, ¢->pe.legs, LEGS_TURN, speedScale ); + CG_RunPlayerLerpFrame( ci, ¢->pe.legs, LEGS_TURN, speedScale ); else - CG_RunLerpFrame( ci, ¢->pe.legs, cent->currentState.legsAnim, speedScale ); + CG_RunPlayerLerpFrame( ci, ¢->pe.legs, cent->currentState.legsAnim, speedScale ); *legsOld = cent->pe.legs.oldFrame; *legs = cent->pe.legs.frame; *legsBackLerp = cent->pe.legs.backlerp; - CG_RunLerpFrame( ci, ¢->pe.torso, cent->currentState.torsoAnim, speedScale ); + CG_RunPlayerLerpFrame( ci, ¢->pe.torso, cent->currentState.torsoAnim, speedScale ); *torsoOld = cent->pe.torso.oldFrame; *torso = cent->pe.torso.frame; @@ -1075,9 +1075,9 @@ static void CG_PlayerNonSegAnimation( centity_t *cent, int *nonSegOld, // do the shuffle turn frames locally if( cent->pe.nonseg.yawing && ( cent->currentState.legsAnim & ~ANIM_TOGGLEBIT ) == NSPA_STAND ) - CG_RunLerpFrame( ci, ¢->pe.nonseg, NSPA_TURN, speedScale ); + CG_RunPlayerLerpFrame( ci, ¢->pe.nonseg, NSPA_TURN, speedScale ); else - CG_RunLerpFrame( ci, ¢->pe.nonseg, cent->currentState.legsAnim, speedScale ); + CG_RunPlayerLerpFrame( ci, ¢->pe.nonseg, cent->currentState.legsAnim, speedScale ); *nonSegOld = cent->pe.nonseg.oldFrame; *nonSeg = cent->pe.nonseg.frame; @@ -2347,13 +2347,13 @@ void CG_Corpse( centity_t *cent ) else if( !ci->nonsegmented ) { memset( ¢->pe.legs, 0, sizeof( lerpFrame_t ) ); - CG_RunLerpFrame( ci, ¢->pe.legs, es->legsAnim, 1 ); + CG_RunPlayerLerpFrame( ci, ¢->pe.legs, es->legsAnim, 1 ); legs.oldframe = cent->pe.legs.oldFrame; legs.frame = cent->pe.legs.frame; legs.backlerp = cent->pe.legs.backlerp; memset( ¢->pe.torso, 0, sizeof( lerpFrame_t ) ); - CG_RunLerpFrame( ci, ¢->pe.torso, es->torsoAnim, 1 ); + CG_RunPlayerLerpFrame( ci, ¢->pe.torso, es->torsoAnim, 1 ); torso.oldframe = cent->pe.torso.oldFrame; torso.frame = cent->pe.torso.frame; torso.backlerp = cent->pe.torso.backlerp; @@ -2361,7 +2361,7 @@ void CG_Corpse( centity_t *cent ) else { memset( ¢->pe.nonseg, 0, sizeof( lerpFrame_t ) ); - CG_RunLerpFrame( ci, ¢->pe.nonseg, es->legsAnim, 1 ); + CG_RunPlayerLerpFrame( ci, ¢->pe.nonseg, es->legsAnim, 1 ); legs.oldframe = cent->pe.nonseg.oldFrame; legs.frame = cent->pe.nonseg.frame; legs.backlerp = cent->pe.nonseg.backlerp; diff --git a/src/cgame/cg_trails.c b/src/cgame/cg_trails.c index e80225e4..6f9aefcf 100644 --- a/src/cgame/cg_trails.c +++ b/src/cgame/cg_trails.c @@ -25,12 +25,12 @@ static trailBeam_t trailBeams[ MAX_TRAIL_BEAMS ]; /* =============== -CG_CalculateBeamTextureCoordinates +CG_CalculateBeamNodeProperties Fills in trailBeamNode_t.textureCoord =============== */ -static void CG_CalculateBeamTextureCoordinates( trailBeam_t *tb ) +static void CG_CalculateBeamNodeProperties( trailBeam_t *tb ) { trailBeamNode_t *i = NULL; trailSystem_t *ts; @@ -129,20 +129,30 @@ Renders a beam */ static void CG_RenderBeam( trailBeam_t *tb ) { - trailBeamNode_t *i = NULL; - trailBeamNode_t *prev = NULL; - trailBeamNode_t *next = NULL; - vec3_t up; - polyVert_t verts[ ( MAX_TRAIL_BEAM_NODES - 1 ) * 4 ]; - int numVerts = 0; - baseTrailBeam_t *btb; + trailBeamNode_t *i = NULL; + trailBeamNode_t *prev = NULL; + trailBeamNode_t *next = NULL; + vec3_t up; + polyVert_t verts[ ( MAX_TRAIL_BEAM_NODES - 1 ) * 4 ]; + int numVerts = 0; + baseTrailBeam_t *btb; + trailSystem_t *ts; + baseTrailSystem_t *bts; if( !tb || !tb->nodes ) return; btb = tb->class; + ts = tb->parent; + bts = ts->class; - CG_CalculateBeamTextureCoordinates( tb ); + if( bts->thirdPersonOnly && + ( CG_AttachmentCentNum( &ts->frontAttachment ) == cg.snap->ps.clientNum || + CG_AttachmentCentNum( &ts->backAttachment ) == cg.snap->ps.clientNum ) && + !cg.renderingThirdPerson ) + return; + + CG_CalculateBeamNodeProperties( tb ); i = tb->nodes; @@ -171,7 +181,7 @@ static void CG_RenderBeam( trailBeam_t *tb ) if( prev ) { - VectorMA( i->position, i->halfWidth + i->jitter, up, verts[ numVerts ].xyz ); + VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 1.0f; @@ -185,7 +195,7 @@ static void CG_RenderBeam( trailBeam_t *tb ) numVerts++; - VectorMA( i->position, -i->halfWidth + i->jitter, up, verts[ numVerts ].xyz ); + VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 0.0f; @@ -202,7 +212,7 @@ static void CG_RenderBeam( trailBeam_t *tb ) if( next ) { - VectorMA( i->position, -i->halfWidth + i->jitter, up, verts[ numVerts ].xyz ); + VectorMA( i->position, -i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 0.0f; @@ -216,7 +226,7 @@ static void CG_RenderBeam( trailBeam_t *tb ) numVerts++; - VectorMA( i->position, i->halfWidth + i->jitter, up, verts[ numVerts ].xyz ); + VectorMA( i->position, i->halfWidth, up, verts[ numVerts ].xyz ); verts[ numVerts ].st[ 0 ] = i->textureCoord; verts[ numVerts ].st[ 1 ] = 1.0f; @@ -444,7 +454,10 @@ static void CG_ApplyJitters( trailBeam_t *tb ) if( tb->nextJitterTimes[ j ] <= cg.time ) { for( i = tb->nodes; i; i = i->next ) - i->jitters[ j ] = ( crandom( ) * btb->jitters[ j ].magnitude ); + { + i->jitters[ j ][ 0 ] = ( crandom( ) * btb->jitters[ j ].magnitude ); + i->jitters[ j ][ 1 ] = ( crandom( ) * btb->jitters[ j ].magnitude ); + } tb->nextJitterTimes[ j ] = cg.time + btb->jitters[ j ].period; } @@ -464,12 +477,46 @@ static void CG_ApplyJitters( trailBeam_t *tb ) for( i = start; i; i = i->next ) { - i->jitter = 0.0f; + vec3_t forward, right, up; + trailBeamNode_t *prev; + trailBeamNode_t *next; + float upJitter = 0.0f, rightJitter = 0.0f; + + prev = i->prev; + next = i->next; + + if( prev && next ) + { + //this node has two neighbours + GetPerpendicularViewVector( cg.refdef.vieworg, next->position, prev->position, up ); + VectorSubtract( next->position, prev->position, forward ); + } + else if( !prev && next ) + { + //this is the front + GetPerpendicularViewVector( cg.refdef.vieworg, next->position, i->position, up ); + VectorSubtract( next->position, i->position, forward ); + } + else if( prev && !next ) + { + //this is the back + GetPerpendicularViewVector( cg.refdef.vieworg, i->position, prev->position, up ); + VectorSubtract( i->position, prev->position, forward ); + } + + VectorNormalize( forward ); + CrossProduct( forward, up, right ); + VectorNormalize( right ); for( j = 0; j < btb->numJitters; j++ ) - i->jitter += i->jitters[ j ]; + { + upJitter += i->jitters[ j ][ 0 ]; + rightJitter += i->jitters[ j ][ 1 ]; + } + + VectorMA( i->position, upJitter, up, i->position ); + VectorMA( i->position, rightJitter, right, i->position ); - //mmmm... nice if( i == end ) break; } @@ -513,7 +560,8 @@ static void CG_UpdateBeam( trailBeam_t *tb ) if( !tb->nodes->next && CG_Attached( &ts->frontAttachment ) ) { // this is the first node to be added - CG_AttachmentPoint( &ts->frontAttachment, i->refPosition ); + if( !CG_AttachmentPoint( &ts->frontAttachment, i->refPosition ) ) + CG_DestroyTrailSystem( &ts ); } else VectorCopy( i->prev->refPosition, i->refPosition ); @@ -536,8 +584,12 @@ static void CG_UpdateBeam( trailBeam_t *tb ) return; } - CG_AttachmentPoint( &ts->frontAttachment, front ); - CG_AttachmentPoint( &ts->backAttachment, back ); + if( !CG_AttachmentPoint( &ts->frontAttachment, front ) ) + CG_DestroyTrailSystem( &ts ); + + if( !CG_AttachmentPoint( &ts->backAttachment, back ) ) + CG_DestroyTrailSystem( &ts ); + VectorSubtract( back, front, dir ); for( j = 0, i = tb->nodes; i; i = i->next, j++ ) @@ -585,7 +637,9 @@ static void CG_UpdateBeam( trailBeam_t *tb ) } } - CG_AttachmentPoint( &ts->frontAttachment, tb->nodes->refPosition ); + if( !CG_AttachmentPoint( &ts->frontAttachment, tb->nodes->refPosition ) ) + CG_DestroyTrailSystem( &ts ); + VectorCopy( tb->nodes->refPosition, tb->nodes->position ); } @@ -940,6 +994,8 @@ static qboolean CG_ParseTrailSystem( baseTrailSystem_t *bts, char **text_p, cons } continue; } + else if( !Q_stricmp( token, "thirdPersonOnly" ) ) + bts->thirdPersonOnly = qtrue; else if( !Q_stricmp( token, "beam" ) ) //acceptable text continue; else if( !Q_stricmp( token, "}" ) ) @@ -1118,7 +1174,7 @@ qhandle_t CG_RegisterTrailSystem( char *name ) baseTrailSystem_t *bts; baseTrailBeam_t *btb; - for( i = 0; i < MAX_TRAIL_SYSTEMS; i++ ) + for( i = 0; i < MAX_BASETRAIL_SYSTEMS; i++ ) { bts = &baseTrailSystems[ i ]; diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index 935342ac..7df8b0fa 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -18,147 +18,6 @@ #include "cg_local.h" /* -========================== -CG_MachineGunEjectBrass -========================== -*/ -static void CG_MachineGunEjectBrass( centity_t *cent ) -{ - localEntity_t *le; - refEntity_t *re; - vec3_t velocity, xvelocity; - vec3_t offset, xoffset; - float waterScale = 1.0f; - vec3_t v[ 3 ]; - - if( cg_brassTime.integer <= 0 ) - return; - - le = CG_AllocLocalEntity( ); - re = &le->refEntity; - - velocity[ 0 ] = 0; - velocity[ 1 ] = -50 + 40 * crandom( ); - velocity[ 2 ] = 100 + 50 * crandom( ); - - le->leType = LE_FRAGMENT; - le->startTime = cg.time; - le->endTime = le->startTime + cg_brassTime.integer + ( cg_brassTime.integer / 4 ) * random( ); - - le->pos.trType = TR_GRAVITY; - le->pos.trTime = cg.time - ( rand( ) & 15 ); - - AnglesToAxis( cent->lerpAngles, v ); - - offset[ 0 ] = 8; - offset[ 1 ] = -4; - offset[ 2 ] = 24; - - xoffset[ 0 ] = offset[ 0 ] * v[ 0 ][ 0 ] + offset[ 1 ] * v[ 1 ][ 0 ] + offset[ 2 ] * v[ 2 ][ 0 ]; - xoffset[ 1 ] = offset[ 0 ] * v[ 0 ][ 1 ] + offset[ 1 ] * v[ 1 ][ 1 ] + offset[ 2 ] * v[ 2 ][ 1 ]; - xoffset[ 2 ] = offset[ 0 ] * v[ 0 ][ 2 ] + offset[ 1 ] * v[ 1 ][ 2 ] + offset[ 2 ] * v[ 2 ][ 2 ]; - VectorAdd( cent->lerpOrigin, xoffset, re->origin ); - - VectorCopy( re->origin, le->pos.trBase ); - - if( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) - waterScale = 0.10f; - - xvelocity[ 0 ] = velocity[ 0 ] * v[ 0 ][ 0 ] + velocity[ 1 ] * v[ 1 ][ 0 ] + velocity[ 2 ] * v[ 2 ][ 0 ]; - xvelocity[ 1 ] = velocity[ 0 ] * v[ 0 ][ 1 ] + velocity[ 1 ] * v[ 1 ][ 1 ] + velocity[ 2 ] * v[ 2 ][ 1 ]; - xvelocity[ 2 ] = velocity[ 0 ] * v[ 0 ][ 2 ] + velocity[ 1 ] * v[ 1 ][ 2 ] + velocity[ 2 ] * v[ 2 ][ 2 ]; - VectorScale( xvelocity, waterScale, le->pos.trDelta ); - - AxisCopy( axisDefault, re->axis ); - re->hModel = cgs.media.machinegunBrassModel; - - le->bounceFactor = 0.4 * waterScale; - - le->angles.trType = TR_LINEAR; - le->angles.trTime = cg.time; - le->angles.trBase[ 0 ] = rand( ) & 31; - le->angles.trBase[ 1 ] = rand( ) & 31; - le->angles.trBase[ 2 ] = rand( ) & 31; - le->angles.trDelta[ 0 ] = 2; - le->angles.trDelta[ 1 ] = 1; - le->angles.trDelta[ 2 ] = 0; - - le->leFlags = LEF_TUMBLE; - le->leBounceSoundType = LEBS_BRASS; - le->leMarkType = LEMT_NONE; -} - -/* -========================== -CG_ShotgunEjectBrass -========================== -*/ -static void CG_ShotgunEjectBrass( centity_t *cent ) -{ - localEntity_t *le; - refEntity_t *re; - vec3_t velocity, xvelocity; - vec3_t offset, xoffset; - vec3_t v[ 3 ]; - float waterScale = 1.0f; - - if( cg_brassTime.integer <= 0 ) - return; - - le = CG_AllocLocalEntity( ); - re = &le->refEntity; - - velocity[ 0 ] = 60 + 60 * crandom( ); - velocity[ 1 ] = 40 + 10 * crandom( ); - velocity[ 2 ] = 100 + 50 * crandom( ); - - le->leType = LE_FRAGMENT; - le->startTime = cg.time; - le->endTime = le->startTime + cg_brassTime.integer * 3 + cg_brassTime.integer * random( ); - - le->pos.trType = TR_GRAVITY; - le->pos.trTime = cg.time; - - AnglesToAxis( cent->lerpAngles, v ); - - offset[ 0 ] = 8; - offset[ 1 ] = 0; - offset[ 2 ] = 24; - - xoffset[ 0 ] = offset[ 0 ] * v[ 0 ][ 0 ] + offset[ 1 ] * v[ 1 ][ 0 ] + offset[ 2 ] * v[ 2 ][ 0 ]; - xoffset[ 1 ] = offset[ 0 ] * v[ 0 ][ 1 ] + offset[ 1 ] * v[ 1 ][ 1 ] + offset[ 2 ] * v[ 2 ][ 1 ]; - xoffset[ 2 ] = offset[ 0 ] * v[ 0 ][ 2 ] + offset[ 1 ] * v[ 1 ][ 2 ] + offset[ 2 ] * v[ 2 ][ 2 ]; - VectorAdd( cent->lerpOrigin, xoffset, re->origin ); - VectorCopy( re->origin, le->pos.trBase ); - - if( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) - waterScale = 0.10f; - - xvelocity[ 0 ] = velocity[ 0 ] * v[ 0 ][ 0 ] + velocity[ 1 ] * v[ 1 ][ 0 ] + velocity[ 2 ] * v[ 2 ][ 0 ]; - xvelocity[ 1 ] = velocity[ 0 ] * v[ 0 ][ 1 ] + velocity[ 1 ] * v[ 1 ][ 1 ] + velocity[ 2 ] * v[ 2 ][ 1 ]; - xvelocity[ 2 ] = velocity[ 0 ] * v[ 0 ][ 2 ] + velocity[ 1 ] * v[ 1 ][ 2 ] + velocity[ 2 ] * v[ 2 ][ 2 ]; - VectorScale( xvelocity, waterScale, le->pos.trDelta ); - - AxisCopy( axisDefault, re->axis ); - re->hModel = cgs.media.shotgunBrassModel; - le->bounceFactor = 0.3f; - - le->angles.trType = TR_LINEAR; - le->angles.trTime = cg.time; - le->angles.trBase[ 0 ] = rand( )&31; - le->angles.trBase[ 1 ] = rand( )&31; - le->angles.trBase[ 2 ] = rand( )&31; - le->angles.trDelta[ 0 ] = 1; - le->angles.trDelta[ 1 ] = 0.5; - le->angles.trDelta[ 2 ] = 0; - - le->leFlags = LEF_TUMBLE; - le->leBounceSoundType = LEBS_BRASS; - le->leMarkType = LEMT_NONE; -} - - -/* ================= CG_RegisterUpgrade @@ -809,19 +668,6 @@ void CG_RegisterWeapon( int weaponNum ) //FIXME: for( i = WPM_NONE + 1; i < WPM_NUM_WEAPONMODES; i++ ) weaponInfo->wim[ i ].loopFireSound = qfalse; - - switch( weaponNum ) - { - case WP_MACHINEGUN: - case WP_MGTURRET: - case WP_CHAINGUN: - weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass; - break; - - case WP_SHOTGUN: - weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass; - break; - } } /* @@ -1670,23 +1516,6 @@ void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode ) if( wi->wim[ weaponMode ].flashSound[ c ] ) trap_S_StartSound( NULL, es->number, CHAN_WEAPON, wi->wim[ weaponMode ].flashSound[ c ] ); } - - // do brass ejection - if( wi->ejectBrassFunc && cg_brassTime.integer > 0 ) - { - if( es->eType == ET_BUILDABLE ) - { - //yucko hack to get turret brass ejecting with the barrel instead of the base - vec3_t temp; - - VectorCopy( cent->lerpAngles, temp ); - VectorCopy( es->angles2, cent->lerpAngles ); - wi->ejectBrassFunc( cent ); - VectorCopy( temp, cent->lerpAngles ); - } - else - wi->ejectBrassFunc( cent ); - } } |