summaryrefslogtreecommitdiff
path: root/src/cgame
diff options
context:
space:
mode:
authorenneract <trem.redman@gmail.com>2014-02-25 13:03:43 +0100
committerenneract <trem.redman@gmail.com>2014-02-25 13:03:43 +0100
commitdac3d3127fc94231bdde0c0822bb12de01e9e836 (patch)
tree17829bc1a1b0ddb2d49421c5ea0114b4c2eff436 /src/cgame
parentcd9f8731a13a29d51a401f67ec2aa0b8962e01c8 (diff)
0.1.7
Diffstat (limited to 'src/cgame')
-rw-r--r--src/cgame/cg_buildable.c682
-rw-r--r--src/cgame/cg_draw.c81
-rw-r--r--src/cgame/cg_ents.c3
-rw-r--r--src/cgame/cg_event.c19
-rw-r--r--src/cgame/cg_local.h121
-rw-r--r--src/cgame/cg_main.c92
-rw-r--r--src/cgame/cg_playerstate.c6
-rw-r--r--src/cgame/cg_servercmds.c11
-rw-r--r--src/cgame/cg_tutorial.c48
-rw-r--r--src/cgame/cg_weapons.c292
10 files changed, 978 insertions, 377 deletions
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;i<bufl;i++)
+ for( i = 0; i < bufl; i++ )
{
- 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]);
+ 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 ] );
}
}
@@ -1620,28 +1691,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( &cent->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 )