From 425decdf7e9284d15aa726e3ae96b9942fb0e3ea Mon Sep 17 00:00:00 2001 From: IronClawTrem Date: Sun, 16 Feb 2020 03:40:06 +0000 Subject: create tremded branch --- src/cgame/cg_buildable.c | 410 +++++++++++++++++++++++++++-------------------- 1 file changed, 233 insertions(+), 177 deletions(-) (limited to 'src/cgame/cg_buildable.c') diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c index e678ebd..7d7596b 100644 --- a/src/cgame/cg_buildable.c +++ b/src/cgame/cg_buildable.c @@ -1,13 +1,14 @@ /* =========================================================================== Copyright (C) 1999-2005 Id Software, Inc. -Copyright (C) 2000-2006 Tim Angus +Copyright (C) 2000-2013 Darklegion Development +Copyright (C) 2015-2019 GrangerHub This file is part of Tremulous. Tremulous is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as -published by the Free Software Foundation; either version 2 of the License, +published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Tremulous is distributed in the hope that it will be @@ -16,12 +17,11 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with Tremulous; if not, write to the Free Software -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +along with Tremulous; if not, see + =========================================================================== */ - #include "cg_local.h" char *cg_buildableSoundNames[ MAX_BUILDABLE_ANIMATIONS ] = @@ -95,6 +95,7 @@ void CG_HumanBuildableExplosion( vec3_t origin, vec3_t dir ) #define CREEP_SIZE 64.0f +#define CREEP_DISTANCE 64.0f /* ================== @@ -107,7 +108,7 @@ static void CG_Creep( centity_t *cent ) float size, frac; trace_t tr; vec3_t temp, origin; - int scaleUpTime = BG_FindBuildTimeForBuildable( cent->currentState.modelindex ); + int scaleUpTime = BG_Buildable( cent->currentState.modelindex )->buildTime; int time; time = cent->currentState.time; @@ -121,7 +122,7 @@ static void CG_Creep( centity_t *cent ) else frac = 1.0f; } - else + else if( time < 0 ) { msec = cg.time + time; if( msec >= 0 && msec < CREEP_SCALEDOWN_TIME ) @@ -131,7 +132,7 @@ static void CG_Creep( centity_t *cent ) } VectorCopy( cent->currentState.origin2, temp ); - VectorScale( temp, -4096, temp ); + VectorScale( temp, -CREEP_DISTANCE, temp ); VectorAdd( temp, cent->lerpOrigin, temp ); CG_Trace( &tr, cent->lerpOrigin, NULL, NULL, temp, cent->currentState.number, MASK_PLAYERSOLID ); @@ -140,7 +141,7 @@ static void CG_Creep( centity_t *cent ) size = CREEP_SIZE * frac; - if( size > 0.0f ) + if( size > 0.0f && tr.fraction < 1.0f ) CG_ImpactMark( cgs.media.creepShader, origin, cent->currentState.origin2, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, qfalse, size, qtrue ); } @@ -168,12 +169,13 @@ static qboolean CG_ParseBuildableAnimationFile( const char *filename, buildable_ // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); - if( len <= 0 ) + if( len < 0 ) return qfalse; - if( len >= sizeof( text ) - 1 ) + if( len == 0 || len >= sizeof( text ) - 1 ) { - CG_Printf( "File %s too long\n", filename ); + trap_FS_FCloseFile( f ); + CG_Printf( "File %s is %s\n", filename, len == 0 ? "empty" : "too long" ); return qfalse; } @@ -258,12 +260,13 @@ static qboolean CG_ParseBuildableSoundFile( const char *filename, buildable_t bu // load the file len = trap_FS_FOpenFile( filename, &f, FS_READ ); - if ( len <= 0 ) + if ( len < 0 ) return qfalse; - if ( len >= sizeof( text ) - 1 ) + if ( len == 0 || len >= sizeof( text ) - 1 ) { - CG_Printf( "File %s too long\n", filename ); + trap_FS_FCloseFile( f ); + CG_Printf( "File %s is %s\n", filename, len == 0 ? "empty" : "too long" ); return qfalse; } @@ -335,7 +338,7 @@ void CG_InitBuildables( void ) for( i = BA_NONE + 1; i < BA_NUM_BUILDABLES; i++ ) { - buildableName = BG_FindNameForBuildable( i ); + buildableName = BG_Buildable( i )->name; //animation.cfg Com_sprintf( filename, sizeof( filename ), "models/buildables/%s/animation.cfg", buildableName ); @@ -350,7 +353,8 @@ void CG_InitBuildables( void ) //models for( j = 0; j <= 3; j++ ) { - if( ( modelFile = BG_FindModelsForBuildable( i, j ) ) ) + modelFile = BG_BuildableConfig( i )->models[ j ]; + if( strlen( modelFile ) > 0 ) cg_buildables[ i ].models[ j ] = trap_R_RegisterModel( modelFile ); } @@ -372,7 +376,7 @@ void CG_InitBuildables( void ) else { //file doesn't exist - use default - if( BG_FindTeamForBuildable( i ) == BIT_ALIENS ) + if( BG_Buildable( i )->team == TEAM_ALIENS ) cg_buildables[ i ].sounds[ j ].sound = defaultAlienSounds[ j ]; else cg_buildables[ i ].sounds[ j ].sound = defaultHumanSounds[ j ]; @@ -426,24 +430,15 @@ cg.time should be between oldFrameTime and frameTime after exit */ static void CG_RunBuildableLerpFrame( centity_t *cent ) { - int f, numFrames; buildable_t buildable = cent->currentState.modelindex; lerpFrame_t *lf = ¢->lerpFrame; - animation_t *anim; buildableAnimNumber_t newAnimation = cent->buildableAnim & ~( ANIM_TOGGLEBIT|ANIM_FORCEBIT ); - // debugging tool to get no animations - if( cg_animSpeed.integer == 0 ) - { - lf->oldFrame = lf->frame = lf->backlerp = 0; - return; - } - // see if the animation sequence is switching if( newAnimation != lf->animationNumber || !lf->animation ) { if( cg_debugRandom.integer ) - CG_Printf( "newAnimation: %d lf->animationNumber: %d lf->animation: %d\n", + CG_Printf( "newAnimation: %d lf->animationNumber: %d lf->animation: 0x%p\n", newAnimation, lf->animationNumber, lf->animation ); CG_SetBuildableLerpFrameAnimation( buildable, lf, newAnimation ); @@ -453,7 +448,7 @@ static void CG_RunBuildableLerpFrame( centity_t *cent ) { if( cg_debugRandom.integer ) CG_Printf( "Sound for animation %d for a %s\n", - newAnimation, BG_FindHumanNameForBuildable( buildable ) ); + newAnimation, BG_Buildable( buildable )->humanName ); trap_S_StartSound( cent->lerpOrigin, cent->currentState.number, CHAN_AUTO, cg_buildables[ buildable ].sounds[ newAnimation ].sound ); @@ -465,72 +460,14 @@ static void CG_RunBuildableLerpFrame( centity_t *cent ) trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, cg_buildables[ buildable ].sounds[ lf->animationNumber ].sound ); - // 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; + CG_RunLerpFrame( lf, 1.0f ); - // 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; - cent->buildableAnim = cent->currentState.torsoAnim; - } - } - - 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"); - } + // animation ended + if( lf->frameTime == cg.time ) + { + cent->buildableAnim = cent->currentState.torsoAnim; + cent->buildableIdleAnim = qtrue; } - - 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 ); } /* @@ -544,10 +481,13 @@ static void CG_BuildableAnimation( centity_t *cent, int *old, int *now, float *b //if no animation is set default to idle anim if( cent->buildableAnim == BANIM_NONE ) + { cent->buildableAnim = es->torsoAnim; + cent->buildableIdleAnim = qtrue; + } //display the first frame of the construction anim if not yet spawned - if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) + if( !( es->eFlags & EF_B_SPAWNED ) ) { animation_t *anim = &cg_buildables[ es->modelindex ].animations[ BANIM_CONSTRUCT1 ]; @@ -572,12 +512,23 @@ static void CG_BuildableAnimation( centity_t *cent, int *old, int *now, float *b CG_Printf( "%d->%d l:%d t:%d %s(%d)\n", cent->oldBuildableAnim, cent->buildableAnim, es->legsAnim, es->torsoAnim, - BG_FindHumanNameForBuildable( es->modelindex ), es->number ); + BG_Buildable( es->modelindex )->humanName, es->number ); if( cent->buildableAnim == es->torsoAnim || es->legsAnim & ANIM_FORCEBIT ) + { cent->buildableAnim = cent->oldBuildableAnim = es->legsAnim; + cent->buildableIdleAnim = qfalse; + } else + { cent->buildableAnim = cent->oldBuildableAnim = es->torsoAnim; + cent->buildableIdleAnim = qtrue; + } + } + else if( cent->buildableIdleAnim == qtrue && + cent->buildableAnim != es->torsoAnim ) + { + cent->buildableAnim = es->torsoAnim; } CG_RunBuildableLerpFrame( cent ); @@ -588,7 +539,7 @@ static void CG_BuildableAnimation( centity_t *cent, int *old, int *now, float *b } } -#define TRACE_DEPTH 64.0f +#define TRACE_DEPTH 15.0f /* =============== @@ -600,8 +551,9 @@ static void CG_PositionAndOrientateBuildable( const vec3_t angles, const vec3_t const vec3_t mins, const vec3_t maxs, vec3_t outAxis[ 3 ], vec3_t outOrigin ) { - vec3_t forward, start, end; + vec3_t forward, end; trace_t tr; + float fraction; AngleVectors( angles, forward, NULL, NULL ); VectorCopy( normal, outAxis[ 2 ] ); @@ -620,16 +572,21 @@ static void CG_PositionAndOrientateBuildable( const vec3_t angles, const vec3_t outAxis[ 1 ][ 2 ] = -outAxis[ 1 ][ 2 ]; VectorMA( inOrigin, -TRACE_DEPTH, normal, end ); - VectorMA( inOrigin, 1.0f, normal, start ); - CG_CapTrace( &tr, start, mins, maxs, end, skipNumber, MASK_PLAYERSOLID ); - if( tr.fraction == 1.0f ) + CG_CapTrace( &tr, inOrigin, mins, maxs, end, skipNumber, + CONTENTS_SOLID | CONTENTS_PLAYERCLIP ); + + fraction = tr.fraction; + if( tr.startsolid ) + fraction = 0; + else if( tr.fraction == 1.0f ) { - //erm we missed completely - try again with a box trace - CG_Trace( &tr, start, mins, maxs, end, skipNumber, MASK_PLAYERSOLID ); + // this is either too far off of the bbox to be useful for gameplay purposes + // or the model is positioned in thin air anyways. + fraction = 0; } - VectorMA( inOrigin, tr.fraction * -TRACE_DEPTH, normal, outOrigin ); + VectorMA( inOrigin, fraction * -TRACE_DEPTH, normal, outOrigin ); } /* @@ -650,15 +607,18 @@ void CG_GhostBuildable( buildable_t buildable ) memset( &ent, 0, sizeof( ent ) ); - BG_FindBBoxForBuildable( buildable, mins, maxs ); + BG_BuildableBoundingBox( buildable, mins, maxs ); BG_PositionBuildableRelativeToPlayer( ps, mins, maxs, CG_Trace, entity_origin, angles, &tr ); + if( cg_rangeMarkerForBlueprint.integer && tr.entityNum != ENTITYNUM_NONE ) + CG_GhostBuildableRangeMarker( buildable, entity_origin, tr.plane.normal ); + CG_PositionAndOrientateBuildable( ps->viewangles, entity_origin, tr.plane.normal, ps->clientNum, mins, maxs, ent.axis, ent.origin ); //offset on the Z axis if required - VectorMA( ent.origin, BG_FindZOffsetForBuildable( buildable ), tr.plane.normal, ent.origin ); + VectorMA( ent.origin, BG_BuildableConfig( buildable )->zOffset, tr.plane.normal, ent.origin ); VectorCopy( ent.origin, ent.lightingOrigin ); VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all @@ -671,7 +631,7 @@ void CG_GhostBuildable( buildable_t buildable ) ent.customShader = cgs.media.redBuildShader; //rescale the model - scale = BG_FindModelScaleForBuildable( buildable ); + scale = BG_BuildableConfig( buildable )->modelScale; if( scale != 1.0f ) { @@ -696,14 +656,14 @@ CG_BuildableParticleEffects static void CG_BuildableParticleEffects( centity_t *cent ) { entityState_t *es = ¢->currentState; - buildableTeam_t team = BG_FindTeamForBuildable( es->modelindex ); - int health = es->generic1 & B_HEALTH_MASK; - float healthFrac = (float)health / B_HEALTH_MASK; + team_t team = BG_Buildable( es->modelindex )->team; + int health = es->misc; + float healthFrac = (float)health / BG_Buildable( es->modelindex )->health; - if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) + if( !( es->eFlags & EF_B_SPAWNED ) ) return; - if( team == BIT_HUMANS ) + if( team == TEAM_HUMANS ) { if( healthFrac < 0.33f && !CG_IsParticleSystemValid( ¢->buildablePS ) ) { @@ -718,7 +678,7 @@ static void CG_BuildableParticleEffects( centity_t *cent ) else if( healthFrac >= 0.33f && CG_IsParticleSystemValid( ¢->buildablePS ) ) CG_DestroyParticleSystem( ¢->buildablePS ); } - else if( team == BIT_ALIENS ) + else if( team == TEAM_ALIENS ) { if( healthFrac < 0.33f && !CG_IsParticleSystemValid( ¢->buildablePS ) ) { @@ -736,7 +696,11 @@ static void CG_BuildableParticleEffects( centity_t *cent ) } } - +/* +================== +CG_BuildableStatusParse +================== +*/ void CG_BuildableStatusParse( const char *filename, buildStat_t *bs ) { pc_token_t token; @@ -866,10 +830,12 @@ void CG_BuildableStatusParse( const char *filename, buildStat_t *bs ) Com_Printf("CG_BuildableStatusParse: unknown token %s in %s\n", token.string, filename ); bs->loaded = qfalse; + trap_Parse_FreeSource( handle ); return; } } bs->loaded = qtrue; + trap_Parse_FreeSource( handle ); } #define STATUS_FADE_TIME 200 @@ -899,23 +865,30 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) qboolean visible = qfalse; vec3_t mins, maxs; entityState_t *hit; + int anim; - if( BG_FindTeamForBuildable( es->modelindex ) == BIT_ALIENS ) + if( BG_Buildable( es->modelindex )->team == TEAM_ALIENS ) bs = &cgs.alienBuildStat; else bs = &cgs.humanBuildStat; if( !bs->loaded ) return; - + d = Distance( cent->lerpOrigin, cg.refdef.vieworg ); if( d > STATUS_MAX_VIEW_DIST ) return; - + Vector4Copy( bs->foreColor, color ); - // trace for center point - BG_FindBBoxForBuildable( es->modelindex, mins, maxs ); + // trace for center point + BG_BuildableBoundingBox( es->modelindex, mins, maxs ); + + // hack for shrunken barricades + anim = es->torsoAnim & ~( ANIM_FORCEBIT | ANIM_TOGGLEBIT ); + if( es->modelindex == BA_A_BARRICADE && + ( anim == BANIM_DESTROYED || !( es->eFlags & EF_B_SPAWNED ) ) ) + maxs[ 2 ] = (int)( maxs[ 2 ] * BARRICADE_SHRINKPROP ); VectorCopy( cent->lerpOrigin, origin ); @@ -960,8 +933,8 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) hit = &cg_entities[ tr.entityNum ].currentState; if( tr.entityNum < MAX_CLIENTS || ( hit->eType == ET_BUILDABLE && - ( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) || - BG_FindTransparentTestForBuildable( hit->modelindex ) ) ) ) + ( !( es->eFlags & EF_B_SPAWNED ) || + BG_Buildable( hit->modelindex )->transparentTest ) ) ) { entNum = tr.entityNum; VectorCopy( tr.endpos, trOrigin ); @@ -972,7 +945,7 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) } // hack to make the kit obscure view if( cg_drawGun.integer && visible && - cg.predictedPlayerState.stats[ STAT_PTEAM ] == PTE_HUMANS && + cg.predictedPlayerState.stats[ STAT_TEAM ] == TEAM_HUMANS && CG_WorldToScreen( origin, &x, &y ) ) { if( x > 450 && y > 290 ) @@ -1006,8 +979,8 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) return; } - health = es->generic1 & B_HEALTH_MASK; - healthScale = (float)health / B_HEALTH_MASK; + health = es->misc; + healthScale = (float)health / BG_Buildable( es->modelindex )->health; if( health > 0 && healthScale < 0.01f ) healthScale = 0.01f; @@ -1024,13 +997,14 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) float picY = y; float scale; float subH, subY; + float clipX, clipY, clipW, clipH; vec4_t frameColor; // this is fudged to get the width/height in the cfg to be more realistic scale = ( picH / d ) * 3; - powered = es->generic1 & B_POWERED_TOGGLEBIT; - marked = es->generic1 & B_MARKED_TOGGLEBIT; + powered = es->eFlags & EF_B_POWERED; + marked = es->eFlags & EF_B_MARKED; picH *= scale; picW *= scale; @@ -1041,6 +1015,12 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) subH = picH - ( picH * bs->verticalMargin ); subY = picY + ( picH * 0.5f ) - ( subH * 0.5f ); + clipW = ( 640.0f * cg_viewsize.integer ) / 100.0f; + clipH = ( 480.0f * cg_viewsize.integer ) / 100.0f; + clipX = 320.0f - ( clipW * 0.5f ); + clipY = 240.0f - ( clipH * 0.5f ); + CG_SetClipRegion( clipX, clipY, clipW, clipH ); + if( bs->frameShader ) { Vector4Copy( bs->backColor, frameColor ); @@ -1073,7 +1053,7 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) healthColor[ 3 ] = color[ 3 ]; trap_R_SetColor( healthColor ); - + CG_DrawPic( hX, hY, hW, hH, cgs.media.whiteShader ); trap_R_SetColor( NULL ); } @@ -1089,7 +1069,7 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) oW *= scale; oX -= ( oW * 0.5f ); oY -= ( oH * 0.5f ); - + trap_R_SetColor( frameColor ); CG_DrawPic( oX, oY, oW, oH, bs->overlayShader ); trap_R_SetColor( NULL ); @@ -1117,12 +1097,12 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) int healthMax; int healthPoints; - healthMax = BG_FindHealthForBuildable( es->modelindex ); + healthMax = BG_Buildable( es->modelindex )->health; healthPoints = (int)( healthScale * healthMax ); if( health > 0 && healthPoints < 1 ) healthPoints = 1; - nX = picX + ( picW * 0.5f ) - 2.0f - ( ( subH * 4 ) * 0.5f ); - + nX = picX + ( picW * 0.5f ) - 2.0f - ( ( subH * 4 ) * 0.5f ); + if( healthPoints > 999 ) nX -= 0.0f; else if( healthPoints > 99 ) @@ -1131,14 +1111,21 @@ static void CG_BuildableStatusDisplay( centity_t *cent ) nX -= subH * 1.0f; else nX -= subH * 1.5f; - + CG_DrawField( nX, subY, 4, subH, subH, healthPoints ); } + trap_R_SetColor( NULL ); + CG_ClearClipRegion( ); } } -static int QDECL CG_SortDistance( const void *a, const void *b ) +/* +================== +CG_SortDistance +================== +*/ +static int CG_SortDistance( const void *a, const void *b ) { centity_t *aent, *bent; float adist, bdist; @@ -1155,6 +1142,48 @@ static int QDECL CG_SortDistance( const void *a, const void *b ) return 0; } +/* +================== +CG_PlayerIsBuilder +================== +*/ +static qboolean CG_PlayerIsBuilder( buildable_t buildable ) +{ + switch( cg.predictedPlayerState.weapon ) + { + case WP_ABUILD: + case WP_ABUILD2: + case WP_HBUILD: + return BG_Buildable( buildable )->team == + BG_Weapon( cg.predictedPlayerState.weapon )->team; + + default: + return qfalse; + } +} + +/* +================== +CG_BuildableRemovalPending +================== +*/ +static qboolean CG_BuildableRemovalPending( int entityNum ) +{ + int i; + playerState_t *ps = &cg.snap->ps; + + if( !( ps->stats[ STAT_BUILDABLE ] & SB_VALID_TOGGLEBIT ) ) + return qfalse; + + for( i = 0; i < MAX_MISC; i++ ) + { + if( ps->misc[ i ] == entityNum ) + return qtrue; + } + + return qfalse; +} + /* ================== CG_DrawBuildableStatus @@ -1168,30 +1197,18 @@ void CG_DrawBuildableStatus( void ) int buildableList[ MAX_ENTITIES_IN_SNAPSHOT ]; int buildables = 0; - switch( cg.predictedPlayerState.weapon ) + for( i = 0; i < cg.snap->numEntities; i++ ) { - case WP_ABUILD: - case WP_ABUILD2: - case WP_HBUILD: - case WP_HBUILD2: - for( i = 0; i < cg.snap->numEntities; i++ ) - { - cent = &cg_entities[ cg.snap->entities[ i ].number ]; - es = ¢->currentState; - - if( es->eType == ET_BUILDABLE && - BG_FindTeamForBuildable( es->modelindex ) == - BG_FindTeamForWeapon( cg.predictedPlayerState.weapon ) ) - buildableList[ buildables++ ] = cg.snap->entities[ i ].number; - } - qsort( buildableList, buildables, sizeof( int ), CG_SortDistance ); - for( i = 0; i < buildables; i++ ) - CG_BuildableStatusDisplay( &cg_entities[ buildableList[ i ] ] ); - break; + cent = &cg_entities[ cg.snap->entities[ i ].number ]; + es = ¢->currentState; - default: - break; + if( es->eType == ET_BUILDABLE && CG_PlayerIsBuilder( es->modelindex ) ) + buildableList[ buildables++ ] = cg.snap->entities[ i ].number; } + + qsort( buildableList, buildables, sizeof( int ), CG_SortDistance ); + for( i = 0; i < buildables; i++ ) + CG_BuildableStatusDisplay( &cg_entities[ buildableList[ i ] ] ); } #define BUILDABLE_SOUND_PERIOD 500 @@ -1205,17 +1222,15 @@ void CG_Buildable( centity_t *cent ) { refEntity_t ent; entityState_t *es = ¢->currentState; - vec3_t angles; vec3_t surfNormal, xNormal, mins, maxs; vec3_t refNormal = { 0.0f, 0.0f, 1.0f }; float rotAngle; - buildableTeam_t team = BG_FindTeamForBuildable( es->modelindex ); + team_t team = BG_Buildable( es->modelindex )->team; float scale; int health; - float healthScale; //must be before EF_NODRAW check - if( team == BIT_ALIENS ) + if( team == TEAM_ALIENS ) CG_Creep( cent ); // if set to invisible, skip @@ -1229,37 +1244,63 @@ void CG_Buildable( centity_t *cent ) memset ( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - VectorCopy( cent->lerpOrigin, ent.lightingOrigin ); - VectorCopy( es->origin2, surfNormal ); - VectorCopy( es->angles, angles ); - BG_FindBBoxForBuildable( es->modelindex, mins, maxs ); + BG_BuildableBoundingBox( es->modelindex, mins, maxs ); if( es->pos.trType == TR_STATIONARY ) - CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal, es->number, - mins, maxs, ent.axis, ent.origin ); + { + // seeing as buildables rarely move, we cache the results and recalculate + // only if the buildable moves or changes orientation + if( VectorCompare( cent->buildableCache.cachedOrigin, cent->lerpOrigin ) && + VectorCompare( cent->buildableCache.cachedAngles, cent->lerpAngles ) && + VectorCompare( cent->buildableCache.cachedNormal, surfNormal ) && + cent->buildableCache.cachedType == es->modelindex ) + { + VectorCopy( cent->buildableCache.axis[ 0 ], ent.axis[ 0 ] ); + VectorCopy( cent->buildableCache.axis[ 1 ], ent.axis[ 1 ] ); + VectorCopy( cent->buildableCache.axis[ 2 ], ent.axis[ 2 ] ); + VectorCopy( cent->buildableCache.origin, ent.origin ); + } + else + { + CG_PositionAndOrientateBuildable( cent->lerpAngles, cent->lerpOrigin, surfNormal, + es->number, mins, maxs, ent.axis, + ent.origin ); + VectorCopy( ent.axis[ 0 ], cent->buildableCache.axis[ 0 ] ); + VectorCopy( ent.axis[ 1 ], cent->buildableCache.axis[ 1 ] ); + VectorCopy( ent.axis[ 2 ], cent->buildableCache.axis[ 2 ] ); + VectorCopy( ent.origin, cent->buildableCache.origin ); + VectorCopy( cent->lerpOrigin, cent->buildableCache.cachedOrigin ); + VectorCopy( cent->lerpAngles, cent->buildableCache.cachedAngles ); + VectorCopy( surfNormal, cent->buildableCache.cachedNormal ); + cent->buildableCache.cachedType = es->modelindex; + } + } + else + { + VectorCopy( cent->lerpOrigin, ent.origin ); + AnglesToAxis( cent->lerpAngles, ent.axis ); + } //offset on the Z axis if required - VectorMA( ent.origin, BG_FindZOffsetForBuildable( es->modelindex ), surfNormal, ent.origin ); + VectorMA( ent.origin, BG_BuildableConfig( es->modelindex )->zOffset, surfNormal, ent.origin ); VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all VectorCopy( ent.origin, ent.lightingOrigin ); ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ]; - if( !( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) + if( !( es->eFlags & EF_B_SPAWNED ) ) { sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild; - if( team == BIT_HUMANS ) + if( team == TEAM_HUMANS ) { ent.customShader = cgs.media.humanSpawningShader; prebuildSound = cgs.media.humanBuildablePrebuild; } - else if( team == BIT_ALIENS ) + else if( team == TEAM_ALIENS ) prebuildSound = cgs.media.alienBuildablePrebuild; trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound ); @@ -1268,7 +1309,7 @@ void CG_Buildable( centity_t *cent ) CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp ); //rescale the model - scale = BG_FindModelScaleForBuildable( es->modelindex ); + scale = BG_BuildableConfig( es->modelindex )->modelScale; if( scale != 1.0f ) { @@ -1281,6 +1322,8 @@ void CG_Buildable( centity_t *cent ) else ent.nonNormalizedAxes = qfalse; + if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) ) + ent.customShader = cgs.media.redBuildShader; //add to refresh list trap_R_AddRefEntityToScene( &ent ); @@ -1324,6 +1367,9 @@ void CG_Buildable( centity_t *cent ) else turretBarrel.nonNormalizedAxes = qfalse; + if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) ) + turretBarrel.customShader = cgs.media.redBuildShader; + trap_R_AddRefEntityToScene( &turretBarrel ); } @@ -1366,6 +1412,9 @@ void CG_Buildable( centity_t *cent ) else turretTop.nonNormalizedAxes = qfalse; + if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) ) + turretTop.customShader = cgs.media.redBuildShader; + trap_R_AddRefEntityToScene( &turretTop ); } @@ -1375,7 +1424,7 @@ void CG_Buildable( centity_t *cent ) weaponInfo_t *weapon = &cg_weapons[ es->weapon ]; if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME || - BG_FindProjTypeForBuildable( es->modelindex ) == WP_TESLAGEN ) + BG_Buildable( es->modelindex )->turretProjType == WP_TESLAGEN ) { if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] || weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] || @@ -1397,27 +1446,34 @@ void CG_Buildable( centity_t *cent ) trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound ); } - health = es->generic1 & B_HEALTH_MASK; - healthScale = (float)health / B_HEALTH_MASK; + health = es->misc; - if( healthScale < cent->lastBuildableHealthScale && ( es->generic1 & B_SPAWNED_TOGGLEBIT ) ) + if( health < cent->lastBuildableHealth && + ( es->eFlags & EF_B_SPAWNED ) ) { if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time ) { - if( team == BIT_HUMANS ) + if( team == TEAM_HUMANS ) { int i = rand( ) % 4; trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] ); } - else if( team == BIT_ALIENS ) + else if( team == TEAM_ALIENS ) trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage ); cent->lastBuildableDamageSoundTime = cg.time; } } - cent->lastBuildableHealthScale = healthScale; + cent->lastBuildableHealth = health; //smoke etc for damaged buildables CG_BuildableParticleEffects( cent ); + + if ( cg_rangeMarkerForBlueprint.integer ) + { + // only light up the powered buildables. + if ( es->eFlags & EF_B_POWERED ) + CG_GhostBuildableRangeMarker( es->modelindex, ent.origin, surfNormal ); + } } -- cgit