From 10121326fbf07b701038893ecdb19f672c29c11e Mon Sep 17 00:00:00 2001 From: /dev/humancontroller Date: Sun, 13 Jul 2014 18:12:01 +0200 Subject: implement the range marker functionality, use it to create buildable range markers use the entity 64-bit client-masking extension when available --- src/cgame/cg_buildable.c | 70 ++++++++++++++++++ src/cgame/cg_draw.c | 62 ++++++++++++++++ src/cgame/cg_drawtools.c | 158 ++++++++++++++++++++++++++++++++++++++++ src/cgame/cg_ents.c | 26 +++++++ src/cgame/cg_local.h | 71 ++++++++++++++++++ src/cgame/cg_main.c | 185 ++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 571 insertions(+), 1 deletion(-) (limited to 'src/cgame') diff --git a/src/cgame/cg_buildable.c b/src/cgame/cg_buildable.c index ca170fd6..b859732e 100644 --- a/src/cgame/cg_buildable.c +++ b/src/cgame/cg_buildable.c @@ -391,6 +391,42 @@ void CG_InitBuildables( void ) cgs.media.teslaZapTS = CG_RegisterTrailSystem( "models/buildables/tesla/zap" ); } +/* +================ +CG_BuildableRangeMarkerProperties +================ +*/ +qboolean CG_GetBuildableRangeMarkerProperties( buildable_t bType, rangeMarkerType_t *rmType, float *range, vec3_t rgb ) +{ + shaderColorEnum_t shc; + + switch( bType ) + { + case BA_A_SPAWN: *range = CREEP_BASESIZE; shc = SHC_LIGHT_GREEN; break; + case BA_A_OVERMIND: *range = CREEP_BASESIZE; shc = SHC_DARK_GREEN; break; + case BA_A_ACIDTUBE: *range = ACIDTUBE_RANGE; shc = SHC_RED; break; + case BA_A_TRAPPER: *range = TRAPPER_RANGE; shc = SHC_PINK; break; + case BA_A_HIVE: *range = HIVE_SENSE_RANGE; shc = SHC_YELLOW; break; + case BA_H_MGTURRET: *range = MGTURRET_RANGE; shc = SHC_ORANGE; break; + case BA_H_TESLAGEN: *range = TESLAGEN_RANGE; shc = SHC_VIOLET; break; + case BA_H_DCC: *range = DC_RANGE; shc = SHC_GREEN_CYAN; break; + case BA_H_REACTOR: *range = REACTOR_BASESIZE; shc = SHC_DARK_BLUE; break; + case BA_H_REPEATER: *range = REPEATER_BASESIZE; shc = SHC_LIGHT_BLUE; break; + default: return qfalse; + } + + if( bType == BA_A_TRAPPER ) + *rmType = RMT_SPHERICAL_CONE_64; + else if( bType == BA_H_MGTURRET ) + *rmType = RMT_SPHERICAL_CONE_240; + else + *rmType = RMT_SPHERE; + + VectorCopy( cg_shaderColors[ shc ], rgb ); + + return qtrue; +} + /* =============== CG_SetBuildableLerpFrameAnimation @@ -596,6 +632,37 @@ static void CG_PositionAndOrientateBuildable( const vec3_t angles, const vec3_t VectorMA( inOrigin, fraction * -TRACE_DEPTH, normal, outOrigin ); } +/* +================ +CG_GhostBuildableRangeMarker +================ +*/ +static void CG_GhostBuildableRangeMarker( buildable_t buildable, const vec3_t origin, const vec3_t normal ) +{ + qboolean drawS, drawI, drawF; + float so, lo, th; + rangeMarkerType_t rmType; + float range; + vec3_t rgb; + + if( CG_GetRangeMarkerPreferences( &drawS, &drawI, &drawF, &so, &lo, &th ) && + CG_GetBuildableRangeMarkerProperties( buildable, &rmType, &range, rgb ) ) + { + vec3_t localOrigin, angles; + + if( buildable == BA_A_HIVE || buildable == BA_H_TESLAGEN ) + VectorMA( origin, BG_BuildableConfig( buildable )->maxs[ 2 ], normal, localOrigin ); + else + VectorCopy( origin, localOrigin ); + + if( rmType != RMT_SPHERE ) + vectoangles( normal, angles ); + + CG_DrawRangeMarker( rmType, localOrigin, ( rmType != RMT_SPHERE ? angles : NULL ), + range, drawS, drawI, drawF, rgb, so, lo, th ); + } +} + /* ================== CG_GhostBuildable @@ -618,6 +685,9 @@ void CG_GhostBuildable( buildable_t buildable ) BG_PositionBuildableRelativeToPlayer( ps, mins, maxs, CG_Trace, entity_origin, angles, &tr ); + if( cg_rangeMarkerForBlueprint.integer && tr.entityNum != ENTITYNUM_NONE ) + CG_GhostBuildableRangeMarker( buildable, entity_origin, tr.plane.normal ); + CG_PositionAndOrientateBuildable( ps->viewangles, entity_origin, tr.plane.normal, ps->clientNum, mins, maxs, ent.axis, ent.origin ); diff --git a/src/cgame/cg_draw.c b/src/cgame/cg_draw.c index f59c11aa..c334490d 100644 --- a/src/cgame/cg_draw.c +++ b/src/cgame/cg_draw.c @@ -3589,6 +3589,66 @@ void CG_ResetPainBlend( void ) cg.lastHealth = cg.snap->ps.stats[ STAT_HEALTH ]; } +/* +================ +CG_DrawBinaryShadersFinalPhases +================ +*/ +static void CG_DrawBinaryShadersFinalPhases( void ) +{ + float ss, f, l, u; + polyVert_t verts[ 4 ] = { + { { 0, 0, 0 }, { 0, 0 }, { 255, 255, 255, 255 } }, + { { 0, 0, 0 }, { 1, 0 }, { 255, 255, 255, 255 } }, + { { 0, 0, 0 }, { 1, 1 }, { 255, 255, 255, 255 } }, + { { 0, 0, 0 }, { 0, 1 }, { 255, 255, 255, 255 } } + }; + int i, j, k; + + if( !cg.numBinaryShadersUsed ) + return; + + ss = cg_binaryShaderScreenScale.value; + if( ss <= 0.0f ) + { + cg.numBinaryShadersUsed = 0; + return; + } + else if( ss > 1.0f ) + ss = 1.0f; + + ss = sqrt( ss ); + + f = 1.01f; // FIXME: is this a good choice to avoid near-clipping? + l = f * tan( DEG2RAD( cg.refdef.fov_x / 2 ) ) * ss; + u = f * tan( DEG2RAD( cg.refdef.fov_y / 2 ) ) * ss; + + VectorMA( cg.refdef.vieworg, f, cg.refdef.viewaxis[ 0 ], verts[ 0 ].xyz ); + VectorMA( verts[ 0 ].xyz, l, cg.refdef.viewaxis[ 1 ], verts[ 0 ].xyz ); + VectorMA( verts[ 0 ].xyz, u, cg.refdef.viewaxis[ 2 ], verts[ 0 ].xyz ); + VectorMA( verts[ 0 ].xyz, -2*l, cg.refdef.viewaxis[ 1 ], verts[ 1 ].xyz ); + VectorMA( verts[ 1 ].xyz, -2*u, cg.refdef.viewaxis[ 2 ], verts[ 2 ].xyz ); + VectorMA( verts[ 0 ].xyz, -2*u, cg.refdef.viewaxis[ 2 ], verts[ 3 ].xyz ); + + trap_R_AddPolyToScene( cgs.media.binaryAlpha1Shader, 4, verts ); + + for( i = 0; i < cg.numBinaryShadersUsed; ++i ) + { + for( j = 0; j < 4; ++j ) + { + for( k = 0; k < 3; ++k ) + verts[ j ].modulate[ k ] = cg.binaryShaderSettings[ i ].color[ k ]; + } + + if( cg.binaryShaderSettings[ i ].drawFrontline ) + trap_R_AddPolyToScene( cgs.media.binaryShaders[ i ].f3, 4, verts ); + if( cg.binaryShaderSettings[ i ].drawIntersection ) + trap_R_AddPolyToScene( cgs.media.binaryShaders[ i ].b3, 4, verts ); + } + + cg.numBinaryShadersUsed = 0; +} + /* ===================== CG_DrawActive @@ -3631,6 +3691,8 @@ void CG_DrawActive( stereoFrame_t stereoView ) VectorMA( cg.refdef.vieworg, -separation, cg.refdef.viewaxis[ 1 ], cg.refdef.vieworg ); + CG_DrawBinaryShadersFinalPhases( ); + // draw 3D view trap_R_RenderScene( &cg.refdef ); diff --git a/src/cgame/cg_drawtools.c b/src/cgame/cg_drawtools.c index f9d7999b..a47d39d7 100644 --- a/src/cgame/cg_drawtools.c +++ b/src/cgame/cg_drawtools.c @@ -437,3 +437,161 @@ char CG_GetColorCharForHealth( int clientnum ) health_char = '3'; return health_char; } + +/* +================ +CG_DrawSphere +================ +*/ +void CG_DrawSphere( const vec3_t center, float radius, int customShader, const float *shaderRGBA ) +{ + refEntity_t re; + memset( &re, 0, sizeof( re ) ); + + re.reType = RT_MODEL; + re.hModel = cgs.media.sphereModel; + re.customShader = customShader; + re.renderfx = RF_NOSHADOW; + if( shaderRGBA != NULL ) + { + int i; + for( i = 0; i < 4; ++i ) + re.shaderRGBA[ i ] = 255 * shaderRGBA[ i ]; + } + + VectorCopy( center, re.origin ); + + radius *= 0.01f; + VectorSet( re.axis[ 0 ], radius, 0, 0 ); + VectorSet( re.axis[ 1 ], 0, radius, 0 ); + VectorSet( re.axis[ 2 ], 0, 0, radius ); + re.nonNormalizedAxes = qtrue; + + trap_R_AddRefEntityToScene( &re ); +} + +/* +================ +CG_DrawSphericalCone +================ +*/ +void CG_DrawSphericalCone( const vec3_t tip, const vec3_t rotation, float radius, + qboolean a240, int customShader, const float *shaderRGBA ) +{ + refEntity_t re; + memset( &re, 0, sizeof( re ) ); + + re.reType = RT_MODEL; + re.hModel = a240 ? cgs.media.sphericalCone240Model : cgs.media.sphericalCone64Model; + re.customShader = customShader; + re.renderfx = RF_NOSHADOW; + if( shaderRGBA != NULL ) + { + int i; + for( i = 0; i < 4; ++i ) + re.shaderRGBA[ i ] = 255 * shaderRGBA[ i ]; + } + + VectorCopy( tip, re.origin ); + + radius *= 0.01f; + AnglesToAxis( rotation, re.axis ); + VectorScale( re.axis[ 0 ], radius, re.axis[ 0 ] ); + VectorScale( re.axis[ 1 ], radius, re.axis[ 1 ] ); + VectorScale( re.axis[ 2 ], radius, re.axis[ 2 ] ); + re.nonNormalizedAxes = qtrue; + + trap_R_AddRefEntityToScene( &re ); +} + +/* +================ +CG_DrawRangeMarker +================ +*/ +void CG_DrawRangeMarker( rangeMarkerType_t rmType, const vec3_t origin, const float *angles, float range, + qboolean drawSurface, qboolean drawIntersection, qboolean drawFrontline, + const vec3_t rgb, float surfaceOpacity, float lineOpacity, float lineThickness ) +{ + if( drawSurface ) + { + qhandle_t pcsh; + vec4_t rgba; + + pcsh = cgs.media.plainColorShader; + VectorCopy( rgb, rgba ); + rgba[ 3 ] = surfaceOpacity; + + switch( rmType ) + { + case RMT_SPHERE: + CG_DrawSphere( origin, range, pcsh, rgba ); + break; + case RMT_SPHERICAL_CONE_64: + CG_DrawSphericalCone( origin, angles, range, qfalse, pcsh, rgba ); + break; + case RMT_SPHERICAL_CONE_240: + CG_DrawSphericalCone( origin, angles, range, qtrue, pcsh, rgba ); + break; + } + } + + if( drawIntersection || drawFrontline ) + { + const cgMediaBinaryShader_t *mbsh; + cgBinaryShaderSetting_t *bshs; + int i; + + if( cg.numBinaryShadersUsed >= NUM_BINARY_SHADERS ) + return; + mbsh = &cgs.media.binaryShaders[ cg.numBinaryShadersUsed ]; + + if( rmType == RMT_SPHERE ) + { + if( range > lineThickness / 2 ) + { + if( drawIntersection ) + CG_DrawSphere( origin, range - lineThickness / 2, mbsh->b1, NULL ); + CG_DrawSphere( origin, range - lineThickness / 2, mbsh->f2, NULL ); + } + + if( drawIntersection ) + CG_DrawSphere( origin, range + lineThickness / 2, mbsh->b2, NULL ); + CG_DrawSphere( origin, range + lineThickness / 2, mbsh->f1, NULL ); + } + else if( rmType == RMT_SPHERICAL_CONE_64 || rmType == RMT_SPHERICAL_CONE_240 ) + { + qboolean a240; + float f, r; + vec3_t forward, tip; + + a240 = ( rmType == RMT_SPHERICAL_CONE_240 ); + f = lineThickness * ( a240 ? 0.26f : 0.8f ); + r = f + lineThickness * ( a240 ? 0.23f : 0.43f ); + AngleVectors( angles, forward, NULL, NULL ); + + if( range > r ) + { + VectorMA( origin, f, forward, tip ); + if( drawIntersection ) + CG_DrawSphericalCone( tip, angles, range - r, a240, mbsh->b1, NULL ); + CG_DrawSphericalCone( tip, angles, range - r, a240, mbsh->f2, NULL ); + } + + VectorMA( origin, -f, forward, tip ); + if( drawIntersection ) + CG_DrawSphericalCone( tip, angles, range + r, a240, mbsh->b2, NULL ); + CG_DrawSphericalCone( tip, angles, range + r, a240, mbsh->f1, NULL ); + } + + bshs = &cg.binaryShaderSettings[ cg.numBinaryShadersUsed ]; + + for( i = 0; i < 3; ++i ) + bshs->color[ i ] = 255 * lineOpacity * rgb[ i ]; + bshs->drawIntersection = drawIntersection; + bshs->drawFrontline = drawFrontline; + + ++cg.numBinaryShadersUsed; + } +} + diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c index d4e0f342..48545715 100644 --- a/src/cgame/cg_ents.c +++ b/src/cgame/cg_ents.c @@ -977,6 +977,28 @@ static void CG_CalcEntityLerpPositions( centity_t *cent ) } +/* +================ +CG_RangeMarker +================ +*/ +void CG_RangeMarker( centity_t *cent ) +{ + qboolean drawS, drawI, drawF; + float so, lo, th; + rangeMarkerType_t rmType; + float range; + vec3_t rgb; + + if( CG_GetRangeMarkerPreferences( &drawS, &drawI, &drawF, &so, &lo, &th ) && + CG_GetBuildableRangeMarkerProperties( cent->currentState.modelindex, &rmType, &range, rgb ) ) + { + CG_DrawRangeMarker( rmType, cent->lerpOrigin, ( rmType > 0 ? cent->lerpAngles : NULL ), + range, drawS, drawI, drawF, rgb, so, lo, th ); + } +} + + /* =============== CG_CEntityPVSEnter @@ -1089,6 +1111,10 @@ static void CG_AddCEntity( centity_t *cent ) CG_Buildable( cent ); break; + case ET_RANGE_MARKER: + CG_RangeMarker( cent ); + break; + case ET_MISSILE: CG_Missile( cent ); break; diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index 404351f5..5e4fde09 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -920,6 +920,15 @@ typedef struct // After this many msec the crosshair name fades out completely #define CROSSHAIR_CLIENT_TIMEOUT 1000 +typedef struct +{ + byte color[ 3 ]; + qboolean drawIntersection; + qboolean drawFrontline; +} cgBinaryShaderSetting_t; + +#define NUM_BINARY_SHADERS 256 + typedef struct { int clientFrame; // incremented each frame @@ -1156,6 +1165,9 @@ typedef struct int nearUsableBuildable; int nextWeaponClickTime; + + int numBinaryShadersUsed; + cgBinaryShaderSetting_t binaryShaderSettings[ NUM_BINARY_SHADERS ]; } cg_t; @@ -1163,6 +1175,17 @@ typedef struct // loaded at gamestate time are stored in cgMedia_t // Other media that can be tied to clients, weapons, or items are // stored in the clientInfo_t, itemInfo_t, weaponInfo_t, and powerupInfo_t + +typedef struct +{ + qhandle_t f1; + qhandle_t f2; + qhandle_t f3; + qhandle_t b1; + qhandle_t b2; + qhandle_t b3; +} cgMediaBinaryShader_t; + typedef struct { qhandle_t charsetShader; @@ -1197,6 +1220,14 @@ typedef struct qhandle_t redBuildShader; qhandle_t humanSpawningShader; + qhandle_t sphereModel; + qhandle_t sphericalCone64Model; + qhandle_t sphericalCone240Model; + + qhandle_t plainColorShader; + qhandle_t binaryAlpha1Shader; + cgMediaBinaryShader_t binaryShaders[ NUM_BINARY_SHADERS ]; + // disconnect qhandle_t disconnectPS; qhandle_t disconnectSound; @@ -1411,6 +1442,22 @@ typedef struct void ( *function )( void ); } consoleCommand_t; +typedef enum +{ + SHC_DARK_BLUE, + SHC_LIGHT_BLUE, + SHC_GREEN_CYAN, + SHC_VIOLET, + SHC_YELLOW, + SHC_ORANGE, + SHC_LIGHT_GREEN, + SHC_DARK_GREEN, + SHC_RED, + SHC_PINK, + SHC_GREY, + SHC_NUM_SHADER_COLORS +} shaderColorEnum_t; + //============================================================================== extern cgs_t cgs; @@ -1423,6 +1470,8 @@ extern upgradeInfo_t cg_upgrades[ 32 ]; extern buildableInfo_t cg_buildables[ BA_NUM_BUILDABLES ]; +extern const vec3_t cg_shaderColors[ SHC_NUM_SHADER_COLORS ]; + extern markPoly_t cg_markPolys[ MAX_MARK_POLYS ]; extern vmCvar_t cg_teslaTrailTime; @@ -1509,6 +1558,16 @@ extern vmCvar_t cg_disableCommandDialogs; extern vmCvar_t cg_disableScannerPlane; extern vmCvar_t cg_tutorial; +extern vmCvar_t cg_rangeMarkerDrawSurface; +extern vmCvar_t cg_rangeMarkerDrawIntersection; +extern vmCvar_t cg_rangeMarkerDrawFrontline; +extern vmCvar_t cg_rangeMarkerSurfaceOpacity; +extern vmCvar_t cg_rangeMarkerLineOpacity; +extern vmCvar_t cg_rangeMarkerLineThickness; +extern vmCvar_t cg_rangeMarkerForBlueprint; +extern vmCvar_t cg_rangeMarkerBuildableTypes; +extern vmCvar_t cg_binaryShaderScreenScale; + extern vmCvar_t cg_painBlendUpRate; extern vmCvar_t cg_painBlendDownRate; extern vmCvar_t cg_painBlendMax; @@ -1567,6 +1626,10 @@ void CG_BuildSpectatorString( void ); qboolean CG_FileExists( char *filename ); void CG_RemoveNotifyLine( void ); void CG_AddNotifyText( void ); +qboolean CG_GetRangeMarkerPreferences( qboolean *drawSurface, qboolean *drawIntersection, + qboolean *drawFrontline, float *surfaceOpacity, + float *lineOpacity, float *lineThickness ); +void CG_UpdateBuildableRangeMarkerMask( void ); // @@ -1609,6 +1672,12 @@ void CG_DrawTopBottom(float x, float y, float w, float h, float size); qboolean CG_WorldToScreen( vec3_t point, float *x, float *y ); char *CG_KeyBinding( const char *bind ); char CG_GetColorCharForHealth( int clientnum ); +void CG_DrawSphere( const vec3_t center, float radius, int customShader, const float *shaderRGBA ); +void CG_DrawSphericalCone( const vec3_t tip, const vec3_t rotation, float radius, + qboolean a240, int customShader, const float *shaderRGBA ); +void CG_DrawRangeMarker( rangeMarkerType_t rmType, const vec3_t origin, const float *angles, float range, + qboolean drawSurface, qboolean drawIntersection, qboolean drawFrontline, + const vec3_t rgb, float surfaceOpacity, float lineOpacity, float lineThickness ); // // cg_draw.c @@ -1659,6 +1728,7 @@ 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 ); +qboolean CG_GetBuildableRangeMarkerProperties( buildable_t bType, rangeMarkerType_t *rmType, float *range, vec3_t rgb ); // // cg_animation.c @@ -1709,6 +1779,7 @@ void CG_PositionEntityOnTag( refEntity_t *entity, const refEntity_t *pare qhandle_t parentModel, char *tagName ); void CG_PositionRotatedEntityOnTag( refEntity_t *entity, const refEntity_t *parent, qhandle_t parentModel, char *tagName ); +void CG_RangeMarker( centity_t *cent ); // diff --git a/src/cgame/cg_main.c b/src/cgame/cg_main.c index 25935b8b..4b7b1758 100644 --- a/src/cgame/cg_main.c +++ b/src/cgame/cg_main.c @@ -191,6 +191,16 @@ vmCvar_t cg_disableCommandDialogs; vmCvar_t cg_disableScannerPlane; vmCvar_t cg_tutorial; +vmCvar_t cg_rangeMarkerDrawSurface; +vmCvar_t cg_rangeMarkerDrawIntersection; +vmCvar_t cg_rangeMarkerDrawFrontline; +vmCvar_t cg_rangeMarkerSurfaceOpacity; +vmCvar_t cg_rangeMarkerLineOpacity; +vmCvar_t cg_rangeMarkerLineThickness; +vmCvar_t cg_rangeMarkerForBlueprint; +vmCvar_t cg_rangeMarkerBuildableTypes; +vmCvar_t cg_binaryShaderScreenScale; + vmCvar_t cg_painBlendUpRate; vmCvar_t cg_painBlendDownRate; vmCvar_t cg_painBlendMax; @@ -308,6 +318,18 @@ static cvarTable_t cvarTable[ ] = { &cg_disableCommandDialogs, "cg_disableCommandDialogs", "0", CVAR_ARCHIVE }, { &cg_disableScannerPlane, "cg_disableScannerPlane", "0", CVAR_ARCHIVE }, { &cg_tutorial, "cg_tutorial", "1", CVAR_ARCHIVE }, + + { &cg_rangeMarkerDrawSurface, "cg_rangeMarkerDrawSurface", "1", CVAR_ARCHIVE }, + { &cg_rangeMarkerDrawIntersection, "cg_rangeMarkerDrawIntersection", "1", CVAR_ARCHIVE }, + { &cg_rangeMarkerDrawFrontline, "cg_rangeMarkerDrawFrontline", "1", CVAR_ARCHIVE }, + { &cg_rangeMarkerSurfaceOpacity, "cg_rangeMarkerSurfaceOpacity", "0.08", CVAR_ARCHIVE }, + { &cg_rangeMarkerLineOpacity, "cg_rangeMarkerLineOpacity", "0.4", CVAR_ARCHIVE }, + { &cg_rangeMarkerLineThickness, "cg_rangeMarkerLineThickness", "4.0", CVAR_ARCHIVE }, + { &cg_rangeMarkerForBlueprint, "cg_rangeMarkerForBlueprint", "1", CVAR_ARCHIVE }, + { &cg_rangeMarkerBuildableTypes, "cg_rangeMarkerBuildableTypes", "support", CVAR_ARCHIVE }, + { NULL, "cg_buildableRangeMarkerMask", "", CVAR_USERINFO }, + { &cg_binaryShaderScreenScale, "cg_binaryShaderScreenScale", "1.0", CVAR_ARCHIVE }, + { &cg_hudFiles, "cg_hudFiles", "ui/hud.txt", CVAR_ARCHIVE}, { &cg_hudFilesEnable, "cg_hudFilesEnable", "0", CVAR_ARCHIVE}, { NULL, "cg_alienConfig", "", CVAR_ARCHIVE }, @@ -418,6 +440,106 @@ static void CG_SetUIVars( void ) trap_Cvar_Set( "ui_stages", va( "%d %d", cgs.alienStage, cgs.humanStage ) ); } +/* +================ +CG_UpdateBuildableRangeMarkerMask +================ +*/ +void CG_UpdateBuildableRangeMarkerMask( void ) +{ + static int mc = 0; + + if( cg_rangeMarkerBuildableTypes.modificationCount != mc ) + { + int brmMask; + char buffer[ MAX_CVAR_VALUE_STRING ]; + char *p, *q; + buildable_t buildable; + + brmMask = 0; + + if( !cg_rangeMarkerBuildableTypes.string[ 0 ] ) + goto empty; + + Q_strncpyz( buffer, cg_rangeMarkerBuildableTypes.string, sizeof( buffer ) ); + p = &buffer[ 0 ]; + + for(;;) + { + q = strchr( p, ',' ); + if( q ) + *q = '\0'; + + while( *p == ' ' ) + ++p; + + buildable = BG_BuildableByName( p )->number; + + if( buildable != BA_NONE ) + { + brmMask |= 1 << buildable; + } + else if( !Q_stricmp( p, "all" ) ) + { + brmMask |= ( 1 << BA_A_OVERMIND ) | ( 1 << BA_A_SPAWN ) | + ( 1 << BA_A_ACIDTUBE ) | ( 1 << BA_A_TRAPPER ) | ( 1 << BA_A_HIVE ) | + ( 1 << BA_H_REACTOR ) | ( 1 << BA_H_REPEATER ) | ( 1 << BA_H_DCC ) | + ( 1 << BA_H_MGTURRET ) | ( 1 << BA_H_TESLAGEN ); + } + else + { + char *pp; + int only; + + if( !Q_stricmpn( p, "alien", 5 ) ) + { + pp = p + 5; + only = ( 1 << BA_A_OVERMIND ) | ( 1 << BA_A_SPAWN ) | + ( 1 << BA_A_ACIDTUBE ) | ( 1 << BA_A_TRAPPER ) | ( 1 << BA_A_HIVE ); + } + else if( !Q_stricmpn( p, "human", 5 ) ) + { + pp = p + 5; + only = ( 1 << BA_H_REACTOR ) | ( 1 << BA_H_REPEATER ) | ( 1 << BA_H_DCC ) | + ( 1 << BA_H_MGTURRET ) | ( 1 << BA_H_TESLAGEN ); + } + else + { + pp = p; + only = ~0; + } + + if( pp != p && !*pp ) + { + brmMask |= only; + } + else if( !Q_stricmp( pp, "support" ) ) + { + brmMask |= only & ( ( 1 << BA_A_OVERMIND ) | ( 1 << BA_A_SPAWN ) | + ( 1 << BA_H_REACTOR ) | ( 1 << BA_H_REPEATER ) | ( 1 << BA_H_DCC ) ); + } + else if( !Q_stricmp( pp, "offensive" ) ) + { + brmMask |= only & ( ( 1 << BA_A_ACIDTUBE ) | ( 1 << BA_A_TRAPPER ) | ( 1 << BA_A_HIVE ) | + ( 1 << BA_H_MGTURRET ) | ( 1 << BA_H_TESLAGEN ) ); + } + else + Com_Printf( S_COLOR_YELLOW "WARNING: unknown buildable or group: %s\n", p ); + } + + if( q ) + p = q + 1; + else + break; + } + + empty: + trap_Cvar_Set( "cg_buildableRangeMarkerMask", va( "%i", brmMask ) ); + + mc = cg_rangeMarkerBuildableTypes.modificationCount; + } +} + /* ================= CG_UpdateCvars @@ -435,7 +557,7 @@ void CG_UpdateCvars( void ) // check for modications here CG_SetUIVars( ); - + CG_UpdateBuildableRangeMarkerMask(); } @@ -811,6 +933,22 @@ static void CG_RegisterGraphics( void ) cgs.media.alienBleedPS = CG_RegisterParticleSystem( "alienBleedPS" ); cgs.media.humanBleedPS = CG_RegisterParticleSystem( "humanBleedPS" ); + cgs.media.sphereModel = trap_R_RegisterModel( "models/generic/sphere" ); + cgs.media.sphericalCone64Model = trap_R_RegisterModel( "models/generic/sphericalCone64" ); + cgs.media.sphericalCone240Model = trap_R_RegisterModel( "models/generic/sphericalCone240" ); + + cgs.media.plainColorShader = trap_R_RegisterShader( "gfx/plainColor" ); + cgs.media.binaryAlpha1Shader = trap_R_RegisterShader( "gfx/binary/alpha1" ); + for( i = 0; i < NUM_BINARY_SHADERS; ++i ) + { + cgs.media.binaryShaders[ i ].f1 = trap_R_RegisterShader( va( "gfx/binary/%03i_F1", i ) ); + cgs.media.binaryShaders[ i ].f2 = trap_R_RegisterShader( va( "gfx/binary/%03i_F2", i ) ); + cgs.media.binaryShaders[ i ].f3 = trap_R_RegisterShader( va( "gfx/binary/%03i_F3", i ) ); + cgs.media.binaryShaders[ i ].b1 = trap_R_RegisterShader( va( "gfx/binary/%03i_B1", i ) ); + cgs.media.binaryShaders[ i ].b2 = trap_R_RegisterShader( va( "gfx/binary/%03i_B2", i ) ); + cgs.media.binaryShaders[ i ].b3 = trap_R_RegisterShader( va( "gfx/binary/%03i_B3", i ) ); + } + CG_BuildableStatusParse( "ui/assets/human/buildstat.cfg", &cgs.humanBuildStat ); CG_BuildableStatusParse( "ui/assets/alien/buildstat.cfg", &cgs.alienBuildStat ); @@ -1911,3 +2049,48 @@ static char *CG_VoIPString( void ) return voipString; } +const vec3_t cg_shaderColors[ SHC_NUM_SHADER_COLORS ] = +{ + { 0.0f, 0.0f, 0.75f }, // dark blue + { 0.3f, 0.35f, 0.625f }, // light blue + { 0.0f, 0.625f, 0.563f }, // green-cyan + { 0.313f, 0.0f, 0.625f }, // violet + { 0.625f, 0.625f, 0.0f }, // yellow + { 0.875f, 0.313f, 0.0f }, // orange + { 0.375f, 0.625f, 0.375f }, // light green + { 0.0f, 0.438f, 0.0f }, // dark green + { 1.0f, 0.0f, 0.0f }, // red + { 0.625f, 0.375f, 0.4f }, // pink + { 0.313f, 0.313f, 0.313f } // grey +}; + +/* +================ +CG_RangeMarkerPreferences +================ +*/ +qboolean CG_GetRangeMarkerPreferences( qboolean *drawSurface, qboolean *drawIntersection, + qboolean *drawFrontline, float *surfaceOpacity, + float *lineOpacity, float *lineThickness ) +{ + *drawSurface = !!cg_rangeMarkerDrawSurface.integer; + *drawIntersection = !!cg_rangeMarkerDrawIntersection.integer; + *drawFrontline = !!cg_rangeMarkerDrawFrontline.integer; + *surfaceOpacity = cg_rangeMarkerSurfaceOpacity.value; + *lineOpacity = cg_rangeMarkerLineOpacity.value; + *lineThickness = cg_rangeMarkerLineThickness.value; + + if( ( *drawSurface && *surfaceOpacity > 0.0f ) || + ( ( *drawIntersection || *drawFrontline ) && *lineOpacity > 0.0f && + *lineThickness > 0.0f && cg_binaryShaderScreenScale.value > 0.0f ) ) + { + if( *surfaceOpacity > 1.0f ) + *surfaceOpacity = 1.0f; + if( *lineOpacity > 1.0f ) + *lineOpacity = 1.0f; + return qtrue; + } + + return qfalse; +} + -- cgit