diff options
Diffstat (limited to 'mod/src/cgame/cg_ents.c')
-rw-r--r-- | mod/src/cgame/cg_ents.c | 1225 |
1 files changed, 0 insertions, 1225 deletions
diff --git a/mod/src/cgame/cg_ents.c b/mod/src/cgame/cg_ents.c deleted file mode 100644 index b622d2f3..00000000 --- a/mod/src/cgame/cg_ents.c +++ /dev/null @@ -1,1225 +0,0 @@ -// Copyright (C) 1999-2000 Id Software, Inc. -// -// cg_ents.c -- present snapshot entities, happens every single frame - -/* - * Portions Copyright (C) 2000-2001 Tim Angus - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the OSML - Open Source Modification License v1.0 as - * described in the file COPYING which is distributed with this source - * code. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - */ - -#include "cg_local.h" - -/* -====================== -CG_DrawBoxFace - -Draws a bounding box face -====================== -*/ -static void CG_DrawBoxFace( vec3_t a, vec3_t b, vec3_t c, vec3_t d ) -{ - polyVert_t verts[ 4 ]; - vec4_t color = { 255.0f, 0.0f, 0.0f, 128.0f }; - - VectorCopy( d, verts[ 0 ].xyz ); - verts[ 0 ].st[ 0 ] = 1; - verts[ 0 ].st[ 1 ] = 1; - Vector4Copy( color, verts[ 0 ].modulate ); - - VectorCopy( c, verts[ 1 ].xyz ); - verts[ 1 ].st[ 0 ] = 1; - verts[ 1 ].st[ 1 ] = 0; - Vector4Copy( color, verts[ 1 ].modulate ); - - VectorCopy( b, verts[ 2 ].xyz ); - verts[ 2 ].st[ 0 ] = 0; - verts[ 2 ].st[ 1 ] = 0; - Vector4Copy( color, verts[ 2 ].modulate ); - - VectorCopy( a, verts[ 3 ].xyz ); - verts[ 3 ].st[ 0 ] = 0; - verts[ 3 ].st[ 1 ] = 1; - Vector4Copy( color, verts[ 3 ].modulate ); - - trap_R_AddPolyToScene( cgs.media.outlineShader, 4, verts ); -} - -/* -====================== -CG_DrawBoundingBox - -Draws a bounding box -====================== -*/ -void CG_DrawBoundingBox( vec3_t origin, vec3_t mins, vec3_t maxs ) -{ - vec3_t ppp, mpp, mmp, pmp; - vec3_t mmm, pmm, ppm, mpm; - - ppp[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - ppp[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - ppp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - mpp[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mpp[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - mpp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - mmp[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mmp[ 1 ] = origin[ 1 ] + mins[ 1 ]; - mmp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - pmp[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - pmp[ 1 ] = origin[ 1 ] + mins[ 1 ]; - pmp[ 2 ] = origin[ 2 ] + maxs[ 2 ]; - - ppm[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - ppm[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - ppm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - mpm[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mpm[ 1 ] = origin[ 1 ] + maxs[ 1 ]; - mpm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - mmm[ 0 ] = origin[ 0 ] + mins[ 0 ]; - mmm[ 1 ] = origin[ 1 ] + mins[ 1 ]; - mmm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - pmm[ 0 ] = origin[ 0 ] + maxs[ 0 ]; - pmm[ 1 ] = origin[ 1 ] + mins[ 1 ]; - pmm[ 2 ] = origin[ 2 ] + mins[ 2 ]; - - //phew! - - CG_DrawBoxFace( ppp, mpp, mmp, pmp ); - CG_DrawBoxFace( ppp, pmp, pmm, ppm ); - CG_DrawBoxFace( mpp, ppp, ppm, mpm ); - CG_DrawBoxFace( mmp, mpp, mpm, mmm ); - CG_DrawBoxFace( pmp, mmp, mmm, pmm ); - CG_DrawBoxFace( mmm, mpm, ppm, pmm ); -} - - -/* -====================== -CG_PositionEntityOnTag - -Modifies the entities position and axis by the given -tag location -====================== -*/ -void CG_PositionEntityOnTag( refEntity_t *entity, const refEntity_t *parent, - qhandle_t parentModel, char *tagName ) -{ - int i; - orientation_t lerped; - - // lerp the tag - trap_R_LerpTag( &lerped, parentModel, parent->oldframe, parent->frame, - 1.0 - parent->backlerp, tagName ); - - // FIXME: allow origin offsets along tag? - VectorCopy( parent->origin, entity->origin ); - for( i = 0; i < 3; i++ ) - VectorMA( entity->origin, lerped.origin[ i ], parent->axis[ i ], entity->origin ); - - // had to cast away the const to avoid compiler problems... - MatrixMultiply( lerped.axis, ( (refEntity_t *)parent )->axis, entity->axis ); - entity->backlerp = parent->backlerp; -} - - -/* -====================== -CG_PositionRotatedEntityOnTag - -Modifies the entities position and axis by the given -tag location -====================== -*/ -void CG_PositionRotatedEntityOnTag( refEntity_t *entity, const refEntity_t *parent, - qhandle_t parentModel, char *tagName ) -{ - int i; - orientation_t lerped; - vec3_t tempAxis[ 3 ]; - -//AxisClear( entity->axis ); - // lerp the tag - trap_R_LerpTag( &lerped, parentModel, parent->oldframe, parent->frame, - 1.0 - parent->backlerp, tagName ); - - // FIXME: allow origin offsets along tag? - VectorCopy( parent->origin, entity->origin ); - for( i = 0; i < 3; i++ ) - VectorMA( entity->origin, lerped.origin[ i ], parent->axis[ i ], entity->origin ); - - // had to cast away the const to avoid compiler problems... - MatrixMultiply( entity->axis, lerped.axis, tempAxis ); - MatrixMultiply( tempAxis, ( (refEntity_t *)parent )->axis, entity->axis ); -} - - - -/* -========================================================================== - -FUNCTIONS CALLED EACH FRAME - -========================================================================== -*/ - -/* -====================== -CG_SetEntitySoundPosition - -Also called by event processing code -====================== -*/ -void CG_SetEntitySoundPosition( centity_t *cent ) -{ - if( cent->currentState.solid == SOLID_BMODEL ) - { - vec3_t origin; - float *v; - - v = cgs.inlineModelMidpoints[ cent->currentState.modelindex ]; - VectorAdd( cent->lerpOrigin, v, origin ); - trap_S_UpdateEntityPosition( cent->currentState.number, origin ); - } - else - trap_S_UpdateEntityPosition( cent->currentState.number, cent->lerpOrigin ); -} - -/* -================== -CG_EntityEffects - -Add continuous entity effects, like local entity emission and lighting -================== -*/ -static void CG_EntityEffects( centity_t *cent ) -{ - // update sound origins - CG_SetEntitySoundPosition( cent ); - - // add loop sound - if( cent->currentState.loopSound ) - { - if( cent->currentState.eType != ET_SPEAKER ) - { - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, - cgs.gameSounds[ cent->currentState.loopSound ] ); - } - else - { - trap_S_AddRealLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, - cgs.gameSounds[ cent->currentState.loopSound ] ); - } - } - - - // constant light glow - if ( cent->currentState.constantLight ) - { - int cl; - int i, r, g, b; - - cl = cent->currentState.constantLight; - r = cl & 255; - g = ( cl >> 8 ) & 255; - b = ( cl >> 16 ) & 255; - i = ( ( cl >> 24 ) & 255 ) * 4; - trap_R_AddLightToScene( cent->lerpOrigin, i, r, g, b ); - } - - if( cg.time > cent->muzzleTSDeathTime && CG_IsTrailSystemValid( ¢->muzzleTS ) ) - CG_DestroyTrailSystem( ¢->muzzleTS ); -} - - -/* -================== -CG_General -================== -*/ -static void CG_General( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // if set to invisible, skip - if( !s1->modelindex ) - return; - - memset( &ent, 0, sizeof( ent ) ); - - // set frame - - ent.frame = s1->frame; - ent.oldframe = ent.frame; - ent.backlerp = 0; - - VectorCopy( cent->lerpOrigin, ent.origin); - VectorCopy( cent->lerpOrigin, ent.oldorigin); - - ent.hModel = cgs.gameModels[ s1->modelindex ]; - - // player model - if( s1->number == cg.snap->ps.clientNum ) - ent.renderfx |= RF_THIRD_PERSON; // only draw from mirrors - - // convert angles to axis - AnglesToAxis( cent->lerpAngles, ent.axis ); - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); -} - -/* -================== -CG_Speaker - -Speaker entities can automatically play sounds -================== -*/ -static void CG_Speaker( centity_t *cent ) -{ - if( ! cent->currentState.clientNum ) - { // FIXME: use something other than clientNum... - return; // not auto triggering - } - - if( cg.time < cent->miscTime ) - return; - - trap_S_StartSound( NULL, cent->currentState.number, CHAN_ITEM, cgs.gameSounds[ cent->currentState.eventParm ] ); - - // ent->s.frame = ent->wait * 10; - // ent->s.clientNum = ent->random * 10; - cent->miscTime = cg.time + cent->currentState.frame * 100 + cent->currentState.clientNum * 100 * crandom( ); -} - - -//============================================================================ - -/* -=============== -CG_LaunchMissile -=============== -*/ -static void CG_LaunchMissile( centity_t *cent ) -{ - entityState_t *es; - const weaponInfo_t *wi; - particleSystem_t *ps; - trailSystem_t *ts; - weapon_t weapon; - weaponMode_t weaponMode; - - es = ¢->currentState; - - weapon = es->weapon; - if( weapon > WP_NUM_WEAPONS ) - weapon = WP_NONE; - - wi = &cg_weapons[ weapon ]; - weaponMode = es->generic1; - - if( wi->wim[ weaponMode ].missileParticleSystem ) - { - ps = CG_SpawnNewParticleSystem( wi->wim[ weaponMode ].missileParticleSystem ); - - if( CG_IsParticleSystemValid( &ps ) ) - { - CG_SetAttachmentCent( &ps->attachment, cent ); - CG_AttachToCent( &ps->attachment ); - } - } - - if( wi->wim[ weaponMode ].missileTrailSystem ) - { - ts = CG_SpawnNewTrailSystem( wi->wim[ weaponMode ].missileTrailSystem ); - - if( CG_IsTrailSystemValid( &ts ) ) - { - CG_SetAttachmentCent( &ts->frontAttachment, cent ); - CG_AttachToCent( &ts->frontAttachment ); - } - } -} - -/* -=============== -CG_Missile -=============== -*/ -static void CG_Missile( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *es; - const weaponInfo_t *wi; - weapon_t weapon; - weaponMode_t weaponMode; - const weaponInfoMode_t *wim; - - es = ¢->currentState; - - weapon = es->weapon; - if( weapon > WP_NUM_WEAPONS ) - weapon = WP_NONE; - - wi = &cg_weapons[ weapon ]; - weaponMode = es->generic1; - - wim = &wi->wim[ weaponMode ]; - - // calculate the axis - VectorCopy( es->angles, cent->lerpAngles ); - - // add dynamic light - if( wim->missileDlight ) - { - trap_R_AddLightToScene( cent->lerpOrigin, wim->missileDlight, - wim->missileDlightColor[ 0 ], - wim->missileDlightColor[ 1 ], - wim->missileDlightColor[ 2 ] ); - } - - // add missile sound - if( wim->missileSound ) - { - vec3_t velocity; - - BG_EvaluateTrajectoryDelta( ¢->currentState.pos, cg.time, velocity ); - - trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, velocity, wim->missileSound ); - } - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - - if( wim->usesSpriteMissle ) - { - ent.reType = RT_SPRITE; - ent.radius = wim->missileSpriteSize; - ent.rotation = 0; - ent.customShader = wim->missileSprite; - ent.shaderRGBA[ 0 ] = 0xFF; - ent.shaderRGBA[ 1 ] = 0xFF; - ent.shaderRGBA[ 2 ] = 0xFF; - ent.shaderRGBA[ 3 ] = 0xFF; - } - else - { - ent.hModel = wim->missileModel; - ent.renderfx = wim->missileRenderfx | RF_NOSHADOW; - - // convert direction of travel into axis - if( VectorNormalize2( es->pos.trDelta, ent.axis[ 0 ] ) == 0 ) - ent.axis[ 0 ][ 2 ] = 1; - - // spin as it moves - if( es->pos.trType != TR_STATIONARY && wim->missileRotates ) - RotateAroundDirection( ent.axis, cg.time / 4 ); - else - RotateAroundDirection( ent.axis, es->time ); - - if( wim->missileAnimates ) - { - int timeSinceStart = cg.time - es->time; - - if( wim->missileAnimLooping ) - { - ent.frame = wim->missileAnimStartFrame + - (int)( ( timeSinceStart / 1000.0f ) * wim->missileAnimFrameRate ) % - wim->missileAnimNumFrames; - } - else - { - ent.frame = wim->missileAnimStartFrame + - (int)( ( timeSinceStart / 1000.0f ) * wim->missileAnimFrameRate ); - - if( ent.frame > ( wim->missileAnimStartFrame + wim->missileAnimNumFrames ) ) - ent.frame = wim->missileAnimStartFrame + wim->missileAnimNumFrames; - } - } - } - - //only refresh if there is something to display - if( wim->missileSprite || wim->missileModel ) - trap_R_AddRefEntityToScene( &ent ); -} - -/* -=============== -CG_Mover -=============== -*/ -static void CG_Mover( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - AnglesToAxis( cent->lerpAngles, ent.axis ); - - ent.renderfx = RF_NOSHADOW; - - // flicker between two skins (FIXME?) - ent.skinNum = ( cg.time >> 6 ) & 1; - - // get the model, either as a bmodel or a modelindex - if( s1->solid == SOLID_BMODEL ) - ent.hModel = cgs.inlineDrawModel[ s1->modelindex ]; - else - ent.hModel = cgs.gameModels[ s1->modelindex ]; - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); - - // add the secondary model - if( s1->modelindex2 ) - { - ent.skinNum = 0; - ent.hModel = cgs.gameModels[ s1->modelindex2 ]; - trap_R_AddRefEntityToScene( &ent ); - } - -} - -/* -=============== -CG_Beam - -Also called as an event -=============== -*/ -void CG_Beam( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( s1->pos.trBase, ent.origin ); - VectorCopy( s1->origin2, ent.oldorigin ); - AxisClear( ent.axis ); - ent.reType = RT_BEAM; - - ent.renderfx = RF_NOSHADOW; - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); -} - - -/* -=============== -CG_Portal -=============== -*/ -static void CG_Portal( centity_t *cent ) -{ - refEntity_t ent; - entityState_t *s1; - - s1 = ¢->currentState; - - // create the render entity - memset( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( s1->origin2, ent.oldorigin ); - ByteToDir( s1->eventParm, ent.axis[ 0 ] ); - PerpendicularVector( ent.axis[ 1 ], ent.axis[ 0 ] ); - - // negating this tends to get the directions like they want - // we really should have a camera roll value - VectorSubtract( vec3_origin, ent.axis[ 1 ], ent.axis[ 1 ] ); - - CrossProduct( ent.axis[ 0 ], ent.axis[ 1 ], ent.axis[ 2 ] ); - ent.reType = RT_PORTALSURFACE; - ent.oldframe = s1->powerups; - ent.frame = s1->frame; // rotation speed - ent.skinNum = s1->clientNum / 256.0 * 360; // roll offset - - // add to refresh list - trap_R_AddRefEntityToScene( &ent ); -} - -//============================================================================ - -#define SETBOUNDS(v1,v2,r) ((v1)[0]=(-r/2),(v1)[1]=(-r/2),(v1)[2]=(-r/2),\ - (v2)[0]=(r/2),(v2)[1]=(r/2),(v2)[2]=(r/2)) -#define RADIUSSTEP 0.5f - -#define FLARE_OFF 0 -#define FLARE_NOFADE 1 -#define FLARE_TIMEFADE 2 -#define FLARE_REALFADE 3 - -/* -========================= -CG_LightFlare -========================= -*/ -static void CG_LightFlare( centity_t *cent ) -{ - refEntity_t flare; - entityState_t *es; - vec3_t forward, delta; - float len; - trace_t tr; - float maxAngle; - vec3_t mins, maxs, start, end; - float srcRadius, srLocal, ratio = 1.0f; - int entityNum; - - es = ¢->currentState; - - if( cg.renderingThirdPerson ) - entityNum = MAGIC_TRACE_HACK; - else - entityNum = cg.predictedPlayerState.clientNum; - - //don't draw light flares - if( cg_lightFlare.integer == FLARE_OFF ) - return; - - //flare is "off" - if( es->eFlags & EF_NODRAW ) - return; - - CG_Trace( &tr, cg.refdef.vieworg, NULL, NULL, es->angles2, - entityNum, MASK_SHOT ); - - //if there is no los between the view and the flare source - //it definately cannot be seen - if( tr.fraction < 1.0f || tr.allsolid ) - return; - - memset( &flare, 0, sizeof( flare ) ); - - flare.reType = RT_SPRITE; - flare.customShader = cgs.gameShaders[ es->modelindex ]; - flare.shaderRGBA[ 0 ] = 0xFF; - flare.shaderRGBA[ 1 ] = 0xFF; - flare.shaderRGBA[ 2 ] = 0xFF; - flare.shaderRGBA[ 3 ] = 0xFF; - - //flares always drawn before the rest of the scene - flare.renderfx |= RF_DEPTHHACK; - - //bunch of geometry - AngleVectors( es->angles, forward, NULL, NULL ); - VectorCopy( cent->lerpOrigin, flare.origin ); - VectorSubtract( flare.origin, cg.refdef.vieworg, delta ); - len = VectorLength( delta ); - VectorNormalize( delta ); - - //flare is too close to camera to be drawn - if( len < es->generic1 ) - return; - - //don't bother for flares behind the view plane - if( DotProduct( delta, cg.refdef.viewaxis[ 0 ] ) < 0.0 ) - return; - - //only recalculate radius and ratio every three frames - if( !( cg.clientFrame % 2 ) ) - { - //can only see the flare when in front of it - flare.radius = len / es->origin2[ 0 ]; - - if( es->origin2[ 2 ] == 0 ) - srcRadius = srLocal = flare.radius / 2.0f; - else - srcRadius = srLocal = len / es->origin2[ 2 ]; - - maxAngle = es->origin2[ 1 ]; - - if( maxAngle > 0.0f ) - { - float radiusMod = 1.0f - ( 180.0f - RAD2DEG( - acos( DotProduct( delta, forward ) ) ) ) / maxAngle; - - if( es->eFlags & EF_NODRAW ) - flare.radius *= radiusMod; - else if( radiusMod < 0.0f ) - flare.radius = 0.0f; - } - - if( flare.radius < 0.0f ) - flare.radius = 0.0f; - - VectorMA( flare.origin, -flare.radius, delta, end ); - VectorMA( cg.refdef.vieworg, flare.radius, delta, start ); - - if( cg_lightFlare.integer == FLARE_REALFADE ) - { - //draw "correct" albeit inefficient flares - srLocal = cent->lfs.lastSrcRadius; - - //flare radius is likely to be the same as last frame so start with it - do - { - srLocal += RADIUSSTEP; - SETBOUNDS( mins, maxs, srLocal ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - } while( ( tr.fraction == 1.0f && !tr.startsolid ) && ( srLocal < srcRadius ) ); - - srLocal -= RADIUSSTEP; - - //shink the flare until there is a los - do - { - SETBOUNDS( mins, maxs, srLocal ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - srLocal -= RADIUSSTEP; - } while( ( tr.fraction < 1.0f || tr.startsolid ) && ( srLocal > 0.0f ) ); - - ratio = srLocal / srcRadius; - - cent->lfs.lastSrcRadius = srLocal; - } - else if( cg_lightFlare.integer == FLARE_TIMEFADE ) - { - //draw timed flares - SETBOUNDS( mins, maxs, srcRadius ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - if( ( tr.fraction < 1.0f || tr.startsolid ) && cent->lfs.status ) - { - cent->lfs.status = qfalse; - cent->lfs.lastTime = cg.time; - } - else if( ( tr.fraction == 1.0f && !tr.startsolid ) && !cent->lfs.status ) - { - cent->lfs.status = qtrue; - cent->lfs.lastTime = cg.time; - } - - //fade flare up - if( cent->lfs.status ) - { - if( cent->lfs.lastTime + es->time > cg.time ) - ratio = (float)( cg.time - cent->lfs.lastTime ) / es->time; - } - - //fade flare down - if( !cent->lfs.status ) - { - if( cent->lfs.lastTime + es->time > cg.time ) - { - ratio = (float)( cg.time - cent->lfs.lastTime ) / es->time; - ratio = 1.0f - ratio; - } - else - ratio = 0.0f; - } - } - else if( cg_lightFlare.integer == FLARE_NOFADE ) - { - //draw nofade flares - SETBOUNDS( mins, maxs, srcRadius ); - CG_Trace( &tr, start, mins, maxs, end, - entityNum, MASK_SHOT ); - - //flare source occluded - if( ( tr.fraction < 1.0f || tr.startsolid ) ) - ratio = 0.0f; - } - } - else - { - ratio = cent->lfs.lastRatio; - flare.radius = cent->lfs.lastRadius; - } - - cent->lfs.lastRatio = ratio; - cent->lfs.lastRadius = flare.radius; - - if( ratio < 1.0f ) - { - flare.radius *= ratio; - flare.shaderRGBA[ 3 ] = (byte)( (float)flare.shaderRGBA[ 3 ] * ratio ); - } - - if( flare.radius <= 0.0f ) - return; - - trap_R_AddRefEntityToScene( &flare ); -} - -/* -========================= -CG_Lev2ZapChain -========================= -*/ -static void CG_Lev2ZapChain( centity_t *cent ) -{ - int i; - entityState_t *es; - centity_t *source, *target; - - es = ¢->currentState; - - for( i = 0; i <= 2; i++ ) - { - switch( i ) - { - case 0: - if( es->time <= 0 ) - continue; - - source = &cg_entities[ es->powerups ]; - target = &cg_entities[ es->time ]; - break; - - case 1: - if( es->time2 <= 0 ) - continue; - - source = &cg_entities[ es->time ]; - target = &cg_entities[ es->time2 ]; - break; - - case 2: - if( es->constantLight <= 0 ) - continue; - - source = &cg_entities[ es->time2 ]; - target = &cg_entities[ es->constantLight ]; - break; - } - - if( !CG_IsTrailSystemValid( ¢->level2ZapTS[ i ] ) ) - cent->level2ZapTS[ i ] = CG_SpawnNewTrailSystem( cgs.media.level2ZapTS ); - - if( CG_IsTrailSystemValid( ¢->level2ZapTS[ i ] ) ) - { - CG_SetAttachmentCent( ¢->level2ZapTS[ i ]->frontAttachment, source ); - CG_SetAttachmentCent( ¢->level2ZapTS[ i ]->backAttachment, target ); - CG_AttachToCent( ¢->level2ZapTS[ i ]->frontAttachment ); - CG_AttachToCent( ¢->level2ZapTS[ i ]->backAttachment ); - } - } -} - -/* -========================= -CG_AdjustPositionForMover - -Also called by client movement prediction code -========================= -*/ -void CG_AdjustPositionForMover( const vec3_t in, int moverNum, int fromTime, int toTime, vec3_t out ) -{ - centity_t *cent; - vec3_t oldOrigin, origin, deltaOrigin; - vec3_t oldAngles, angles, deltaAngles; - - if( moverNum <= 0 || moverNum >= ENTITYNUM_MAX_NORMAL ) - { - VectorCopy( in, out ); - return; - } - - cent = &cg_entities[ moverNum ]; - - if( cent->currentState.eType != ET_MOVER ) - { - VectorCopy( in, out ); - return; - } - - BG_EvaluateTrajectory( ¢->currentState.pos, fromTime, oldOrigin ); - BG_EvaluateTrajectory( ¢->currentState.apos, fromTime, oldAngles ); - - BG_EvaluateTrajectory( ¢->currentState.pos, toTime, origin ); - BG_EvaluateTrajectory( ¢->currentState.apos, toTime, angles ); - - VectorSubtract( origin, oldOrigin, deltaOrigin ); - VectorSubtract( angles, oldAngles, deltaAngles ); - - VectorAdd( in, deltaOrigin, out ); - - // FIXME: origin change when on a rotating object -} - - -/* -============================= -CG_InterpolateEntityPosition -============================= -*/ -static void CG_InterpolateEntityPosition( centity_t *cent ) -{ - vec3_t current, next; - float f; - - // it would be an internal error to find an entity that interpolates without - // a snapshot ahead of the current one - if( cg.nextSnap == NULL ) - CG_Error( "CG_InterpoateEntityPosition: cg.nextSnap == NULL" ); - - f = cg.frameInterpolation; - - // this will linearize a sine or parabolic curve, but it is important - // to not extrapolate player positions if more recent data is available - BG_EvaluateTrajectory( ¢->currentState.pos, cg.snap->serverTime, current ); - BG_EvaluateTrajectory( ¢->nextState.pos, cg.nextSnap->serverTime, next ); - - cent->lerpOrigin[ 0 ] = current[ 0 ] + f * ( next[ 0 ] - current[ 0 ] ); - cent->lerpOrigin[ 1 ] = current[ 1 ] + f * ( next[ 1 ] - current[ 1 ] ); - cent->lerpOrigin[ 2 ] = current[ 2 ] + f * ( next[ 2 ] - current[ 2 ] ); - - BG_EvaluateTrajectory( ¢->currentState.apos, cg.snap->serverTime, current ); - BG_EvaluateTrajectory( ¢->nextState.apos, cg.nextSnap->serverTime, next ); - - cent->lerpAngles[ 0 ] = LerpAngle( current[ 0 ], next[ 0 ], f ); - cent->lerpAngles[ 1 ] = LerpAngle( current[ 1 ], next[ 1 ], f ); - cent->lerpAngles[ 2 ] = LerpAngle( current[ 2 ], next[ 2 ], f ); - -} - -/* -=============== -CG_CalcEntityLerpPositions - -=============== -*/ -static void CG_CalcEntityLerpPositions( centity_t *cent ) -{ - // if this player does not want to see extrapolated players - if( !cg_smoothClients.integer ) - { - // make sure the clients use TR_INTERPOLATE - if( cent->currentState.number < MAX_CLIENTS ) - { - cent->currentState.pos.trType = TR_INTERPOLATE; - cent->nextState.pos.trType = TR_INTERPOLATE; - } - } - - if( cent->interpolate && cent->currentState.pos.trType == TR_INTERPOLATE ) - { - CG_InterpolateEntityPosition( cent ); - return; - } - - // first see if we can interpolate between two snaps for - // linear extrapolated clients - if( cent->interpolate && cent->currentState.pos.trType == TR_LINEAR_STOP && - cent->currentState.number < MAX_CLIENTS ) - { - CG_InterpolateEntityPosition( cent ); - return; - } - - // just use the current frame and evaluate as best we can - BG_EvaluateTrajectory( ¢->currentState.pos, cg.time, cent->lerpOrigin ); - BG_EvaluateTrajectory( ¢->currentState.apos, cg.time, cent->lerpAngles ); - - // adjust for riding a mover if it wasn't rolled into the predicted - // player state - if( cent != &cg.predictedPlayerEntity ) - { - CG_AdjustPositionForMover( cent->lerpOrigin, cent->currentState.groundEntityNum, - cg.snap->serverTime, cg.time, cent->lerpOrigin ); - } -} - - -/* -=============== -CG_CEntityPVSEnter - -=============== -*/ -static void CG_CEntityPVSEnter( centity_t *cent ) -{ - entityState_t *es = ¢->currentState; - - if( cg_debugPVS.integer ) - CG_Printf( "Entity %d entered PVS\n", cent->currentState.number ); - - switch( es->eType ) - { - case ET_MISSILE: - CG_LaunchMissile( cent ); - break; - } - - //clear any particle systems from previous uses of this centity_t - cent->muzzlePS = NULL; - cent->muzzlePsTrigger = qfalse; - cent->jetPackPS = NULL; - cent->jetPackState = JPS_OFF; - cent->buildablePS = NULL; - cent->entityPS = NULL; - cent->entityPSMissing = qfalse; - - //make sure that the buildable animations are in a consistent state - //when a buildable enters the PVS - cent->buildableAnim = cent->lerpFrame.animationNumber = BANIM_NONE; - cent->oldBuildableAnim = es->legsAnim; -} - - -/* -=============== -CG_CEntityPVSLeave - -=============== -*/ -static void CG_CEntityPVSLeave( centity_t *cent ) -{ - int i; - entityState_t *es = ¢->currentState; - - if( cg_debugPVS.integer ) - CG_Printf( "Entity %d left PVS\n", cent->currentState.number ); - - switch( es->eType ) - { - case ET_LEV2_ZAP_CHAIN: - for( i = 0; i <= 2; i++ ) - { - if( CG_IsTrailSystemValid( ¢->level2ZapTS[ i ] ) ) - CG_DestroyTrailSystem( ¢->level2ZapTS[ i ] ); - } - break; - } -} - - -/* -=============== -CG_AddCEntity - -=============== -*/ -static void CG_AddCEntity( centity_t *cent ) -{ - // event-only entities will have been dealt with already - if( cent->currentState.eType >= ET_EVENTS ) - return; - - // calculate the current origin - CG_CalcEntityLerpPositions( cent ); - - // add automatic effects - CG_EntityEffects( cent ); - - switch( cent->currentState.eType ) - { - default: - CG_Error( "Bad entity type: %i\n", cent->currentState.eType ); - break; - - case ET_INVISIBLE: - case ET_PUSH_TRIGGER: - case ET_TELEPORT_TRIGGER: - break; - - case ET_GENERAL: - CG_General( cent ); - break; - - case ET_CORPSE: - CG_Corpse( cent ); - break; - - case ET_PLAYER: - CG_Player( cent ); - break; - - case ET_BUILDABLE: - CG_Buildable( cent ); - break; - - case ET_MISSILE: - CG_Missile( cent ); - break; - - case ET_MOVER: - CG_Mover( cent ); - break; - - case ET_BEAM: - CG_Beam( cent ); - break; - - case ET_PORTAL: - CG_Portal( cent ); - break; - - case ET_SPEAKER: - CG_Speaker( cent ); - break; - - case ET_PARTICLE_SYSTEM: - CG_ParticleSystemEntity( cent ); - break; - - case ET_ANIMMAPOBJ: - CG_AnimMapObj( cent ); - break; - - case ET_MODELDOOR: - CG_ModelDoor( cent ); - break; - - case ET_LIGHTFLARE: - CG_LightFlare( cent ); - break; - - case ET_LEV2_ZAP_CHAIN: - CG_Lev2ZapChain( cent ); - break; - } -} - -/* -=============== -CG_AddPacketEntities - -=============== -*/ -void CG_AddPacketEntities( void ) -{ - int num; - centity_t *cent; - playerState_t *ps; - - // set cg.frameInterpolation - if( cg.nextSnap ) - { - int delta; - - delta = ( cg.nextSnap->serverTime - cg.snap->serverTime ); - - if( delta == 0 ) - cg.frameInterpolation = 0; - else - cg.frameInterpolation = (float)( cg.time - cg.snap->serverTime ) / delta; - } - else - { - cg.frameInterpolation = 0; // actually, it should never be used, because - // no entities should be marked as interpolating - } - - // the auto-rotating items will all have the same axis - cg.autoAngles[ 0 ] = 0; - cg.autoAngles[ 1 ] = ( cg.time & 2047 ) * 360 / 2048.0; - cg.autoAngles[ 2 ] = 0; - - cg.autoAnglesFast[ 0 ] = 0; - cg.autoAnglesFast[ 1 ] = ( cg.time & 1023 ) * 360 / 1024.0f; - cg.autoAnglesFast[ 2 ] = 0; - - AnglesToAxis( cg.autoAngles, cg.autoAxis ); - AnglesToAxis( cg.autoAnglesFast, cg.autoAxisFast ); - - // generate and add the entity from the playerstate - ps = &cg.predictedPlayerState; - BG_PlayerStateToEntityState( ps, &cg.predictedPlayerEntity.currentState, qfalse ); - cg.predictedPlayerEntity.valid = qtrue; - CG_AddCEntity( &cg.predictedPlayerEntity ); - - // lerp the non-predicted value for lightning gun origins - CG_CalcEntityLerpPositions( &cg_entities[ cg.snap->ps.clientNum ] ); - - // scanner - CG_UpdateEntityPositions( ); - - for( num = 0; num < MAX_GENTITIES; num++ ) - cg_entities[ num ].valid = qfalse; - - // add each entity sent over by the server - for( num = 0; num < cg.snap->numEntities; num++ ) - { - cent = &cg_entities[ cg.snap->entities[ num ].number ]; - cent->valid = qtrue; - } - - for( num = 0; num < MAX_GENTITIES; num++ ) - { - cent = &cg_entities[ num ]; - - if( cent->valid && !cent->oldValid ) - CG_CEntityPVSEnter( cent ); - else if( !cent->valid && cent->oldValid ) - CG_CEntityPVSLeave( cent ); - - cent->oldValid = cent->valid; - } - - // add each entity sent over by the server - for( num = 0; num < cg.snap->numEntities; num++ ) - { - cent = &cg_entities[ cg.snap->entities[ num ].number ]; - CG_AddCEntity( cent ); - } - - //make an attempt at drawing bounding boxes of selected entity types - if( cg_drawBBOX.integer ) - { - for( num = 0; num < cg.snap->numEntities; num++ ) - { - float x, zd, zu; - vec3_t mins, maxs; - entityState_t *es; - - cent = &cg_entities[ cg.snap->entities[ num ].number ]; - es = ¢->currentState; - - switch( es->eType ) - { - case ET_BUILDABLE: - case ET_MISSILE: - case ET_CORPSE: - x = ( es->solid & 255 ); - zd = ( ( es->solid >> 8 ) & 255 ); - zu = ( ( es->solid >> 16 ) & 255 ) - 32; - - mins[ 0 ] = mins[ 1 ] = -x; - maxs[ 0 ] = maxs[ 1 ] = x; - mins[ 2 ] = -zd; - maxs[ 2 ] = zu; - - CG_DrawBoundingBox( cent->lerpOrigin, mins, maxs ); - break; - - default: - break; - } - } - } -} - |