From dac3d3127fc94231bdde0c0822bb12de01e9e836 Mon Sep 17 00:00:00 2001 From: enneract Date: Tue, 25 Feb 2014 13:03:43 +0100 Subject: 0.1.7 --- src/cgame/cg_buildable.c | 682 +++++++++++++++++++++++++++------------------ src/cgame/cg_draw.c | 81 ++++-- src/cgame/cg_ents.c | 3 +- src/cgame/cg_event.c | 19 ++ src/cgame/cg_local.h | 121 +++++++- src/cgame/cg_main.c | 92 +++++- src/cgame/cg_playerstate.c | 6 + src/cgame/cg_servercmds.c | 11 +- src/cgame/cg_tutorial.c | 48 +--- src/cgame/cg_weapons.c | 292 ++++++++++++++++++- 10 files changed, 978 insertions(+), 377 deletions(-) (limited to 'src/cgame') diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c index 0c851b0..5646f90 100644 --- a/src/cgame/cg_buildable.c +++ b/src/cgame/cg_buildable.c @@ -45,6 +45,77 @@ char *cg_buildableSoundNames[ MAX_BUILDABLE_ANIMATIONS ] = static sfxHandle_t defaultAlienSounds[ MAX_BUILDABLE_ANIMATIONS ]; static sfxHandle_t defaultHumanSounds[ MAX_BUILDABLE_ANIMATIONS ]; +/* +====================== +CG_RenderCuboid + +Render a cuboid with proper lighting and UV maps +====================== +*/ +static void CG_RenderCuboid_Face( vec3_t a, vec3_t b, vec3_t c, vec3_t d, + int da, int db, + vec4_t color, + float texscale, qhandle_t shader ) +{ + polyVert_t verts[ 4 ]; + + VectorCopy( d, verts[ 0 ].xyz ); + verts[ 0 ].st[ 0 ] = d[ da ] * texscale; + verts[ 0 ].st[ 1 ] = d[ db ] * texscale; + Vector4Copy( color, verts[ 0 ].modulate ); + VectorCopy( c, verts[ 1 ].xyz ); + verts[ 1 ].st[ 0 ] = c[ da ] * texscale; + verts[ 1 ].st[ 1 ] = c[ db ] * texscale; + Vector4Copy( color, verts[ 1 ].modulate ); + VectorCopy( b, verts[ 2 ].xyz ); + verts[ 2 ].st[ 0 ] = b[ da ] * texscale; + verts[ 2 ].st[ 1 ] = b[ db ] * texscale; + Vector4Copy( color, verts[ 2 ].modulate ); + VectorCopy( a, verts[ 3 ].xyz ); + verts[ 3 ].st[ 0 ] = a[ da ] * texscale; + verts[ 3 ].st[ 1 ] = a[ db ] * texscale; + Vector4Copy( color, verts[ 3 ].modulate ); + + trap_R_AddPolyToScene( shader, 4, verts ); +} + +static void CG_RenderCuboid( vec3_t mins, vec3_t maxs, float texscale, qhandle_t shader ) +{ + int i; + vec3_t midpoint, ambient, directed, idc; + vec4_t color = { 255.0f, 255.0f, 255.0f, 255.0f }; + vec3_t ppp, ppn, pnp, pnn, npp, npn, nnp, nnn; + + //lighting + VectorAdd( mins, maxs, midpoint ); + VectorScale( midpoint, 0.5f, midpoint ); + trap_R_LightForPoint( midpoint, ambient, directed, idc ); + VectorAdd( ambient, directed, color ); + for( i = 0; i < 3; i++ ) + if( color[ i ] > 255.0f ) + color[ i ] = 255.0f; + + //vertices + VectorSet( ppp, maxs[ 0 ], maxs[ 1 ], maxs[ 2 ] ); + VectorSet( ppn, maxs[ 0 ], maxs[ 1 ], mins[ 2 ] ); + VectorSet( pnp, maxs[ 0 ], mins[ 1 ], maxs[ 2 ] ); + VectorSet( pnn, maxs[ 0 ], mins[ 1 ], mins[ 2 ] ); + VectorSet( npp, mins[ 0 ], maxs[ 1 ], maxs[ 2 ] ); + VectorSet( npn, mins[ 0 ], maxs[ 1 ], mins[ 2 ] ); + VectorSet( nnp, mins[ 0 ], mins[ 1 ], maxs[ 2 ] ); + VectorSet( nnn, mins[ 0 ], mins[ 1 ], mins[ 2 ] ); + + //faces + //+-x + CG_RenderCuboid_Face( ppn, ppp, pnp, pnn, 1, 2, color, texscale, shader ); + CG_RenderCuboid_Face( nnn, nnp, npp, npn, 1, 2, color, texscale, shader ); + //+-y + CG_RenderCuboid_Face( ppp, ppn, npn, npp, 0, 2, color, texscale, shader ); + CG_RenderCuboid_Face( nnp, nnn, pnn, pnp, 0, 2, color, texscale, shader ); + //+-z + CG_RenderCuboid_Face( npp, nnp, pnp, ppp, 0, 1, color, texscale, shader ); + CG_RenderCuboid_Face( ppn, pnn, nnn, npn, 0, 1, color, texscale, shader ); +} /* ====================== @@ -1283,7 +1354,6 @@ static void CG_BuildableStatusDisplay( centity_t *cent, qboolean cuboid, vec3_t int health; float x, y; vec4_t color; - qboolean powered, marked; trace_t tr; float d; buildStat_t *bs; @@ -1378,8 +1448,8 @@ static void CG_BuildableStatusDisplay( centity_t *cent, qboolean cuboid, vec3_t } } - if(cuboid) - visible=qtrue; + if( cuboid ) + visible = qtrue; // hack to make the kit obscure view if( cg_drawGun.integer && visible && @@ -1429,13 +1499,13 @@ static void CG_BuildableStatusDisplay( centity_t *cent, qboolean cuboid, vec3_t else if( healthScale > 1.0f ) healthScale = 1.0f; - if(cuboid) + if( cuboid ) { - x=320; - y=240; - d=Distance(cg.refdef.vieworg,trac); - if(d<64.0f) - d=64.0f; + x = 320; + y = 240; + d = Distance( cg.refdef.vieworg, trac ); + if( d < 64.0f ) + d = 64.0f ; } else if( !CG_WorldToScreen( origin, &x, &y ) ) @@ -1454,9 +1524,6 @@ static void CG_BuildableStatusDisplay( centity_t *cent, qboolean cuboid, vec3_t // this is fudged to get the width/height in the cfg to be more realistic scale = ( picH / d ) * 3; - powered = es->eFlags & EF_B_POWERED; - marked = es->eFlags & EF_B_MARKED; - picH *= scale; picW *= scale; picX -= ( picW * 0.5f ); @@ -1527,20 +1594,21 @@ static void CG_BuildableStatusDisplay( centity_t *cent, qboolean cuboid, vec3_t } trap_R_SetColor( color ); - if( !powered ) + { float pX; - + pX = picX + ( subH * bs->horizontalMargin ); - CG_DrawPic( pX, subY, subH, subH, bs->noPowerShader ); - } - - if( marked ) - { - float mX; - - mX = picX + picW - ( subH * bs->horizontalMargin ) - subH; - CG_DrawPic( mX, subY, subH, subH, bs->markedShader ); + + if( BG_Buildable( es->modelindex, NULL )->team == TEAM_HUMANS ) + { + float offs = 2000.0f / d; + CG_DrawPic( pX - offs, subY - offs, + subH + 2.0f * offs, subH + 2.0f * offs, + CG_BuildablePowerStatusIcon( es ) ); + } + else if( !( es->eFlags & EF_B_POWERED ) ) + CG_DrawPic( pX, subY, subH, subH, bs->noPowerShader ); } //NOTE: dont use CG_DrawField, too few digits @@ -1555,19 +1623,22 @@ static void CG_BuildableStatusDisplay( centity_t *cent, qboolean cuboid, vec3_t if( health > 0 && healthPoints < 1 ) healthPoints = 1; - Com_sprintf(buf,sizeof(buf),"%i",healthPoints); - bufl=strlen(buf); - cW=subH*cgDC.aspectScale; - cH=subH; - nX=picX+picW*0.5f-cW*bufl*0.5f; + Com_sprintf( buf, sizeof( buf ), "%i", healthPoints ); + bufl = strlen(buf); + cW = subH*cgDC.aspectScale; + cH = subH; + nX = picX + picW * 0.5f - cW * bufl * 0.5f; - for(i=0;iverticalMargin-subH*0.5f,cW,cH,cgs.media.numberShaders[frame]); + if( buf[ i ] == '-' ) + frame = STAT_MINUS; + else + frame = buf[ i ] - '0'; + CG_DrawPic( nX + i * cW, + y + bs->verticalMargin - subH * 0.5f, + cW, cH, + cgs.media.numberShaders[ frame ] ); } } @@ -1618,28 +1689,6 @@ static qboolean CG_PlayerIsBuilder( buildable_t buildable ) } } -/* -================== -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 @@ -1656,7 +1705,7 @@ void CG_DrawBuildableStatus( void ) trace_t tr; qboolean cuboid; - if((cg.predictedPlayerState.stats[STAT_BUILDABLE]&~SB_VALID_TOGGLEBIT)>BA_NONE) + if( ( cg.predictedPlayerState.stats[STAT_BUILDABLE] & ~SB_VALID_TOGGLEBIT) > BA_NONE ) return; //hide buildstats if we're placing a buildable for( i = 0; i < cg.snap->numEntities; i++ ) @@ -1674,8 +1723,8 @@ void CG_DrawBuildableStatus( void ) qsort( buildableList, buildables, sizeof( int ), CG_SortDistance ); for( i = 0; i < buildables; i++ ) { - cuboid = BG_Buildable(cg_entities[buildableList[i]].currentState.modelindex,NULL)->cuboid; - if(cuboid && tr.entityNum!=buildableList[i] ) + cuboid = BG_IsCuboid( cg_entities[ buildableList[ i ] ].currentState.modelindex ); + if(cuboid && tr.entityNum != buildableList[ i ] ) continue; CG_BuildableStatusDisplay( &cg_entities[ buildableList[ i ] ], cuboid, tr.endpos ); } @@ -1713,11 +1762,11 @@ void CG_Buildable( centity_t *cent ) return; } - // cuboids use a bit different rendering code !@#CUBOID + // cuboids use a bit different rendering code if( BG_IsCuboid( es->modelindex ) ) { - qhandle_t texture=0,cracks=0; - vec3_t dims; + qhandle_t texture = 0,cracks = 0; + vec3_t dims, mins, maxs; const cuboidAttributes_t *cuboidAttr; const cuboidInfo_t *cuboidInfo; int i, health, sound; @@ -1733,12 +1782,30 @@ void CG_Buildable( centity_t *cent ) else if ( healthPct < 0.0f ) healthPct = 0.0f; - if( cuboidInfo->useCracks ) + if( ( es->eFlags & EF_B_SPAWNED ) && cuboidInfo->useCracks && healthPct < 0.95f ) { + float progress; + const float o = 1.02f; //md3 rendering is not exact, so render it bigger to compensate + if( cuboidInfo->textureCount ) texture = cuboidInfo->textures[ 0 ]; - if( healthPct < 0.75f ) - cracks = cgs.media.cuboidCracks[ (int)( CUBOID_CRACK_TEXTURES - 1 - floor( CUBOID_CRACK_TEXTURES * healthPct ) ) - 1 ]; + + memset( &ent, 0, sizeof( ent ) ); + ent.reType = RT_MODEL; + VectorCopy( cent->lerpOrigin, ent.origin ); + + ent.axis[0][0]=-dims[0]/2.0f*o;ent.axis[0][1]=0.0f; ent.axis[0][2]=0.0f; + ent.axis[1][0]=0.0f; ent.axis[1][1]=-dims[1]/2.0f*o;ent.axis[1][2]=0.0f; + ent.axis[2][0]=0.0f; ent.axis[2][1]=0.0f; ent.axis[2][2]=dims[2]/2.0f*o; + ent.nonNormalizedAxes = qtrue; + + progress = healthPct; + + ent.customShader = cgs.media.cuboidCracks; + ent.shaderTime = 0.001f * cg.time + progress; + + ent.hModel = cgs.media.cuboidModel; + trap_R_AddRefEntityToScene( &ent ); } else for( i = 0; i < cuboidInfo->textureCount; i++ ) @@ -1750,13 +1817,22 @@ void CG_Buildable( centity_t *cent ) if( !( es->eFlags & EF_B_SPAWNED ) ) { - sfxHandle_t prebuildSound=cgs.media.humanBuildablePrebuild; + sfxHandle_t prebuildSound; + if( team == TEAM_HUMANS ) { - texture = cgs.media.humanSpawningShader; - prebuildSound = cgs.media.humanBuildablePrebuild; + if( es->eFlags & EF_B_POWERED ) + { + texture = cgs.media.humanSpawningShader; + prebuildSound = cgs.media.humanBuildablePrebuild; + } + else + { + texture = cgs.media.humanUnpoweredSpawningShader; + prebuildSound = cgs.media.unpoweredSurgeLoop; + } } - else if(team==TEAM_ALIENS) + else if( team == TEAM_ALIENS ) { texture = cgs.media.cuboidAlienPrebuild; prebuildSound = cgs.media.alienBuildablePrebuild; @@ -1764,24 +1840,11 @@ void CG_Buildable( centity_t *cent ) cracks = 0; trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound ); } - - memset( &ent, 0, sizeof( ent ) ); - ent.reType = RT_MODEL; - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - VectorCopy( cent->lerpOrigin, ent.lightingOrigin ); - - //NOTE: don't use CG_PositionAndOrientateBuildable, it screws up everything - ent.axis[0][0]=-dims[0]/2.0f;ent.axis[0][1]=0.0f; ent.axis[0][2]=0.0f; - ent.axis[1][0]=0.0f; ent.axis[1][1]=-dims[1]/2.0f;ent.axis[1][2]=0.0f; - ent.axis[2][0]=0.0f; ent.axis[2][1]=0.0f; ent.axis[2][2]=dims[2]/2.0f; - ent.nonNormalizedAxes = qtrue; - - ent.customShader = texture; - ent.hModel = cgs.media.cuboidModel; - trap_R_AddRefEntityToScene( &ent ); - if( cracks ) - CG_DrawCuboid( ent.origin, dims, cracks, 1 ); + + BG_CuboidBBox( dims, mins, maxs ); + VectorAdd( mins, cent->lerpOrigin, mins ); + VectorAdd( maxs, cent->lerpOrigin, maxs ); + CG_RenderCuboid( mins, maxs, 0.01f, texture ); if( health < cent->lastBuildableHealth && ( es->eFlags & EF_B_SPAWNED ) ) { @@ -1795,247 +1858,253 @@ void CG_Buildable( centity_t *cent ) } } else - { - - memset ( &ent, 0, sizeof( ent ) ); + { + memset ( &ent, 0, sizeof( ent ) ); - VectorCopy( cent->lerpOrigin, ent.origin ); - VectorCopy( cent->lerpOrigin, ent.oldorigin ); - VectorCopy( cent->lerpOrigin, ent.lightingOrigin ); + VectorCopy( cent->lerpOrigin, ent.origin ); + VectorCopy( cent->lerpOrigin, ent.oldorigin ); + VectorCopy( cent->lerpOrigin, ent.lightingOrigin ); - VectorCopy( es->origin2, surfNormal ); + VectorCopy( es->origin2, surfNormal ); - VectorCopy( es->angles, angles ); - BG_BuildableBoundingBox( es->modelindex, mins, maxs ); + VectorCopy( es->angles, angles ); + BG_BuildableBoundingBox( es->modelindex, mins, maxs ); - if( es->pos.trType == TR_STATIONARY ) - { - // Positioning a buildable involves potentially up to two traces, and - // 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.cachedNormal, surfNormal ) ) - { - 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 + if( es->pos.trType == TR_STATIONARY ) { - CG_PositionAndOrientateBuildable( angles, ent.origin, surfNormal, - es->number, mins, maxs, ent.axis, - ent.origin, qfalse ); - 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( surfNormal, cent->buildableCache.cachedNormal ); + // Positioning a buildable involves potentially up to two traces, and + // 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.cachedNormal, surfNormal ) ) + { + 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( angles, ent.origin, surfNormal, + es->number, mins, maxs, ent.axis, + ent.origin, qfalse ); + 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( surfNormal, cent->buildableCache.cachedNormal ); + } } - } - - 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 ); + VectorMA( ent.origin, BG_BuildableConfig( es->modelindex )->zOffset, surfNormal, ent.origin ); + - ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ]; + VectorCopy( ent.origin, ent.oldorigin ); // don't positionally lerp at all + VectorCopy( ent.origin, ent.lightingOrigin ); - if( !( es->eFlags & EF_B_SPAWNED ) ) - { - sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild; + ent.hModel = cg_buildables[ es->modelindex ].models[ 0 ]; - if( team == TEAM_HUMANS ) + if( !( es->eFlags & EF_B_SPAWNED ) ) { - ent.customShader = cgs.media.humanSpawningShader; - prebuildSound = cgs.media.humanBuildablePrebuild; - } - else if( team == TEAM_ALIENS ) - prebuildSound = cgs.media.alienBuildablePrebuild; + sfxHandle_t prebuildSound = cgs.media.humanBuildablePrebuild; - trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound ); - } + if( team == TEAM_HUMANS ) + { + if( es->eFlags & EF_B_POWERED ) + { + ent.customShader = cgs.media.humanSpawningShader; + prebuildSound = cgs.media.humanBuildablePrebuild; + } + else + { + ent.customShader = cgs.media.humanUnpoweredSpawningShader; + prebuildSound = cgs.media.unpoweredSurgeLoop; + } + } + else if( team == TEAM_ALIENS ) + prebuildSound = cgs.media.alienBuildablePrebuild; + + trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, prebuildSound ); + } - CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp ); + CG_BuildableAnimation( cent, &ent.oldframe, &ent.frame, &ent.backlerp ); - //rescale the model - scale = BG_BuildableConfig( es->modelindex )->modelScale; + //rescale the model + scale = BG_BuildableConfig( es->modelindex )->modelScale; - if( scale != 1.0f ) - { - VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] ); - VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] ); - VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] ); + if( scale != 1.0f ) + { + VectorScale( ent.axis[ 0 ], scale, ent.axis[ 0 ] ); + VectorScale( ent.axis[ 1 ], scale, ent.axis[ 1 ] ); + VectorScale( ent.axis[ 2 ], scale, ent.axis[ 2 ] ); - ent.nonNormalizedAxes = qtrue; - } - else - ent.nonNormalizedAxes = qfalse; - + ent.nonNormalizedAxes = qtrue; + } + 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 ); - //add to refresh list - trap_R_AddRefEntityToScene( &ent ); + CrossProduct( surfNormal, refNormal, xNormal ); + VectorNormalize( xNormal ); + rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) ); - CrossProduct( surfNormal, refNormal, xNormal ); - VectorNormalize( xNormal ); - rotAngle = RAD2DEG( acos( DotProduct( surfNormal, refNormal ) ) ); + //turret barrel bit + if( cg_buildables[ es->modelindex ].models[ 1 ] ) + { + refEntity_t turretBarrel; + vec3_t flatAxis[ 3 ]; - //turret barrel bit - if( cg_buildables[ es->modelindex ].models[ 1 ] ) - { - refEntity_t turretBarrel; - vec3_t flatAxis[ 3 ]; + memset( &turretBarrel, 0, sizeof( turretBarrel ) ); - memset( &turretBarrel, 0, sizeof( turretBarrel ) ); + turretBarrel.hModel = cg_buildables[ es->modelindex ].models[ 1 ]; - turretBarrel.hModel = cg_buildables[ es->modelindex ].models[ 1 ]; + CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" ); + VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin ); - CG_PositionEntityOnTag( &turretBarrel, &ent, ent.hModel, "tag_turret" ); - VectorCopy( cent->lerpOrigin, turretBarrel.lightingOrigin ); + { + vec3_t interpolated; + int i; - { - vec3_t interpolated; - int i; + for( i = 0; i < 3 ; i++ ) + interpolated[ i ] = LerpAngle( es->angles2[ i ], cent->nextState.angles2[ i ], cg.frameInterpolation ); - for( i = 0; i < 3 ; i++ ) - interpolated[ i ] = LerpAngle( es->angles2[ i ], cent->nextState.angles2[ i ], cg.frameInterpolation ); + AnglesToAxis( interpolated, flatAxis ); + } - AnglesToAxis( interpolated, flatAxis ); - } + RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); + RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); + RotatePointAroundVector( turretBarrel.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); - RotatePointAroundVector( turretBarrel.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); - RotatePointAroundVector( turretBarrel.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); - RotatePointAroundVector( turretBarrel.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); + turretBarrel.oldframe = ent.oldframe; + turretBarrel.frame = ent.frame; + turretBarrel.backlerp = ent.backlerp; - turretBarrel.oldframe = ent.oldframe; - turretBarrel.frame = ent.frame; - turretBarrel.backlerp = ent.backlerp; + turretBarrel.customShader = ent.customShader; - turretBarrel.customShader = ent.customShader; + if( scale != 1.0f ) + { + VectorScale( turretBarrel.axis[ 0 ], scale, turretBarrel.axis[ 0 ] ); + VectorScale( turretBarrel.axis[ 1 ], scale, turretBarrel.axis[ 1 ] ); + VectorScale( turretBarrel.axis[ 2 ], scale, turretBarrel.axis[ 2 ] ); - if( scale != 1.0f ) - { - VectorScale( turretBarrel.axis[ 0 ], scale, turretBarrel.axis[ 0 ] ); - VectorScale( turretBarrel.axis[ 1 ], scale, turretBarrel.axis[ 1 ] ); - VectorScale( turretBarrel.axis[ 2 ], scale, turretBarrel.axis[ 2 ] ); + turretBarrel.nonNormalizedAxes = qtrue; + } + else + turretBarrel.nonNormalizedAxes = qfalse; - turretBarrel.nonNormalizedAxes = qtrue; + trap_R_AddRefEntityToScene( &turretBarrel ); } - else - turretBarrel.nonNormalizedAxes = qfalse; - - if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) ) - turretBarrel.customShader = cgs.media.redBuildShader; - trap_R_AddRefEntityToScene( &turretBarrel ); - } + //turret barrel bit + if( cg_buildables[ es->modelindex ].models[ 2 ] ) + { + refEntity_t turretTop; + vec3_t flatAxis[ 3 ]; + vec3_t swivelAngles; - //turret barrel bit - if( cg_buildables[ es->modelindex ].models[ 2 ] ) - { - refEntity_t turretTop; - vec3_t flatAxis[ 3 ]; - vec3_t swivelAngles; + memset( &turretTop, 0, sizeof( turretTop ) ); - memset( &turretTop, 0, sizeof( turretTop ) ); + VectorCopy( es->angles2, swivelAngles ); + swivelAngles[ PITCH ] = 0.0f; - VectorCopy( es->angles2, swivelAngles ); - swivelAngles[ PITCH ] = 0.0f; + turretTop.hModel = cg_buildables[ es->modelindex ].models[ 2 ]; - turretTop.hModel = cg_buildables[ es->modelindex ].models[ 2 ]; + CG_PositionRotatedEntityOnTag( &turretTop, &ent, ent.hModel, "tag_turret" ); + VectorCopy( cent->lerpOrigin, turretTop.lightingOrigin ); + AnglesToAxis( swivelAngles, flatAxis ); - CG_PositionRotatedEntityOnTag( &turretTop, &ent, ent.hModel, "tag_turret" ); - VectorCopy( cent->lerpOrigin, turretTop.lightingOrigin ); - AnglesToAxis( swivelAngles, flatAxis ); + RotatePointAroundVector( turretTop.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); + RotatePointAroundVector( turretTop.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); + RotatePointAroundVector( turretTop.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); - RotatePointAroundVector( turretTop.axis[ 0 ], xNormal, flatAxis[ 0 ], -rotAngle ); - RotatePointAroundVector( turretTop.axis[ 1 ], xNormal, flatAxis[ 1 ], -rotAngle ); - RotatePointAroundVector( turretTop.axis[ 2 ], xNormal, flatAxis[ 2 ], -rotAngle ); + turretTop.oldframe = ent.oldframe; + turretTop.frame = ent.frame; + turretTop.backlerp = ent.backlerp; - turretTop.oldframe = ent.oldframe; - turretTop.frame = ent.frame; - turretTop.backlerp = ent.backlerp; + turretTop.customShader = ent.customShader; - turretTop.customShader = ent.customShader; + if( scale != 1.0f ) + { + VectorScale( turretTop.axis[ 0 ], scale, turretTop.axis[ 0 ] ); + VectorScale( turretTop.axis[ 1 ], scale, turretTop.axis[ 1 ] ); + VectorScale( turretTop.axis[ 2 ], scale, turretTop.axis[ 2 ] ); - if( scale != 1.0f ) - { - VectorScale( turretTop.axis[ 0 ], scale, turretTop.axis[ 0 ] ); - VectorScale( turretTop.axis[ 1 ], scale, turretTop.axis[ 1 ] ); - VectorScale( turretTop.axis[ 2 ], scale, turretTop.axis[ 2 ] ); + turretTop.nonNormalizedAxes = qtrue; + } + else + turretTop.nonNormalizedAxes = qfalse; - turretTop.nonNormalizedAxes = qtrue; + trap_R_AddRefEntityToScene( &turretTop ); } - else - turretTop.nonNormalizedAxes = qfalse; - - if( CG_PlayerIsBuilder( es->modelindex ) && CG_BuildableRemovalPending( es->number ) ) - turretTop.customShader = cgs.media.redBuildShader; - trap_R_AddRefEntityToScene( &turretTop ); - } - - //weapon effects for turrets - if( es->eFlags & EF_FIRING ) - { - weaponInfo_t *weapon = &cg_weapons[ es->weapon ]; - - if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME || - BG_Buildable( es->modelindex, NULL )->turretProjType == WP_TESLAGEN ) + //weapon effects for turrets + if( es->eFlags & EF_FIRING ) { - if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] || - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] || - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ) + weaponInfo_t *weapon = &cg_weapons[ es->weapon ]; + + if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME || + BG_Buildable( es->modelindex, NULL )->turretProjType == WP_TESLAGEN ) { - trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ), - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ], - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ], - weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ); + if( weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ] || + weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ] || + weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ) + { + trap_R_AddLightToScene( cent->lerpOrigin, 300 + ( rand( ) & 31 ), + weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 0 ], + weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 1 ], + weapon->wim[ WPM_PRIMARY ].flashDlightColor[ 2 ] ); + } } - } - if( weapon->wim[ WPM_PRIMARY ].firingSound ) - { - trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, - weapon->wim[ WPM_PRIMARY ].firingSound ); + if( weapon->wim[ WPM_PRIMARY ].firingSound ) + { + trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, + weapon->wim[ WPM_PRIMARY ].firingSound ); + } + else if( weapon->readySound ) + trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound ); } - else if( weapon->readySound ) - trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, weapon->readySound ); - } - - //smoke etc for damaged buildables - CG_BuildableParticleEffects( cent ); - - + + //smoke etc for damaged buildables + CG_BuildableParticleEffects( cent ); + + - - health = es->generic1; + + health = es->generic1; - if( health < cent->lastBuildableHealth && - ( es->eFlags & EF_B_SPAWNED ) ) - { - if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time ) + if( health < cent->lastBuildableHealth && + ( es->eFlags & EF_B_SPAWNED ) ) { - if( team == TEAM_HUMANS ) + if( cent->lastBuildableDamageSoundTime + BUILDABLE_SOUND_PERIOD < cg.time ) { - int i = rand( ) % 4; - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] ); - } - else if( team == TEAM_ALIENS ) - trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage ); + if( team == TEAM_HUMANS ) + { + int i = rand( ) % 4; + trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.humanBuildableDamage[ i ] ); + } + else if( team == TEAM_ALIENS ) + trap_S_StartSound( NULL, es->number, CHAN_BODY, cgs.media.alienBuildableDamage ); - cent->lastBuildableDamageSoundTime = cg.time; + cent->lastBuildableDamageSoundTime = cg.time; + } } - } - - cent->lastBuildableHealth = health; + cent->lastBuildableHealth = health; } //if (is a cuboid) + + + // play a loop if there's not enough power for it to build / activate + if( ( !( es->eFlags & EF_B_SPAWNED ) && + !( es->eFlags & EF_B_POWERED ) ) || + ( ( BG_Buildable( es->modelindex, NULL )->requiresPower || + es->modelindex != BA_H_REPEATER ) && + !( es->eFlags & EF_B_POWERED ) && + ( es->eFlags & EF_B_SURGE ) ) ) + trap_S_AddLoopingSound( es->number, cent->lerpOrigin, vec3_origin, cgs.media.unpoweredSurgeLoop ); } char cuboidInfo[128]; @@ -2049,17 +2118,21 @@ Draw the cuboid info string generated by CG_Cuboid_Info. */ void CG_Cuboid_DrawInfo(void) { - float x,y,w,h,s=0.5f; + float x,y,w,h,s=0.5f; + + // disabled by default (replaced by ckit's display) + if( !cg_drawCuboidInfo.integer ) + return; - if(!BG_Buildable(cg.predictedPlayerState.stats[STAT_BUILDABLE]&~SB_VALID_TOGGLEBIT,NULL)->cuboid) - return; + if( !BG_Buildable( cg.predictedPlayerState.stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT, NULL )->cuboid ) + return; - w=UI_Text_Width(cuboidInfo,s); - h=UI_Text_Height(cuboidInfo,s); - x=320.0f-w/2.0f+cg_cuboidInfoX.value; - y=240.0f-h/2.0f+cg_cuboidInfoY.value; + w= UI_Text_Width( cuboidInfo, s ); + h= UI_Text_Height( cuboidInfo, s ); + x= 320.0f - w / 2.0f + cg_cuboidInfoX.value; + y= 240.0f - h / 2.0f + cg_cuboidInfoY.value; - UI_Text_Paint(x,y,s,colorWhite,cuboidInfo,0,0,ITEM_TEXTSTYLE_SHADOWEDMORE); + UI_Text_Paint( x, y, s, colorWhite, cuboidInfo, 0, 0, ITEM_TEXTSTYLE_SHADOWEDMORE ); } /* @@ -2076,6 +2149,9 @@ void CG_Cuboid_Info(void) const buildableAttributes_t *attr; int axis=cg_cuboidResizeAxis.integer; + if( !cg_drawCuboidInfo.integer ) + return; + attr=BG_Buildable(cg.predictedPlayerState.stats[STAT_BUILDABLE]&~SB_VALID_TOGGLEBIT,cg.cuboidSelection); Com_sprintf(cuboidInfo,sizeof(cuboidInfo), "^7[^3%c^7] | ^%c%.1f^7x^%c%.1f^7x^%c%.1f ^7| ^3%i^7HP | ^3%i^7ms | ^3%i^7BP", @@ -2342,3 +2418,53 @@ void CG_CuboidAttack_f(void) trap_SendClientCommand( va( "%s", CG_Argv(0) ) ); } +/* +====================== +CG_BuildablePowerStatusIcon + +Figures out the power status icon for a buildable +====================== +*/ +qhandle_t CG_BuildablePowerStatusIcon( entityState_t *es ) +{ + qboolean powered = ( es->eFlags & EF_B_POWERED ); + + if( !( es->eFlags & EF_B_SPAWNED ) ) + { + if( powered ) + return cgs.media.ckit_icon_surge; + else + return cgs.media.ckit_icon_nosurge; + } + + if( BG_Buildable( es->modelindex, NULL )->isPowerSource || + es->modelindex == BA_H_REPEATER ) + { + qboolean active = ( es->eFlags & EF_B_SURGE ); + + if( !active ) + return cgs.media.ckit_icon_off; + else if( powered ) + return cgs.media.ckit_icon_power; + else + return cgs.media.ckit_icon_nopower; + } + else + { + if( !( es->eFlags & EF_B_SURGE ) ) + { + if( powered ) + return cgs.media.ckit_icon_power; + else + return cgs.media.ckit_icon_nopower; + } + else + { + if( powered ) + return cgs.media.ckit_icon_surge; + else + return cgs.media.ckit_icon_nosurge; + } + } + return 0; +} diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index aa6df3d..e9cccf4 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -636,7 +636,6 @@ static void CG_DrawPlayerWallclimbing( rectDef_t *rect, vec4_t backColor, vec4_t static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color ) { int value; - int valueMarked = -1; qboolean bp = qfalse; switch( BG_PrimaryWeapon( cg.snap->ps.stats ) ) @@ -648,8 +647,7 @@ static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color ) case WP_ABUILD: case WP_ABUILD2: case WP_HBUILD: - value = cg.snap->ps.persistant[ PERS_BP ]; - valueMarked = cg.snap->ps.persistant[ PERS_MARKEDBP ]; + value = cg.snap->ps.persistant[ PERS_BUILDPOINTS ]; bp = qtrue; break; @@ -660,8 +658,6 @@ static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color ) if( value > 999 ) value = 999; - if( valueMarked > 999 ) - valueMarked = 999; if( value > -1 ) { @@ -678,10 +674,7 @@ static void CG_DrawPlayerAmmoValue( rectDef_t *rect, vec4_t color ) return; } - if( valueMarked > 0 ) - text = va( "%d+(%d)", value, valueMarked ); - else - text = va( "%d", value ); + text = va( "%d", value ); len = strlen( text ); @@ -2557,10 +2550,10 @@ CG_DrawCrosshair static void CG_DrawCrosshair( rectDef_t *rect, vec4_t color ) { float w, h; - qhandle_t hShader; float x, y; weaponInfo_t *wi; weapon_t weapon; + qboolean hit, ff; weapon = BG_GetPlayerWeapon( &cg.snap->ps ); @@ -2590,24 +2583,66 @@ static void CG_DrawCrosshair( rectDef_t *rect, vec4_t color ) x = rect->x + ( rect->w / 2 ) - ( w / 2 ); y = rect->y + ( rect->h / 2 ) - ( h / 2 ); - hShader = wi->crossHair; + hit = ( cg.time <= cg.lastHitTime + 75 ); + ff = ( cg.time == cg.crosshairClientTime || cg.crosshairBuildable >= 0 ); - //aiming at a friendly player/buildable, dim the crosshair - if( cg.time == cg.crosshairClientTime || cg.crosshairBuildable >= 0 ) - { - int i; - for( i = 0; i < 3; i++ ) - color[i] *= .5f; + color[ 3 ] = 0.6f; - } - - if( hShader != 0 ) + trap_R_SetColor( color ); + + switch( wi->crossHairType ) { + case CH_NONE: + break; + + case CH_DOT: + if( ff ) + CG_DrawPic( x, y, w, h, cgs.media.ch_friendly ); + else + CG_DrawPic( x, y, w, h, cgs.media.ch_dot ); - trap_R_SetColor( color ); - CG_DrawPic( x, y, w, h, hShader ); - trap_R_SetColor( NULL ); + if( hit ) + CG_DrawPic( x, y, w, h, cgs.media.ch_dothit ); + + break; + + case CH_CIRCLE: + if( ff ) + CG_DrawPic( x, y, w, h, cgs.media.ch_friendly ); + + if( hit ) + CG_DrawPic( x, y, w, h, cgs.media.ch_circlehit ); + else + CG_DrawPic( x, y, w, h, cgs.media.ch_circle ); + + break; + + case CH_CIRCLEDDOT: + if( ff ) + CG_DrawPic( x, y, w, h, cgs.media.ch_friendly ); + else + CG_DrawPic( x, y, w, h, cgs.media.ch_dot ); + + if( hit ) + CG_DrawPic( x, y, w, h, cgs.media.ch_circlehit ); + else + CG_DrawPic( x, y, w, h, cgs.media.ch_circle ); + + break; + + case CH_ALIEN: + if( ff ) + CG_DrawPic( x, y, w, h, cgs.media.ch_afriendly ); + else + CG_DrawPic( x, y, w, h, cgs.media.ch_adot ); + + if( hit ) + CG_DrawPic( x, y, w, h, cgs.media.ch_acircle ); + + break; } + + trap_R_SetColor( NULL ); } diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c index 339cd8e..6b1523d 100644 --- a/src/cgame/cg_ents.c +++ b/src/cgame/cg_ents.c @@ -236,7 +236,8 @@ static void CG_EntityEffects( centity_t *cent ) // constant light glow - if ( cent->currentState.constantLight ) + if ( cent->currentState.constantLight && + cent->currentState.eType != ET_BUILDABLE ) { int cl; int i, r, g, b; diff --git a/src/cgame/cg_event.c b/src/cgame/cg_event.c index c8ca2e6..adc319c 100644 --- a/src/cgame/cg_event.c +++ b/src/cgame/cg_event.c @@ -808,6 +808,25 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.repeaterUseSound ); break; + case EV_POWER_SWITCH: + trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.powerSwitchSound ); + break; + + case EV_POWER_ZAP: + { + particleSystem_t *ps; + ps = CG_SpawnNewParticleSystem( cgs.media.humanPowerZapPS ); + + if( CG_IsParticleSystemValid( &ps ) ) + { + CG_SetAttachmentPoint( &ps->attachment, position ); + CG_SetAttachmentCent( &ps->attachment, cg_entities + es->number ); + CG_AttachToPoint( &ps->attachment ); + } + } + trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.powerZap[ rand() % 4 ] ); + break; + case EV_GRENADE_BOUNCE: if( rand( ) & 1 ) trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.hardBounceSound1 ); diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index a81d1df..e4949b5 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -79,8 +79,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA #define TEAM_OVERLAY_MAXNAME_WIDTH 12 #define TEAM_OVERLAY_MAXLOCATION_WIDTH 16 -#define CUBOID_CRACK_TEXTURES 4 - typedef enum { FOOTSTEP_NORMAL, @@ -814,6 +812,15 @@ typedef struct weaponInfoMode_s sfxHandle_t impactFleshSound[ 4 ]; //random impact sound } weaponInfoMode_t; +enum +{ + CH_NONE, + CH_DOT, + CH_CIRCLE, + CH_CIRCLEDDOT, + CH_ALIEN +}; + // each WP_* weapon enum has an associated weaponInfo_t // that contains media references necessary to present the // weapon and its effects @@ -839,7 +846,7 @@ typedef struct weaponInfo_s qhandle_t weaponIcon; qhandle_t ammoIcon; - qhandle_t crossHair; + int crossHairType; int crossHairSize; sfxHandle_t readySound; @@ -932,6 +939,25 @@ typedef struct #define MAX_CONSOLE_TEXT 8192 #define MAX_CONSOLE_LINES 32 +#define MAX_CKIT_ROWS 6 +#define MAX_CKIT_COLUMNS 7 +#define MAX_CKIT_TEXT 64 //make it big so Com_sprintf won't spam errors + +typedef struct +{ + qhandle_t icon; + char text[ MAX_CKIT_TEXT ]; +} ckitDisplayLine_t; + +typedef struct +{ + qhandle_t background; + qhandle_t bigicona; + qhandle_t bigiconb; + ckitDisplayLine_t lines[ MAX_CKIT_ROWS ]; +} ckitDisplay_t; + + // all cg.stepTime, cg.duckTime, cg.landTime, etc are set to cg.time when the action // occurs, and they will have visible effects for #define STEP_TIME or whatever msec after @@ -1194,6 +1220,16 @@ typedef struct qhandle_t announcerStack[ MAX_ANNOUNCER_STACK ]; int announcerStackPos; int announcerStackLatest; + + // no space for voltage and current information so they're being sent + // over the network in commands + int bse_entityNum; + float bse_voltage; + float bse_current; + + ckitDisplay_t ckitDisp; + + int lastHitTime; } cg_t; @@ -1228,6 +1264,7 @@ typedef struct qhandle_t teamOverlayShader; qhandle_t numberShaders[ 11 ]; + qhandle_t digitalNumberShaders[ 12 ]; // note: 11 is comma qhandle_t shadowMarkShader; qhandle_t wakeMarkShader; @@ -1236,6 +1273,7 @@ typedef struct qhandle_t greenBuildShader; qhandle_t redBuildShader; qhandle_t humanSpawningShader; + qhandle_t humanUnpoweredSpawningShader; // disconnect qhandle_t disconnectPS; @@ -1337,13 +1375,17 @@ typedef struct qhandle_t humanBleedPS; qhandle_t alienBuildableBleedPS; qhandle_t humanBuildableBleedPS; - + + qhandle_t humanPowerZapPS; qhandle_t teslaZapTS; sfxHandle_t lCannonWarningSound; sfxHandle_t lCannonWarningSound2; + qhandle_t friendlyCrosshair; + qhandle_t hitCrosshair; + qhandle_t buildWeaponTimerPie[ 8 ]; qhandle_t upgradeClassIconShader; qhandle_t healthCross; @@ -1353,7 +1395,7 @@ typedef struct qhandle_t healthCrossPoisoned; qhandle_t healthCrossImplanted; - qhandle_t cuboidCracks[CUBOID_CRACK_TEXTURES-1]; + qhandle_t cuboidCracks; qhandle_t cuboidModel; qhandle_t cuboidRedBuildShader; qhandle_t cuboidYellowBuildShader; @@ -1378,6 +1420,50 @@ typedef struct qhandle_t basivisionShader; qhandle_t basivisionBlipShader; qhandle_t basivisionFlareShader; + + sfxHandle_t unpoweredSurgeLoop; + sfxHandle_t powerSwitchSound; + sfxHandle_t powerZap[ 4 ]; + + //ckit's hacky dynamic display + qhandle_t ckitBackgroundShader; //note: supposed to be dynamic but I've got nothing put there yet + qhandle_t ckitOverlayShader; + + qhandle_t ckit_background; + qhandle_t ckit_overlay; + qhandle_t ckit_bigicona; + qhandle_t ckit_bigiconb; + qhandle_t ckit_icon; + qhandle_t ckit_digit; + + qhandle_t ckit_icon_bp; + qhandle_t ckit_icon_current; + qhandle_t ckit_icon_depth; + qhandle_t ckit_icon_health; + qhandle_t ckit_icon_height; + qhandle_t ckit_icon_network; + qhandle_t ckit_icon_nopower; + qhandle_t ckit_icon_nosurge; + qhandle_t ckit_icon_off; + qhandle_t ckit_icon_power; + qhandle_t ckit_icon_storedbp; + qhandle_t ckit_icon_surge; + qhandle_t ckit_icon_time; + qhandle_t ckit_icon_voltage; + qhandle_t ckit_icon_width; + + qhandle_t ch_dot; + qhandle_t ch_dothit; + qhandle_t ch_circle; + qhandle_t ch_circlehit; + qhandle_t ch_friendly; + + qhandle_t ch_adot; + qhandle_t ch_acircle; + qhandle_t ch_afriendly; + qhandle_t ch_aheadshot; + + sfxHandle_t hitSound; } cgMedia_t; typedef struct @@ -1425,7 +1511,6 @@ typedef struct int timelimit; int maxclients; char mapname[ MAX_QPATH ]; - qboolean markDeconstruct; // Whether or not buildables are marked int voteTime[ NUM_TEAMS ]; int voteYes[ NUM_TEAMS ]; @@ -1623,8 +1708,10 @@ extern vmCvar_t cg_chatTeamPrefix; extern vmCvar_t cg_cuboidResizeAxis; extern vmCvar_t cg_cuboidResizeRate; extern vmCvar_t cg_cuboidPSQuality; + extern vmCvar_t cg_cuboidInfoX; extern vmCvar_t cg_cuboidInfoY; +extern vmCvar_t cg_drawCuboidInfo; extern vmCvar_t cg_fuelInfoX; extern vmCvar_t cg_fuelInfoY; @@ -1634,6 +1721,11 @@ extern vmCvar_t cg_announcer; extern vmCvar_t cg_cameraShakeMagnitude; +extern vmCvar_t cg_debug1; +extern vmCvar_t cg_debug2; +extern vmCvar_t cg_debug3; +extern vmCvar_t cg_debug4; + // // cg_main.c // @@ -1753,15 +1845,16 @@ void CG_DrawBuildableStatus( void ); void CG_InitBuildables( void ); void CG_HumanBuildableExplosion( vec3_t origin, vec3_t dir ); void CG_AlienBuildableExplosion( vec3_t origin, vec3_t dir ); -void CG_CuboidAxis_f(void); -void CG_CuboidRotate_f(void); -void CG_CuboidSize_f(void); -void CG_Cuboid_Send(void); -void CG_Cuboid_Response(void); +void CG_CuboidAxis_f( void ); +void CG_CuboidRotate_f( void ); +void CG_CuboidSize_f( void ); +void CG_Cuboid_Send( void ); +void CG_Cuboid_Response( void ); void CG_CuboidResize( qboolean enlarge ); -void CG_CuboidExplosion(buildable_t buildable, vec3_t origin, vec3_t cuboid); -void CG_DrawCuboidParticles(void); -void CG_CuboidAttack_f(void); +void CG_CuboidExplosion( buildable_t buildable, vec3_t origin, vec3_t cuboid ); +void CG_DrawCuboidParticles( void ); +void CG_CuboidAttack_f( void ); +qhandle_t CG_BuildablePowerStatusIcon( entityState_t *es ); // // cg_animation.c diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index ff3d567..ee37596 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -226,8 +226,10 @@ vmCvar_t cg_chatTeamPrefix; vmCvar_t cg_cuboidResizeAxis; vmCvar_t cg_cuboidResizeRate; vmCvar_t cg_cuboidPSQuality; + vmCvar_t cg_cuboidInfoX; vmCvar_t cg_cuboidInfoY; +vmCvar_t cg_drawCuboidInfo; vmCvar_t cg_fuelInfoX; vmCvar_t cg_fuelInfoY; @@ -237,6 +239,11 @@ vmCvar_t cg_announcer; vmCvar_t cg_cameraShakeMagnitude; +vmCvar_t cg_debug1; +vmCvar_t cg_debug2; +vmCvar_t cg_debug3; +vmCvar_t cg_debug4; + typedef struct { vmCvar_t *vmCvar; @@ -379,13 +386,19 @@ static cvarTable_t cvarTable[ ] = { &cg_cuboidInfoX, "cg_cuboidInfoX" ,"0", CVAR_ARCHIVE }, { &cg_cuboidInfoY, "cg_cuboidInfoY" ,"150", CVAR_ARCHIVE }, + { &cg_drawCuboidInfo, "cg_drawCuboidInfo" ,"0", CVAR_ARCHIVE }, { &cg_fuelInfoX, "cg_fuelInfoX" ,"0", CVAR_ARCHIVE }, { &cg_fuelInfoY, "cg_fuelInfoY" ,"150", CVAR_ARCHIVE }, { &cg_fuelInfoScale, "cg_fuelInfoScale" ,"0.5", CVAR_ARCHIVE }, { &cg_announcer, "cg_announcer", "1", CVAR_ARCHIVE }, - { &cg_cameraShakeMagnitude, "cg_cameraShakeMagnitude", "1", CVAR_ARCHIVE } + { &cg_cameraShakeMagnitude, "cg_cameraShakeMagnitude", "1", CVAR_ARCHIVE }, + + { &cg_debug1, "cg_debug1", "", CVAR_CHEAT }, + { &cg_debug2, "cg_debug2", "", CVAR_CHEAT }, + { &cg_debug3, "cg_debug3", "", CVAR_CHEAT }, + { &cg_debug4, "cg_debug4", "", CVAR_CHEAT } }; static int cvarTableSize = sizeof( cvarTable ) / sizeof( cvarTable[0] ); @@ -745,6 +758,13 @@ static void CG_RegisterSounds( void ) cgs.media.cuboidResizeSoundB = trap_S_RegisterSound( "sound/cuboid/resizeb.wav", qfalse ); cgs.media.cuboidRotateSound = trap_S_RegisterSound( "sound/cuboid/rotate.wav", qfalse ); cgs.media.cuboidAxisChangeSound = trap_S_RegisterSound( "sound/cuboid/axischange.wav", qfalse ); + + cgs.media.unpoweredSurgeLoop = trap_S_RegisterSound( "sound/buildables/human/unpowered_surge.wav", qfalse ); + cgs.media.powerSwitchSound = trap_S_RegisterSound( "sound/buildables/human/switch.wav", qfalse ); + for( i = 0; i < 4; i++ ) + cgs.media.powerZap[ i ] = trap_S_RegisterSound( va( "sound/buildables/human/powerzap%i.wav", i + 1 ), qfalse ); + + cgs.media.hitSound = trap_S_RegisterSound( "sound/feedback/hit.wav", qfalse ); } @@ -776,6 +796,21 @@ static void CG_RegisterGraphics( void ) "gfx/2d/numbers/nine_32b", "gfx/2d/numbers/minus_32b", }; + static char *sb_digital[ 12 ] = + { + "gfx/2d/digital/0", + "gfx/2d/digital/1", + "gfx/2d/digital/2", + "gfx/2d/digital/3", + "gfx/2d/digital/4", + "gfx/2d/digital/5", + "gfx/2d/digital/6", + "gfx/2d/digital/7", + "gfx/2d/digital/8", + "gfx/2d/digital/9", + "gfx/2d/digital/minus", + "gfx/2d/digital/comma" + }; static char *buildWeaponTimerPieShaders[ 8 ] = { "ui/assets/neutral/1_5pie", @@ -797,6 +832,9 @@ static void CG_RegisterGraphics( void ) for( i = 0; i < 11; i++ ) cgs.media.numberShaders[ i ] = trap_R_RegisterShader( sb_nums[ i ] ); + + for( i = 0; i < 12; i++ ) + cgs.media.digitalNumberShaders[ i ] = trap_R_RegisterShader( sb_digital[ i ] ); cgs.media.viewBloodShader = trap_R_RegisterShader( "gfx/damage/fullscreen_painblend" ); @@ -813,14 +851,13 @@ static void CG_RegisterGraphics( void ) cgs.media.backTileShader = trap_R_RegisterShader( "console" ); - // building shaders cgs.media.greenBuildShader = trap_R_RegisterShader("gfx/misc/greenbuild" ); cgs.media.redBuildShader = trap_R_RegisterShader("gfx/misc/redbuild" ); cgs.media.humanSpawningShader = trap_R_RegisterShader("models/buildables/telenode/rep_cyl" ); + cgs.media.humanUnpoweredSpawningShader = trap_R_RegisterShader("gfx/misc/unpowered_prebuild" ); - for( i = 0; i < CUBOID_CRACK_TEXTURES - 1; i++ ) - cgs.media.cuboidCracks[ i ] = trap_R_RegisterShader( va( "models/cuboid/cracks_%i", i ) ); + cgs.media.cuboidCracks = trap_R_RegisterShader( "models/cuboid/cracks" ); cgs.media.cuboidModel = trap_R_RegisterModel( "models/cuboid/cuboid.md3" ); cgs.media.cuboidRedBuildShader = trap_R_RegisterShader( "gfx/cuboid/build_red" ); @@ -832,9 +869,30 @@ static void CG_RegisterGraphics( void ) cg.waitForCB = qfalse; cg.cuboidValid = qfalse; cg.latestCBNumber = 0; + VectorSet( cg.cuboidSelection, 30, 30, 30 ); + + // ckit... + cgs.media.ckitBackgroundShader = trap_R_RegisterShader( "gfx/ckit/background" ); + cgs.media.ckitOverlayShader = trap_R_RegisterShader( "gfx/ckit/overlay" ); + + cgs.media.ckit_icon_bp = trap_R_RegisterShader( "gfx/ckit/icon_bp" ); + cgs.media.ckit_icon_current = trap_R_RegisterShader( "gfx/ckit/icon_current" ); + cgs.media.ckit_icon_depth = trap_R_RegisterShader( "gfx/ckit/icon_depth" ); + cgs.media.ckit_icon_health = trap_R_RegisterShader( "gfx/ckit/icon_health" ); + cgs.media.ckit_icon_height = trap_R_RegisterShader( "gfx/ckit/icon_height" ); + cgs.media.ckit_icon_network = trap_R_RegisterShader( "gfx/ckit/icon_network" ); + cgs.media.ckit_icon_nopower = trap_R_RegisterShader( "gfx/ckit/icon_nopower" ); + cgs.media.ckit_icon_nosurge = trap_R_RegisterShader( "gfx/ckit/icon_nosurge" ); + cgs.media.ckit_icon_off = trap_R_RegisterShader( "gfx/ckit/icon_off" ); + cgs.media.ckit_icon_power = trap_R_RegisterShader( "gfx/ckit/icon_power" ); + cgs.media.ckit_icon_storedbp = trap_R_RegisterShader( "gfx/ckit/icon_storedbp" ); + cgs.media.ckit_icon_surge = trap_R_RegisterShader( "gfx/ckit/icon_surge" ); + cgs.media.ckit_icon_time = trap_R_RegisterShader( "gfx/ckit/icon_time" ); + cgs.media.ckit_icon_voltage = trap_R_RegisterShader( "gfx/ckit/icon_voltage" ); + cgs.media.ckit_icon_width = trap_R_RegisterShader( "gfx/ckit/icon_width" ); for( i = 0; i < 15; i++ ) - cgs.media.splashLogo[ i ] = trap_R_RegisterShader( va( "cuboid/logo_%i.tga", i ) ); + cgs.media.splashLogo[ i ] = trap_R_RegisterShader( va( "cuboid/logo_%i.tga", i ) ); cgs.media.splashLeft = trap_R_RegisterShader( "cuboid/logo_left.tga" ); cgs.media.splashRight = trap_R_RegisterShader( "cuboid/logo_right.tga" ); @@ -845,6 +903,21 @@ static void CG_RegisterGraphics( void ) for( i = 0; i < 8; i++ ) cgs.media.buildWeaponTimerPie[ i ] = trap_R_RegisterShader( buildWeaponTimerPieShaders[ i ] ); + cgs.media.friendlyCrosshair = trap_R_RegisterShader( "gfx/2d/crosshair_friendly.tga" ); + cgs.media.hitCrosshair = trap_R_RegisterShader( "gfx/2d/crosshair_hit.tga" ); + + cgs.media.ch_dot = trap_R_RegisterShader( "gfx/2d/ch_dot.tga" ); + cgs.media.ch_dothit = trap_R_RegisterShader( "gfx/2d/ch_dothit.tga" ); + cgs.media.ch_circle = trap_R_RegisterShader( "gfx/2d/ch_circle.tga" ); + cgs.media.ch_circlehit = trap_R_RegisterShader( "gfx/2d/ch_circlehit.tga" ); + cgs.media.ch_friendly = trap_R_RegisterShader( "gfx/2d/ch_friendly.tga" ); + + cgs.media.ch_adot = trap_R_RegisterShader( "gfx/2d/ch_adot.tga" ); + cgs.media.ch_acircle = trap_R_RegisterShader( "gfx/2d/ch_acircle.tga" ); + cgs.media.ch_afriendly = trap_R_RegisterShader( "gfx/2d/ch_afriendly.tga" ); + cgs.media.ch_aheadshot = trap_R_RegisterShader( "gfx/2d/ch_aheadshot.tga" ); + + // player health cross shaders cgs.media.healthCross = trap_R_RegisterShader( "ui/assets/neutral/cross.tga" ); cgs.media.healthCross2X = trap_R_RegisterShader( "ui/assets/neutral/cross2.tga" ); @@ -885,6 +958,8 @@ static void CG_RegisterGraphics( void ) cgs.media.humanBuildableBleedPS = CG_RegisterParticleSystem( "humanBuildableBleedPS"); cgs.media.alienBuildableBleedPS = CG_RegisterParticleSystem( "alienBuildableBleedPS" ); + cgs.media.humanPowerZapPS = CG_RegisterParticleSystem( "humanPowerZapPS" ); + cgs.media.alienBleedPS = CG_RegisterParticleSystem( "alienBleedPS" ); cgs.media.humanBleedPS = CG_RegisterParticleSystem( "humanBleedPS" ); @@ -1010,6 +1085,13 @@ static void CG_RegisterClients( void ) cgs.media.jetpackFlashModel = trap_R_RegisterModel( "models/players/human_base/jetpack_flash.md3" ); cgs.media.battpackModel = trap_R_RegisterModel( "models/players/human_base/battpack.md3" ); + cgs.media.ckit_background = trap_R_RegisterModel( "models/weapons/ckit/ckit_background.md3" ); + cgs.media.ckit_overlay = trap_R_RegisterModel( "models/weapons/ckit/ckit_overlay.md3" ); + cgs.media.ckit_bigicona = trap_R_RegisterModel( "models/weapons/ckit/ckit_bigicona.md3" ); + cgs.media.ckit_bigiconb = trap_R_RegisterModel( "models/weapons/ckit/ckit_bigiconb.md3" ); + cgs.media.ckit_icon = trap_R_RegisterModel( "models/weapons/ckit/ckit_icon.md3" ); + cgs.media.ckit_digit = trap_R_RegisterModel( "models/weapons/ckit/ckit_digit.md3" ); + cg.charModelFraction = 1.0f; trap_UpdateScreen( ); diff --git a/src/cgame/cg_playerstate.c b/src/cgame/cg_playerstate.c index 242a3bb..f7c8074 100644 --- a/src/cgame/cg_playerstate.c +++ b/src/cgame/cg_playerstate.c @@ -271,6 +271,12 @@ void CG_CheckLocalSounds( playerState_t *ps, playerState_t *ops ) last = cg.time; } } + + if( ps->persistant[ PERS_HITS ] != ops->persistant[ PERS_HITS ] ) + { + trap_S_StartSound( NULL, cg.predictedPlayerState.clientNum, CHAN_AUTO, cgs.media.hitSound ); + cg.lastHitTime = cg.time; + } // if we are going into the intermission, don't start any voices if( cg.intermissionStarted ) diff --git a/src/cgame/cg_servercmds.c b/src/cgame/cg_servercmds.c index cf820c0..f9a173a 100644 --- a/src/cgame/cg_servercmds.c +++ b/src/cgame/cg_servercmds.c @@ -119,7 +119,6 @@ void CG_ParseServerinfo( void ) info = CG_ConfigString( CS_SERVERINFO ); cgs.timelimit = atoi( Info_ValueForKey( info, "timelimit" ) ); cgs.maxclients = atoi( Info_ValueForKey( info, "sv_maxclients" ) ); - cgs.markDeconstruct = atoi( Info_ValueForKey( info, "g_markDeconstruct" ) ); mapname = Info_ValueForKey( info, "mapname" ); Com_sprintf( cgs.mapname, sizeof( cgs.mapname ), "maps/%s.bsp", mapname ); } @@ -661,13 +660,9 @@ void CG_Menu( int menu, int arg ) //=============================== case MN_H_NOBP: - if( cgs.markDeconstruct ) - longMsg = "There is no power remaining. Free up power by marking " - "existing buildable objects."; - else - longMsg = "There is no power remaining. Free up power by deconstructing " - "existing buildable objects."; - shortMsg = "There is no power remaining"; + longMsg = "You don't have enough build points. Acquire more of them from " + "a Factory."; + shortMsg = "Insufficient build points"; type = DT_BUILD; break; diff --git a/src/cgame/cg_tutorial.c b/src/cgame/cg_tutorial.c index 212db33..cb596b9 100644 --- a/src/cgame/cg_tutorial.c +++ b/src/cgame/cg_tutorial.c @@ -202,27 +202,9 @@ static void CG_AlienBuilderText( char *text, playerState_t *ps ) if( ( es = CG_BuildableInRange( ps, NULL ) ) ) { - if( cgs.markDeconstruct ) - { - if( es->eFlags & EF_B_MARKED ) - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to unmark this structure for replacement\n", - CG_KeyNameForCommand( "deconstruct" ) ) ); - } - else - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to mark this structure for replacement\n", - CG_KeyNameForCommand( "deconstruct" ) ) ); - } - } - else - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to destroy this structure\n", - CG_KeyNameForCommand( "deconstruct" ) ) ); - } + Q_strcat( text, MAX_TUTORIAL_TEXT, + va( "Press %s to destroy this structure\n", + CG_KeyNameForCommand( "deconstruct" ) ) ); } if( ( ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) == BA_NONE ) @@ -378,27 +360,9 @@ static void CG_HumanCkitText( char *text, playerState_t *ps ) if( ( es = CG_BuildableInRange( ps, NULL ) ) ) { - if( cgs.markDeconstruct ) - { - if( es->eFlags & EF_B_MARKED ) - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to unmark this structure\n", - CG_KeyNameForCommand( "deconstruct" ) ) ); - } - else - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to mark this structure\n", - CG_KeyNameForCommand( "deconstruct" ) ) ); - } - } - else - { - Q_strcat( text, MAX_TUTORIAL_TEXT, - va( "Press %s to destroy this structure\n", - CG_KeyNameForCommand( "deconstruct" ) ) ); - } + Q_strcat( text, MAX_TUTORIAL_TEXT, + va( "Press %s to destroy this structure\n", + CG_KeyNameForCommand( "deconstruct" ) ) ); } } diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c index 7e22baf..b3dd4c7 100644 --- a/src/cgame/cg_weapons.c +++ b/src/cgame/cg_weapons.c @@ -605,15 +605,27 @@ static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi ) if( size < 0 ) size = 0; + wi->crossHairSize = size; + token = COM_Parse( &text_p ); if( !token ) break; - wi->crossHair = trap_R_RegisterShader( token ); - wi->crossHairSize = size; - - if( !wi->crossHair ) - CG_Printf( S_COLOR_RED "ERROR: weapon crosshair not found %s\n", token ); + if( !Q_stricmp( token, "none" ) ) + wi->crossHairType = CH_NONE; + else if( !Q_stricmp( token, "dot" ) ) + wi->crossHairType = CH_DOT; + else if( !Q_stricmp( token, "circle" ) ) + wi->crossHairType = CH_CIRCLE; + else if( !Q_stricmp( token, "circleddot" ) ) + wi->crossHairType = CH_CIRCLEDDOT; + else if( !Q_stricmp( token, "alien" ) ) + wi->crossHairType = CH_ALIEN; + else + { + Com_Printf( S_COLOR_YELLOW "WARNING: unknown cross hair type '%s'\n", token ); + wi->crossHairType = CH_NONE; + } continue; } @@ -869,6 +881,180 @@ static float CG_MachinegunSpinAngle( centity_t *cent, qboolean firing ) return angle; } +/* +============= +CG_GenerateCKitDisplay + +Figures out what should be displayed on the CKit's display +============= +*/ +static void CG_GenerateCKitDisplay( void ) +{ + int row = 0; + ckitDisplay_t *cd = &cg.ckitDisp; + entityState_t *es; + playerState_t *ps = &cg.predictedPlayerState; + qboolean target = qfalse; // true if looking at something + qboolean player = qfalse; // true if looking at a player (buildable otherwise) + int buildable; // buildable type + qboolean probing = qfalse; // measures voltages and currents + int powerNetwork; + int probeEntity; + qboolean building; // displays buildable's info + qboolean cuboid; // true if building cuboid + const buildableAttributes_t *battr; + int buildTimer; + + memset( &cg.ckitDisp, 0, sizeof( cg.ckitDisp ) ); + + /* + part 1: figure out what we're dealing with + */ + + powerNetwork = ( ps->misc[ MISC_INFOHEAD ] & 1023 ); + + probeEntity = ( ps->misc[ MISC_INFOHEAD ] >> 10 ) & 1023; + if( probeEntity != 1023 ) + { + target = qtrue; + if( probeEntity < MAX_CLIENTS ) + { + target = qtrue; + player = qtrue; + probing = ( cg.crosshairClientNum == probeEntity ); + } + else + probing = ( cg.crosshairBuildable == probeEntity ); + + es = &cg_entities[ probeEntity ].currentState; + } + + buildable = cg.predictedPlayerState.stats[ STAT_BUILDABLE ] &~ SB_VALID_TOGGLEBIT; + building = ( buildable != BA_NONE ); + if( building ) + { + battr = BG_Buildable( buildable, cg.cuboidSelection ); + cuboid = battr->cuboid; + } + + buildTimer = ps->stats[ STAT_MISC ]; + + /* + part 2: set up icons & text + */ + + cd->background = cgs.media.ckitBackgroundShader; + + // first big icon indicates if power is available + if( powerNetwork ) + cd->bigicona = cgs.media.ckit_icon_power; + else + cd->bigicona = cgs.media.ckit_icon_nopower; + + // second big icon always shows the building's state + if( target && !player ) + cd->bigiconb = CG_BuildablePowerStatusIcon( es ); + + if( building ) + { + if( cuboid ) + { + //width + cd->lines[ row ].icon = cgs.media.ckit_icon_width; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.1f", cg.cuboidSelection[ 0 ] ); + + //height + cd->lines[ row ].icon = cgs.media.ckit_icon_depth; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.1f", cg.cuboidSelection[ 1 ] ); + + //depth + cd->lines[ row ].icon = cgs.media.ckit_icon_height; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.1f", cg.cuboidSelection[ 2 ] ); + } + + //build points + cd->lines[ row ].icon = cgs.media.ckit_icon_bp; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", battr->buildPoints ); + + //health + cd->lines[ row ].icon = cgs.media.ckit_icon_health; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", battr->health ); + + //build time + cd->lines[ row ].icon = cgs.media.ckit_icon_time; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.1f", 0.001f * battr->buildTime ); + } + else + { + if( buildTimer ) + { + //build timer + cd->lines[ row ].icon = cgs.media.ckit_icon_time; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.1f", 0.001f * buildTimer ); + } + + // power network detector + cd->lines[ row ].icon = cgs.media.ckit_icon_network; + if( powerNetwork ) + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", powerNetwork ); + else + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "--------------------" ); + + + if( target ) + { + battr = BG_Buildable( es->modelindex, es->angles ); + + if( probing ) + { + if( !player ) + { + // ammeter + cd->lines[ row ].icon = cgs.media.ckit_icon_current; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.2f", 0.001f * ps->misc[ MISC_INFO1 ] ); + + // voltmeter + cd->lines[ row ].icon = cgs.media.ckit_icon_voltage; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.2f", 0.001f * ps->misc[ MISC_INFO2 ] ); + + // stored BP + if( BG_Buildable( es->modelindex, NULL )->hasStorage ) + { + cd->lines[ row ].icon = cgs.media.ckit_icon_storedbp; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%.1f", 0.1f * ps->misc[ MISC_INFO3 ] ); + } + } + else + { + // health + cd->lines[ row ].icon = cgs.media.ckit_icon_health; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", ps->misc[ MISC_INFO1 ] ); + + // stored BP + if( ps->misc[ MISC_INFO3 ] != -1 ) + { + cd->lines[ row ].icon = cgs.media.ckit_icon_storedbp; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", ps->misc[ MISC_INFO2 ] ); + } + } + } + + if( !player ) + { + //health + cd->lines[ row ].icon = cgs.media.ckit_icon_health; + if( battr->cuboid ) + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", es->constantLight ); + else + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", es->generic1 ); + + //build points + cd->lines[ row ].icon = cgs.media.ckit_icon_bp; + Com_sprintf( cd->lines[ row++ ].text, MAX_CKIT_TEXT, "%i", battr->buildPoints ); + } + } + } +} /* ============= @@ -1033,6 +1219,100 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent CG_DestroyParticleSystem( ¢->muzzlePS ); } + // NOTE: this thing is full of magic numbers - they were determined by trial and error, do not modify + if( ps && weaponNum == WP_HBUILD ) + { + refEntity_t ent; + vec3_t origin; + float y; + int i, j, l; + + CG_GenerateCKitDisplay( ); + + memset( &ent, 0, sizeof( ent ) ); + ent.renderfx = parent->renderfx; + CG_PositionEntityOnTag( &ent, parent, parent->hModel, "tag_weapon" ); + + // offset it a bit + VectorMA( ent.origin, -0.1f, ent.axis[ 0 ], ent.origin ); + + // background + if( ( ent.customShader = cg.ckitDisp.background ) ) + { + ent.hModel = cgs.media.ckit_background; + trap_R_AddRefEntityToScene( &ent ); + } + + // overlay + ent.hModel = cgs.media.ckit_overlay; + ent.customShader = cgs.media.ckitOverlayShader; + trap_R_AddRefEntityToScene( &ent ); + + // big icons + if( ( ent.customShader = cg.ckitDisp.bigicona ) ) + { + ent.hModel = cgs.media.ckit_bigicona; + trap_R_AddRefEntityToScene( &ent ); + } + + if( ( ent.customShader = cg.ckitDisp.bigiconb ) ) + { + ent.hModel = cgs.media.ckit_bigiconb; + trap_R_AddRefEntityToScene( &ent ); + } + + // backup the origin + VectorCopy( ent.origin, origin ); + + // draw all 6 rows + for( y = 0.0f, i = 0; i < MAX_CKIT_ROWS; i++, y += -0.48f ) + { + VectorMA( origin, y * 0.42f, ent.axis[ 0 ], ent.origin ); + VectorMA( ent.origin, y, ent.axis[ 2 ], ent.origin ); + + if( ( ent.customShader = cg.ckitDisp.lines[ i ].icon ) ) + { + ent.hModel = cgs.media.ckit_icon; + trap_R_AddRefEntityToScene( &ent ); + } + + ent.hModel = cgs.media.ckit_digit; + l = strlen( cg.ckitDisp.lines[ i ].text ); + + if( l > MAX_CKIT_COLUMNS ) + l = MAX_CKIT_COLUMNS; + + VectorMA( ent.origin, -0.3f * ( MAX_CKIT_COLUMNS - l - 1 ), ent.axis[ 1 ], ent.origin ); + + for( j = 0; j < l && j < MAX_CKIT_COLUMNS; j++ ) + { + int index; + char ch; + + ch = cg.ckitDisp.lines[ i ].text[ j ]; + + if( ch >= '0' && ch <= '9' ) + index = ch - '0'; + else if( ch == '-' ) + index = 10; + else if( ch == '.' ) + index = 11; + else + index = 0; + + if( random() > 0.995f ) + { + index += (int)( random() * 11 ); + index %= 11; + } + + ent.customShader = cgs.media.digitalNumberShaders[ index ]; + VectorMA( ent.origin, -0.3f, ent.axis[ 1 ], ent.origin ); + trap_R_AddRefEntityToScene( &ent ); + } + } + } + // add the flash if( !weapon->wim[ weaponMode ].continuousFlash || !firing ) { @@ -1124,7 +1404,7 @@ void CG_AddViewWeapon( playerState_t *ps ) weaponInfo_t *wi; weapon_t weapon = ps->weapon; weaponMode_t weaponMode = ps->generic1; - vec3_t cuboidSize; + vec3_t cuboidSize; // no weapon carried - can't draw it if( weapon == WP_NONE ) -- cgit