2005-03-09 01:31:56 +00:00
//======== (C) Copyright 2001 Charles G. Cleveland All rights reserved. =========
//
// The copyright to the contents herein is the property of Charles G. Cleveland.
// The contents may be used and/or copied only with the written permission of
// Charles G. Cleveland, or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// Purpose: All graphical HUD operations
//
// $Workfile: AvHHudRender.cpp $
// $Date: 2002/10/24 21:31:13 $
//
//-------------------------------------------------------------------------------
// $Log: AvHHudRender.cpp,v $
// Revision 1.25 2002/10/24 21:31:13 Flayra
// - Removed some parts of energy drawing (unneeded clutter)
// - New marine HUD artwork (mainhud.spr)
// - Reworked upgrade drawing to only draw one of a type of upgrade (this was the last thing for v1.0, so it's a bit yucky)
//
// Revision 1.24 2002/10/18 22:20:14 Flayra
// - Fixed alien mass crash when a player left the server
//
// Revision 1.23 2002/10/16 00:59:33 Flayra
// - Added titles for umbra and primal scream
// - Don't draw building circles for entities on the other team (not even for commander)
// - Tried drawing building circles for ghost buildings, but it was confusing
//
// Revision 1.22 2002/10/03 18:56:10 Flayra
// - Moved alien energy to fuser3
// - Changed limits for energy and resources
// - Draw order icons centered around order position
// - Don't draw health rings for opposing teams
//
// Revision 1.21 2002/09/25 20:48:37 Flayra
// - Allow more UI to draw when gestating
// - Only draw text for blip closest to reticle
// - Don't draw stuff when dead
// - Changed order blinking
//
// Revision 1.20 2002/09/23 22:19:58 Flayra
// - Added "paralyzed" indicator
// - HUD element repositioning and refactoring
// - Added alien build circles
// - Added visible motion-tracking sprite to marine HUD
// - Removed special siege sprite
//
// Revision 1.19 2002/09/09 19:57:33 Flayra
// - Fixed black edges in D3D
// - Added blinking "webbed" indicator
// - Refactored UI constants
// - Fixed help icons
// - Added hive info indicator
// - Draw more info as spectator
//
// Revision 1.18 2002/08/31 18:01:01 Flayra
// - Work at VALVe
//
// Revision 1.17 2002/08/16 02:38:44 Flayra
// - Draw "webbed" message
// - Draw health for buildings and players
// - Removed old overwatch code
//
// Revision 1.16 2002/08/09 01:03:36 Flayra
// - Started refactoring for moving variable sprite hole drawing into TriAPI
//
// Revision 1.15 2002/08/02 21:56:54 Flayra
// - Added reticle help, new tooltip system and much nicer order drawing! Also changed jetpack label to use font, and refactored some sprite names.
//
// Revision 1.14 2002/07/26 23:05:06 Flayra
// - Generate numerical feedback for damage events
//
// Revision 1.13 2002/07/23 17:09:41 Flayra
// - Add ability to centered, translated strings, visually-smooth energy level, new hive sight info, draw parasited message, draw marine upgrades, new method of drawing alien upgrades (overlapping and offset)
//
// Revision 1.12 2002/07/10 14:42:26 Flayra
// - Removed cl_particleinfo drawing differences
//
// Revision 1.11 2002/07/08 17:07:56 Flayra
// - Started to add display of marine upgrade sprite, fixed bug where building indicators aren't displayed after a map change, info_location drawing changes, primal scream color tweak, removed old hive drawing code
//
// Revision 1.10 2002/07/01 21:36:23 Flayra
// - Added primal scream effect, added building ranges for ghost buildings, removed outdated code, removed mapping build sprite, call vidinit() on hive sight sprites
//
// Revision 1.9 2002/06/25 18:03:09 Flayra
// - Added info_locations, removed old weapon help system, added smooth resource swelling, lots of alien UI usability changes, fixed problem with ghost building
//
// Revision 1.8 2002/06/10 19:57:01 Flayra
// - Allow drawing just a portion of a texture when scaling it, draw team hierarchy for soldiers
//
// Revision 1.7 2002/06/03 16:49:20 Flayra
// - Help sprites moved into one animated sprite
//
// Revision 1.6 2002/05/28 17:49:06 Flayra
// - Hive sight sprite changes
//
// Revision 1.5 2002/05/23 02:33:42 Flayra
// - Post-crash checkin. Restored @Backup from around 4/16. Contains changes for last four weeks of development.
//
//===============================================================================
# include "mod/AvHHud.h"
# include "cl_dll/hud.h"
# include "cl_dll/cl_util.h"
# include "mod/AvHConstants.h"
# include "mod/AvHClientVariables.h"
# include "mod/AvHSpecials.h"
# include "common/cl_entity.h"
# include "mod/AvHTitles.h"
# include "pm_shared/pm_debug.h"
# include "util/MathUtil.h"
# include "common/r_efx.h"
# include "cl_dll/eventscripts.h"
# include "mod/AvHSprites.h"
# include "ui/UIUtil.h"
# include "types.h"
# include <signal.h>
# include "common/com_model.h"
# include "cl_dll/studio_util.h"
# include "cl_dll/r_studioint.h"
# include "mod/AvHMiniMap.h"
# include "mod/AvHActionButtons.h"
# include "util/STLUtil.h"
# include "mod/AvHSharedUtil.h"
# include "common/event_api.h"
# include "mod/AvHScriptManager.h"
2005-04-01 03:04:57 +00:00
# include <p_vector.h>
# include <papi.h>
2005-03-09 01:31:56 +00:00
# include "mod/AvHParticleSystemManager.h"
# include "mod/AvHTeamHierarchy.h"
# include "mod/AvHClientUtil.h"
# include "mod/AvHTooltip.h"
# include "cl_dll/demo.h"
# include "common/demo_api.h"
# include "mod/AvHHudConstants.h"
# include "mod/AvHPlayerUpgrade.h"
# include "mod/AvHCommanderModeHandler.h"
# include "common/ref_params.h"
# include "mod/AvHTechImpulsePanel.h"
# include "mod/AvHServerVariables.h"
# include "mod/AvHSpriteAPI.h"
# include "mod/AvHParticleEditorHandler.h"
void IN_GetMousePos ( int * mx , int * my ) ;
// Externs
extern int g_iVisibleMouse ;
extern playermove_t * pmove ;
extern engine_studio_api_t IEngineStudio ;
extern " C " Vector gPredictedPlayerOrigin ;
extern vec3_t v_origin ;
extern vec3_t v_angles ;
//extern vec3_t gPlayerOrigin;
//extern vec3_t gPlayerAngles;
extern ref_params_s * pDemoRefParams ;
extern vec3_t gPlaybackViewOrigin ;
extern AvHCommanderModeHandler gCommanderHandler ;
extern AvHParticleEditorHandler gParticleEditorHandler ;
float kD3DErrorValue = 0.01f ;
vec3_t GetViewOrigin ( )
{
vec3_t theOrigin = v_origin ;
//cl_entity_t* theViewEntity = gEngfuncs.GetLocalPlayer();//gEngfuncs.GetViewModel();
//if(theViewEntity && /*pDemoRefParams &&*/ gEngfuncs.pDemoAPI->IsPlayingback())
//{
// //theOrigin = pDemoRefParams->vieworg;
// theOrigin = theViewEntity->origin;
//}
if ( gEngfuncs . pDemoAPI - > IsPlayingback ( ) )
{
theOrigin = gPlaybackViewOrigin ;
}
return theOrigin ;
// return v_origin;
}
void BuildLerpedPoint ( float inXPercentage , float inYPercentage , const Vector & inUpperLeft , const Vector & inUpperRight , const Vector & inLowerLeft , Vector & outPoint )
{
ASSERT ( inXPercentage > = 0.0f ) ;
ASSERT ( inXPercentage < = 1.0f ) ;
ASSERT ( inYPercentage > = 0.0f ) ;
ASSERT ( inYPercentage < = 1.0f ) ;
Vector theUpperLeftToUpperRight ;
VectorSubtract ( inUpperRight , inUpperLeft , theUpperLeftToUpperRight ) ;
Vector theUpperLeftToLowerLeft ;
VectorSubtract ( inLowerLeft , inUpperLeft , theUpperLeftToLowerLeft ) ;
Vector theXComp ;
VectorScale ( theUpperLeftToUpperRight , inXPercentage , theXComp ) ;
Vector theYComp ;
VectorScale ( theUpperLeftToLowerLeft , inYPercentage , theYComp ) ;
outPoint = inUpperLeft + theXComp + theYComp ;
//float theXPercentage = (outPoint.x - inUpperLeft.x)/(theXComp.x + theYComp.x);
//float theYPercentage = (outPoint.y - inUpperLeft.y)/(theXComp.y + theYComp.y);
}
void CalculatePlaneInfo ( const Vector & inUpperLeft , const Vector & inUpperRight , const Vector & inLowerLeft , float & outD , Vector & outPlaneNormal )
{
// Cross two vectors for plane normal
Vector theUpperRightToUpperLeft ;
VectorSubtract ( inUpperLeft , inUpperRight , theUpperRightToUpperLeft ) ;
theUpperRightToUpperLeft = theUpperRightToUpperLeft . Normalize ( ) ;
Vector theUpperLeftToLowerLeft ;
VectorSubtract ( inLowerLeft , inUpperLeft , theUpperLeftToLowerLeft ) ;
theUpperLeftToLowerLeft = theUpperLeftToLowerLeft . Normalize ( ) ;
// Calculate plane normal
CrossProduct ( theUpperRightToUpperLeft , theUpperLeftToLowerLeft , outPlaneNormal ) ;
// Plug in one of the points for D (Ax + By + Cz = -D)
outD = - ( outPlaneNormal . x * inUpperLeft . x + outPlaneNormal . y * inUpperLeft . y + outPlaneNormal . z * inUpperLeft . z ) ;
}
void CalculatePointOnPlane ( int inXPos , int inYPos , const Vector & inOrigin , const Vector & inPlaneNormal , float inPlaneD , Vector & outPoint )
{
Vector theRay ;
CreatePickingRay ( inXPos , inYPos , theRay ) ;
// Solve for parametric t
float thePlaneA = inPlaneNormal . x ;
float thePlaneB = inPlaneNormal . y ;
float thePlaneC = inPlaneNormal . z ;
float theT = - ( thePlaneA * inOrigin . x + thePlaneB * inOrigin . y + thePlaneC * inOrigin . z + inPlaneD ) / ( thePlaneA * theRay . x + thePlaneB * theRay . y + thePlaneC * theRay . z ) ;
// Now we have t, solve for the endpoint
outPoint . x = inOrigin . x + theT * theRay . x ;
outPoint . y = inOrigin . y + theT * theRay . y ;
outPoint . z = inOrigin . z + theT * theRay . z ;
}
void ProjectPointFromViewOrigin ( int inDistanceToProject , int inScreenX , int inScreenY , Vector & outResult )
{
Vector theRay ;
CreatePickingRay ( inScreenX , inScreenY , theRay ) ;
// project default distance along picking ray
VectorMA ( GetViewOrigin ( ) , inDistanceToProject , theRay , outResult ) ;
}
void AvHHud : : DrawTranslatedString ( int inX , int inY , const char * inStringToTranslate , bool inCentered , bool inIgnoreUpgrades , bool inTrimExtraInfo )
{
// Translate
string theTranslatedText ;
LocalizeString ( inStringToTranslate , theTranslatedText ) ;
if ( theTranslatedText [ 0 ] = = ' # ' )
{
theTranslatedText = theTranslatedText . substr ( 1 , theTranslatedText . size ( ) ) ;
}
if ( inTrimExtraInfo )
{
AvHCUTrimExtraneousLocationText ( theTranslatedText ) ;
}
// Draw it
if ( theTranslatedText ! = " " )
{
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , inIgnoreUpgrades , false ) ;
char theCharBuffer [ 512 ] ;
sprintf ( theCharBuffer , " %s " , theTranslatedText . c_str ( ) ) ;
if ( inCentered )
{
this - > DrawHudStringCentered ( inX , inY , ScreenWidth ( ) , theCharBuffer , theR , theG , theB ) ;
}
else
{
this - > DrawHudString ( inX , inY , ScreenWidth ( ) , theCharBuffer , theR , theG , theB ) ;
}
}
}
bool gWarpHUDSprites = false ;
float gWarpXAmount = 0.0f ;
float gWarpYAmount = 0.0f ;
float gWarpXSpeed = 0.0f ;
float gWarpYSpeed = 0.0f ;
void SetWarpHUDSprites ( bool inMode , float inWarpXAmount = 0.0f , float inWarpYAmount = 0.0f , float inWarpXSpeed = 0.0f , float inWarpYSpeed = 0.0f )
{
gWarpHUDSprites = inMode ;
gWarpXAmount = inWarpXAmount ;
gWarpYAmount = inWarpYAmount ;
gWarpXSpeed = inWarpXSpeed ;
gWarpYSpeed = inWarpYSpeed ;
}
void DrawScaledHUDSprite ( int inSpriteHandle , int inMode , int inRowsInSprite = 1 , int inX = 0 , int inY = 0 , int inWidth = ScreenWidth ( ) , int inHeight = ScreenHeight ( ) , int inForceSpriteFrame = - 1 , float inStartU = 0.0f , float inStartV = 0.0f , float inEndU = 1.0f , float inEndV = 1.0f , float inRotateUVRadians = 0.0f , bool inUVWrapsOverFrames = false )
{
// Count number of frames
int theNumFrames = SPR_Frames ( inSpriteHandle ) ;
//int theSpriteWidth = SPR_Width(inSpriteHandle, 0);
//int theSpriteHeight = SPR_Height(inSpriteHandle, 0);
//float theAspectRatio = theSpriteWidth/theSpriteHeight;
// ASSERT that the the number of rows makes sense for the number of frames
ASSERT ( theNumFrames > 0 ) ;
float theFloatNumCols = ( float ) theNumFrames / inRowsInSprite ;
int theNumCols = ( int ) theFloatNumCols ;
ASSERT ( theNumCols = = theFloatNumCols ) ;
//int theNumRows = theNumFrames/theNumCols;
int theNumRows = inRowsInSprite ;
// Allow scaling of one frame, without tiling
if ( inForceSpriteFrame ! = - 1 )
{
theNumRows = theNumCols = 1 ;
}
// Make sure coords are bounded to allowable ranges
inStartU = min ( max ( inStartU , kD3DErrorValue ) , 1.0f - kD3DErrorValue ) ;
inStartV = min ( max ( inStartV , kD3DErrorValue ) , 1.0f - kD3DErrorValue ) ;
inEndU = min ( max ( inEndU , kD3DErrorValue ) , 1.0f - kD3DErrorValue ) ;
inEndV = min ( max ( inEndV , kD3DErrorValue ) , 1.0f - kD3DErrorValue ) ;
if ( inRotateUVRadians ! = 0.0f )
{
// Rotate all the UV coords
vec3_t theAngles ( 0.0f , 0.0f , inRotateUVRadians ) ;
float theMatrix [ 3 ] [ 4 ] ;
AngleMatrix ( theAngles , theMatrix ) ;
float theRotatedValues [ 3 ] ;
float theStartValues [ 3 ] = { inStartU , inStartV , 0.0f } ;
VectorRotate ( theStartValues , theMatrix , theRotatedValues ) ;
inStartU = theRotatedValues [ 0 ] ;
inStartV = theRotatedValues [ 1 ] ;
float theEndValues [ 3 ] = { inEndU , inEndV , 0.0f } ;
VectorRotate ( theEndValues , theMatrix , theRotatedValues ) ;
inEndU = theRotatedValues [ 0 ] ;
inEndV = theRotatedValues [ 1 ] ;
}
// Calculate width and height of each quad
int theQuadScreenWidth = inWidth / theNumCols ;
int theQuadScreenHeight = inHeight / theNumRows ;
//Vector thePickRay;
//int theHalfWidth = ScreenWidth/2;
//int theHalfHeight = ScreenHeight/2;
//CreatePickingRay(theHalfWidth, theHalfHeight, thePickRay);
//char gDebugMessage[256];
//sprintf(gDebugMessage, "(%d, %d): %f, %f, %f", theHalfWidth, theHalfHeight, thePickRay.x, thePickRay.y, thePickRay.z);
//CenterPrint(gDebugMessage);
//float theRenderOrigin[3];
//pVector theUp;
//pVector theRight;
//pVector theNormal;
//IEngineStudio.GetViewInfo(theRenderOrigin, (float*)&theUp, (float*)&theRight, (float*)&theNormal);
//Demo_WriteVector(TYPE_VIEWANGLES, v_angles);
//Demo_WriteVector(TYPE_VIEWORIGIN, v_origin);
vec3_t theRenderOrigin ;
VectorCopy ( GetViewOrigin ( ) , theRenderOrigin ) ;
vec3_t theForward , theRight , theUp ;
AngleVectors ( v_angles , theForward , theRight , theUp ) ;
Vector theRenderOriginVector ;
theRenderOriginVector . x = theRenderOrigin [ 0 ] ;
theRenderOriginVector . y = theRenderOrigin [ 1 ] ;
theRenderOriginVector . z = theRenderOrigin [ 2 ] ;
// This is the smallest value that displays and it still clips with the view model a little
const int kDistanceToProject = 10 ;
// create picking ray for upper left of quad
Vector theUpperLeftRay ;
//CreatePickingRay(inX, inY, theUpperLeftRay);
CreatePickingRay ( 0 , 0 , theUpperLeftRay ) ;
// create picking ray for lower left of quad
Vector theLowerLeftRay ;
//CreatePickingRay(inX, inY+inHeight, theLowerLeftRay);
CreatePickingRay ( 0 , ScreenHeight ( ) , theLowerLeftRay ) ;
// create picking ray for upper right of quad
Vector theUpperRightRay ;
//CreatePickingRay(inX+inWidth, inY, theUpperRightRay);
CreatePickingRay ( ScreenWidth ( ) , 0 , theUpperRightRay ) ;
// project default distance along picking ray
Vector theUpperLeftWorldPos ;
VectorMA ( theRenderOrigin , kDistanceToProject , theUpperLeftRay , theUpperLeftWorldPos ) ;
Vector theUpperRightWorldPos ;
VectorMA ( theRenderOrigin , kDistanceToProject , theUpperRightRay , theUpperRightWorldPos ) ;
Vector theLowerLeftWorldPos ;
VectorMA ( theRenderOrigin , kDistanceToProject , theLowerLeftRay , theLowerLeftWorldPos ) ;
// Create formula for plane
float thePlaneD ;
Vector thePlaneNormal ;
CalculatePlaneInfo ( theUpperLeftWorldPos , theUpperRightWorldPos , theLowerLeftWorldPos , thePlaneD , thePlaneNormal ) ;
// loop through screen height
int theCurrentFrame = 0 ;
// Allow drawing of just one frame
if ( inForceSpriteFrame ! = - 1 )
{
theCurrentFrame = inForceSpriteFrame ;
}
for ( int i = 0 ; i < theNumRows ; i + + )
{
// loop through screen width
for ( int j = 0 ; j < theNumCols ; j + + )
{
// draw quad
gEngfuncs . pTriAPI - > RenderMode ( inMode ) ;
gEngfuncs . pTriAPI - > CullFace ( TRI_NONE ) ;
//gEngfuncs.pTriAPI->Brightness(1);
if ( gEngfuncs . pTriAPI - > SpriteTexture ( ( struct model_s * ) gEngfuncs . GetSpritePointer ( inSpriteHandle ) , theCurrentFrame ) )
{
gEngfuncs . pTriAPI - > Begin ( TRI_TRIANGLE_STRIP ) ;
//gEngfuncs.pTriAPI->Color4f(1.0f, 1.0f, 1.0f, 1.0f);
bool theIsFirstRow = ( i = = 0 ) ;
bool theIsFirstCol = ( j = = 0 ) ;
bool theIsLastRow = ( i = = ( theNumRows - 1 ) ) ;
bool theIsLastCol = ( j = = ( theNumCols - 1 ) ) ;
float theStartU = inStartU ;
float theStartV = inStartV ;
float theEndU = inEndU ;
float theEndV = inEndV ;
if ( inUVWrapsOverFrames )
{
if ( ( theNumCols > 1 ) & & ! theIsFirstCol )
{
theStartU = 0.0f ;
}
if ( ( theNumRows > 1 ) & & ! theIsFirstRow )
{
theStartV = 0.0f ;
}
if ( ( theNumCols > 1 ) & & ! theIsLastCol )
{
theEndU = 1.0f ;
}
if ( ( theNumRows > 1 ) & & ! theIsLastRow )
{
theEndV = 1.0f ;
}
}
// Optionally warp XY coords using current time
int theWarpXStartAmount = 0 ;
int theWarpYStartAmount = 0 ;
int theWarpXEndAmount = 0 ;
int theWarpYEndAmount = 0 ;
if ( gWarpHUDSprites )
{
float theCurrentTime = gHUD . GetTimeOfLastUpdate ( ) ;
float theNormXAmount = theCurrentTime * gWarpXSpeed - ( int ) ( theCurrentTime * gWarpXSpeed ) ; // Get fractional part of second
float theNormYAmount = theCurrentTime * gWarpYSpeed - ( int ) ( theCurrentTime * gWarpYSpeed ) ;
float theSinusoidalNormXAmount = cos ( theNormXAmount * 2.0f * M_PI ) ;
float theSinusoidalNormYAmount = sin ( theNormYAmount * 2.0f * M_PI ) ;
float theXAmount = theSinusoidalNormXAmount * gWarpXAmount ; // - gWarpUAmount/2.0f;
float theYAmount = theSinusoidalNormYAmount * gWarpYAmount ; // - gWarpVAmount/2.0f;
if ( ! theIsFirstCol )
{
theWarpXStartAmount = theXAmount * ScreenWidth ( ) ;
}
if ( ! theIsLastCol )
{
theWarpXEndAmount = theXAmount * ScreenWidth ( ) ;
}
if ( ! theIsFirstRow )
{
theWarpYStartAmount = theYAmount * ScreenHeight ( ) ;
}
if ( ! theIsLastRow )
{
theWarpYEndAmount = theYAmount * ScreenHeight ( ) ;
}
}
// Compensate for gamma
float theGammaSlope = gHUD . GetGammaSlope ( ) ;
float theColorComponent = 1.0f / theGammaSlope ;
gEngfuncs . pTriAPI - > Color4f ( theColorComponent , theColorComponent , theColorComponent , 1.0f ) ;
Vector thePoint ;
//float theMinXPercentage = (float)j/theNumCols;
//float theMaxXPercentage = (float)(j+1)/theNumCols;
//float theMinYPercentage = (float)i/theNumRows;
//float theMaxYPercentage = (float)(i+1)/theNumRows;
int theMinXPos = inX + ( ( float ) j / theNumCols ) * inWidth + theWarpXStartAmount ;
int theMinYPos = inY + ( ( float ) i / theNumRows ) * inHeight + theWarpYStartAmount ;
int theMaxXPos = inX + ( ( float ) ( j + 1 ) / theNumCols ) * inWidth + theWarpXEndAmount ;
int theMaxYPos = inY + ( ( float ) ( i + 1 ) / theNumRows ) * inHeight + theWarpYEndAmount ;
// Lower left
Vector thePointOne ;
//BuildLerpedPoint(theMinXPercentage, theMaxYPercentage, theUpperLeftWorldPos, theUpperRightWorldPos, theLowerLeftWorldPos, thePointOne);
CalculatePointOnPlane ( theMinXPos , theMaxYPos , theRenderOriginVector , thePlaneNormal , thePlaneD , thePointOne ) ;
float theU = theStartU ;
float theV = theEndV ;
gEngfuncs . pTriAPI - > TexCoord2f ( theU , theV ) ; // 0,1
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePointOne ) ;
// Upper left
Vector thePointTwo ;
//BuildLerpedPoint(theMinXPercentage, theMinYPercentage, theUpperLeftWorldPos, theUpperRightWorldPos, theLowerLeftWorldPos, thePointTwo);
CalculatePointOnPlane ( theMinXPos , theMinYPos , theRenderOriginVector , thePlaneNormal , thePlaneD , thePointTwo ) ;
theU = theStartU ;
theV = theStartV ;
//gEngfuncs.pTriAPI->TexCoord2f(inStartU, inStartV); // 0,0
gEngfuncs . pTriAPI - > TexCoord2f ( theU , theV ) ; // 0,1
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePointTwo ) ;
// Lower right
Vector thePointFour ;
//BuildLerpedPoint(theMaxXPercentage, theMaxYPercentage, theUpperLeftWorldPos, theUpperRightWorldPos, theLowerLeftWorldPos, thePointFour);
CalculatePointOnPlane ( theMaxXPos , theMaxYPos , theRenderOriginVector , thePlaneNormal , thePlaneD , thePointFour ) ;
theU = theEndU ;
theV = theEndV ;
//gEngfuncs.pTriAPI->TexCoord2f(inEndU, inEndV);// 1,1
gEngfuncs . pTriAPI - > TexCoord2f ( theU , theV ) ; // 0,1
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePointFour ) ;
// Upper right
Vector thePointThree ;
//BuildLerpedPoint(theMaxXPercentage, theMinYPercentage, theUpperLeftWorldPos, theUpperRightWorldPos, theLowerLeftWorldPos, thePointThree);
CalculatePointOnPlane ( theMaxXPos , theMinYPos , theRenderOriginVector , thePlaneNormal , thePlaneD , thePointThree ) ;
theU = theEndU ;
theV = theStartV ;
//gEngfuncs.pTriAPI->TexCoord2f(inEndU, inStartV); // 1,0
gEngfuncs . pTriAPI - > TexCoord2f ( theU , theV ) ; // 0,1
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePointThree ) ;
gEngfuncs . pTriAPI - > End ( ) ;
}
// Increment frame
theCurrentFrame + + ;
// Allow drawing of just one frame
if ( inForceSpriteFrame ! = - 1 )
{
theCurrentFrame = inForceSpriteFrame ;
}
// increment current x and y
//theCurrentScreenX += theQuadScreenWidth;
}
//theCurrentScreenX = 0;
//theCurrentScreenY += theQuadScreenHeight;
}
}
void DrawVariableScaledHUDSprite ( float inFactor , int inSpriteHandle , int inMode , int inX , int inY , int inWidth , int inHeight )
{
// Draw as two scaled sprites, one for the level and one for the "empty" level
// Assumes that sprite has two frames, with the empty level being frame 0 and the full frame being frame 1
int theWidth = inWidth ;
float theStartU = 0.0f ;
float theEndU = 1.0f ;
int theHeight = inFactor * inHeight ;
float theStartV = 1.0f - inFactor ;
float theEndV = 1.0f ;
int theX = inX ;
int theY = inY + inHeight - theHeight ;
DrawScaledHUDSprite ( inSpriteHandle , inMode , 1 , theX , theY , theWidth , theHeight , 1 , theStartU , theStartV , theEndU , theEndV ) ;
// Draw background
theHeight = ( 1.0f - inFactor ) * inHeight ;
theY = inY ;
theStartV = 0.0f ;
theEndV = 1.0f - inFactor ;
DrawScaledHUDSprite ( inSpriteHandle , inMode , 1 , theX , theY , theWidth , theHeight , 0 , theStartU , theStartV , theEndU , theEndV ) ;
}
void DrawSpriteOnGroundAtPoint ( vec3_t inOrigin , int inRadius , HSPRITE inSprite , int inRenderMode = kRenderNormal , int inFrame = 0 , float inAlpha = 1.0f )
{
if ( gEngfuncs . pTriAPI - > SpriteTexture ( ( struct model_s * ) gEngfuncs . GetSpritePointer ( inSprite ) , inFrame ) )
{
gEngfuncs . pTriAPI - > CullFace ( TRI_NONE ) ;
gEngfuncs . pTriAPI - > RenderMode ( inRenderMode ) ;
//gEngfuncs.pTriAPI->RenderMode( kRenderTransTexture );
//gEngfuncs.pTriAPI->Color4f(inR, inG, inB, inA);
gEngfuncs . pTriAPI - > Begin ( TRI_TRIANGLE_STRIP ) ;
// Draw one quad
vec3_t thePoint = inOrigin ;
float theGammaSlope = gHUD . GetGammaSlope ( ) ;
ASSERT ( theGammaSlope > 0.0f ) ;
float theColorComponent = 1.0f / theGammaSlope ;
gEngfuncs . pTriAPI - > Color4f ( theColorComponent , theColorComponent , theColorComponent , inAlpha ) ;
gEngfuncs . pTriAPI - > Brightness ( 1.6f ) ;
thePoint [ 0 ] = inOrigin [ 0 ] - inRadius ;
thePoint [ 1 ] = inOrigin [ 1 ] - inRadius ;
gEngfuncs . pTriAPI - > TexCoord2f ( 0 , 0 ) ;
gEngfuncs . pTriAPI - > Vertex3f ( thePoint [ 0 ] , thePoint [ 1 ] , thePoint [ 2 ] ) ;
thePoint [ 0 ] = inOrigin [ 0 ] - inRadius ;
thePoint [ 1 ] = inOrigin [ 1 ] + inRadius ;
gEngfuncs . pTriAPI - > TexCoord2f ( 0 , 1 ) ;
gEngfuncs . pTriAPI - > Vertex3f ( thePoint [ 0 ] , thePoint [ 1 ] , thePoint [ 2 ] ) ;
thePoint [ 0 ] = inOrigin [ 0 ] + inRadius ;
thePoint [ 1 ] = inOrigin [ 1 ] - inRadius ;
gEngfuncs . pTriAPI - > TexCoord2f ( 1 , 0 ) ;
gEngfuncs . pTriAPI - > Vertex3f ( thePoint [ 0 ] , thePoint [ 1 ] , thePoint [ 2 ] ) ;
thePoint [ 0 ] = inOrigin [ 0 ] + inRadius ;
thePoint [ 1 ] = inOrigin [ 1 ] + inRadius ;
gEngfuncs . pTriAPI - > TexCoord2f ( 1 , 1 ) ;
gEngfuncs . pTriAPI - > Vertex3f ( thePoint [ 0 ] , thePoint [ 1 ] , thePoint [ 2 ] ) ;
gEngfuncs . pTriAPI - > End ( ) ;
gEngfuncs . pTriAPI - > RenderMode ( kRenderNormal ) ;
}
}
void AvHHud : : DrawPlayerNames ( )
{
bool inReadyRoom = false ; //(this->GetPlayMode() == PLAYMODE_READYROOM);
bool inTopDownMode = this - > GetInTopDownMode ( ) ;
if ( inTopDownMode | | inReadyRoom /*&& !gEngfuncs.pDemoAPI->IsPlayingback()*/ )
{
cl_entity_s * theLocalPlayer = gEngfuncs . GetLocalPlayer ( ) ;
if ( theLocalPlayer )
{
int theLocalPlayerIndex = theLocalPlayer - > index ;
// Loop through all players
for ( int i = 1 ; i < = kMaxPlayers ; i + + )
{
if ( ( i ! = theLocalPlayerIndex ) & & AvHCUGetIsEntityInPVSAndVisible ( i ) )
{
cl_entity_s * theCurrentPlayer = gEngfuncs . GetEntityByIndex ( i ) ;
bool theDrawEntity = ( inReadyRoom | | ( theCurrentPlayer & & theCurrentPlayer - > player & & ( AvHTeamNumber ( theCurrentPlayer - > curstate . team ) = = this - > GetHUDTeam ( ) ) & & ( i ! = theLocalPlayerIndex ) ) ) ;
if ( theDrawEntity )
{
string theEntityName ;
bool theIsEnemy ;
if ( this - > GetEntityInfoString ( i , theEntityName , theIsEnemy ) )
{
vec3_t theEntityOrigin ;
VectorCopy ( theCurrentPlayer - > curstate . origin , theEntityOrigin ) ;
theEntityOrigin . z + = AvHCUGetIconHeightForPlayer ( ( AvHUser3 ) theCurrentPlayer - > curstate . iuser3 ) ;
// If they are on screen
Vector theScreenPos ;
if ( AvHCUWorldToScreen ( theEntityOrigin , ( float * ) & theScreenPos ) )
{
// Set color
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , true , false ) ;
// If selected, draw in different color
if ( inTopDownMode )
{
bool theIsSelected = ( std : : find ( this - > mSelected . begin ( ) , this - > mSelected . end ( ) , i ) ! = this - > mSelected . end ( ) ) ;
if ( theIsSelected )
{
// Selected color
UnpackRGB ( theR , theG , theB , RGB_MARINE_SELECTED ) ;
if ( GetHasUpgrade ( theCurrentPlayer - > curstate . iuser4 , MASK_PARASITED ) )
{
string thePrePendString ;
LocalizeString ( kParasited , thePrePendString ) ;
theEntityName = string ( theEntityName + " ( " + thePrePendString + " ) " ) ;
// Set color to parasited color
UnpackRGB ( theR , theG , theB , RGB_MARINE_PARASITED ) ;
}
}
}
// Set text color draw in different color
this - > mTopDownPlayerNameMessage . SetRGB ( theR , theG , theB ) ;
this - > mTopDownPlayerNameMessage . SetIgnoreFadeForLifetime ( true ) ;
// Set the message info and draw it
this - > mTopDownPlayerNameMessage . SetText ( theEntityName ) ;
// Set position
Vector theNormPos ;
float theNormX = theScreenPos . x / ScreenWidth ( ) ;
int theBoxHeight = this - > mTopDownPlayerNameMessage . GetScreenHeight ( ) ;
float theNormY = ( theScreenPos . y - theBoxHeight ) / ScreenHeight ( ) ;
if ( ( inTopDownMode & & ! this - > GetIsRegionBlockedByUI ( theNormX , theNormY ) ) | | inReadyRoom )
{
this - > mTopDownPlayerNameMessage . SetNormalizedScreenX ( theNormX ) ;
this - > mTopDownPlayerNameMessage . SetNormalizedScreenY ( theNormY ) ;
this - > mTopDownPlayerNameMessage . SetCentered ( true ) ;
this - > mTopDownPlayerNameMessage . SetNormalizedMaxWidth ( kReticleMaxWidth ) ;
this - > mTopDownPlayerNameMessage . Draw ( ) ;
}
}
}
}
}
}
}
}
}
//bool AvHHud::ChopStringOfMaxScreenWidth(int inMaxScreenWidth, string& ioBaseString, string& outChoppedString)
//{
// // Loop backwards through the string, until we get a string that fits in this screen width
// int theCurrentLength = ioBaseString.length();
// int theMaxLength = ioBaseString.length();
// bool theSuccess = false;
//
// while(!theSuccess)
// {
// string theCurrentString = ioBaseString.substr(0, theCurrentLength);
// int theCurrentStringScreenWidth = this->GetHudStringWidth(theCurrentString.c_str());
// if(theCurrentStringScreenWidth <= inMaxScreenWidth)
// {
// // Look for a word to break the line
// while((theCurrentLength > 0) && !theSuccess)
// {
// char theCurrentChar = ioBaseString[theCurrentLength-1];
// if((theCurrentChar == ' ') || (theCurrentLength == theMaxLength))
// {
// outChoppedString = ioBaseString.substr(0, theCurrentLength);
// ioBaseString = ioBaseString.substr(theCurrentLength, ioBaseString.length() - theCurrentLength);
// theSuccess = true;
// break;
// }
// else
// {
// theCurrentLength--;
// }
// }
// }
// else
// {
// theCurrentLength--;
// }
// }
//
// return theSuccess;
//}
void AvHHud : : DrawReticleInfo ( )
{
this - > mReticleMessage . Draw ( ) ;
// if(this->mReticleInfoText != "")
// {
// const float kMaxWidth = .3f;
// int kMaxScreenWidth = kMaxWidth*ScreenWidth;
//
// StringList theStringList;
// string theHelpString = this->mReticleInfoText;
//
// do
// {
// string theNewString;
// if(ChopStringOfMaxScreenWidth(kMaxScreenWidth, theHelpString, theNewString))
// {
// theStringList.push_back(theNewString);
// }
// else
// {
// theHelpString = "";
// }
// }
// while(theHelpString != "");
//
// // For each line, if the line contains any special markers, move them to their own lines
//
// // Compute max width of all the strings, add some extra for a frame
// int theBoxWidth = 0;
// StringList::iterator theStringListIter;
// for(theStringListIter = theStringList.begin(); theStringListIter != theStringList.end(); theStringListIter++)
// {
// int theCurrentScreenWidth = this->GetHudStringWidth(theStringListIter->c_str());
// theBoxWidth = max(theBoxWidth, theCurrentScreenWidth);
// }
// int theLineHSpacing = .01f*ScreenWidth;
// theBoxWidth += 2*theLineHSpacing;
//
// // Compute max height needed to contain all the strings, add some extra for a frame
// int theLineVSpacing = .01f*ScreenHeight();
// int theLineHeight = this->GetHudStringHeight();
// int theBoxHeight = 2*theLineVSpacing + (theStringList.size()*theLineHeight);
//
// int theFillStartX = this->mReticleInfoScreenX;
// int theFillStartY = this->mReticleInfoScreenY;
//
// theFillStartX -= theBoxWidth/2;
// theFillStartY -= theBoxHeight/2;
//
// // Draw nice border and shaded background
// const float kReticleInfoMaxAlpha = 25;
// float theNormalizedAlpha = this->mReticleInfoColorA/255;
// int theAlphaComponent = theNormalizedAlpha*kReticleInfoMaxAlpha;
//
// FillRGBA(theFillStartX, theFillStartY, theBoxWidth, theBoxHeight, this->mReticleInfoColorR, this->mReticleInfoColorG, this->mReticleInfoColorB, theAlphaComponent);
// vguiSimpleBox(theFillStartX, theFillStartY, theFillStartX + theBoxWidth, theFillStartY + theBoxHeight, this->mReticleInfoColorR, this->mReticleInfoColorG, this->mReticleInfoColorB, theAlphaComponent);
//
// // Now draw each line, non-centered, left-aligned
// int theLineNumber = 0;
// for(theStringListIter = theStringList.begin(); theStringListIter != theStringList.end(); theStringListIter++)
// {
// int theR = this->mReticleInfoColorR;
// int theG = this->mReticleInfoColorG;
// int theB = this->mReticleInfoColorB;
//
// // If the line starts with a marker, draw it in a special color
// //string theDamageMarker(kDamageMarker);
// //if(theStringListIter->substr(0, theDamageMarker.length()) == theDamageMarker)
// //{
// // // Draw string in yellow
// // theR = theG = 255;
// // theB = 25;
// //}
//
// int theBaseY = theFillStartY + theLineVSpacing + theLineNumber*theLineHeight;
//
// // Draw message (DrawHudStringCentered only centers in x)
// this->DrawHudString(theFillStartX + theLineHSpacing, theBaseY /*- theLineHeight/2*/, ScreenWidth, theStringListIter->c_str(), theR*theNormalizedAlpha, theG*theNormalizedAlpha, theB*theNormalizedAlpha);
//
// theLineNumber++;
// }
// }
}
void AvHHud : : DrawToolTips ( )
{
if ( ! gEngfuncs . pDemoAPI - > IsPlayingback ( ) )
{
this - > mHelpMessage . Draw ( ) ;
// Draw each one
for ( AvHTooltipListType : : iterator theIter = this - > mTooltips . begin ( ) ; theIter ! = this - > mTooltips . end ( ) ; theIter + + )
{
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , true , false ) ;
theIter - > SetRGB ( theR , theG , theB ) ;
theIter - > Draw ( ) ;
}
}
}
void AvHHud : : DrawWorldSprite ( int inSpriteHandle , int inRenderMode , vec3_t inWorldPosition , int inFrame , float inWorldSize )
{
vec3_t theUpperLeft ;
vec3_t theLowerRight ;
vec3_t theForward , theRight , theUp ;
AngleVectors ( v_angles , theForward , theRight , theUp ) ;
vec3_t theToUpperLeft ;
VectorAdd ( - theRight , theUp , theToUpperLeft ) ;
VectorNormalize ( theToUpperLeft ) ;
VectorMA ( inWorldPosition , inWorldSize , theToUpperLeft , theUpperLeft ) ;
vec3_t theToLowerRight ;
VectorAdd ( theRight , - theUp , theToLowerRight ) ;
VectorNormalize ( theToLowerRight ) ;
VectorMA ( inWorldPosition , inWorldSize , theToLowerRight , theLowerRight ) ;
vec3_t theScreenUpperLeft ;
vec3_t theScreenLowerRight ;
// World to screen returns true if the world pos is behind the viewer
if ( ! gEngfuncs . pTriAPI - > WorldToScreen ( ( float * ) theUpperLeft , ( float * ) theScreenUpperLeft ) )
{
if ( ! gEngfuncs . pTriAPI - > WorldToScreen ( ( float * ) theLowerRight , ( float * ) theScreenLowerRight ) )
{
// If the sprite is behind you, push it to the bottom or top of the screen
// cl_entity_t* theLocalPlayer = gEngfuncs.GetLocalPlayer();
// ASSERT(theLocalPlayer);
//
// vec3_t theDirectionToOrder;
// VectorSubtract(inWorldPosition, theLocalPlayer->origin, theDirectionToOrder);
// float theDotProduct = DotProduct(theDirectionToOrder, theLocalPlayer->angles);
// if(theDotProduct < 0)
// {
// if(theWorldPos.z < theLocalPlayer->origin.z)
// {
// theY = theScreenHeight - theSpriteHeight - theScreenBorder;
// }
// else
// {
// theY = theScreenBorder;
// }
// vec3_t theCrossProduct;
// theCrossProduct = CrossProduct(theLocalPlayer->angles, theDirectionToOrder);
//
// // It's to our right
// if(theCrossProduct.z > 0)
// {
// theX = theScreenWidth - theSpriteWidth - theScreenBorder;
// }
// else
// {
// theX = theScreenBorder;
// }
// }
// float theDistanceToLocation = (float)VectorDistance(inWorldPosition, theLocalPlayer->origin);
// const theMaxDistance = 1500;
// float theEffectiveDistance = min(theDistanceToLocation, theMaxDistance);
// const int theMinColorComponent = 100;
// int theColorComponent = max(theMinColorComponent, 255 - ((theEffectiveDistance/theMaxDistance)*255));
//SPR_Set(inSpriteHandle, theColorComponent, theColorComponent, theColorComponent);
////SPR_DrawHoles((int)0, theX, theY, NULL);
//if(inRenderMode == kRenderNormal)
//{
// SPR_Draw(inFrame, theX, theY, NULL);
//}
//else if(inRenderMode == kRenderTransAdd)
//{
// SPR_DrawAdditive(inFrame, theX, theY, NULL);
//}
float theScreenX = XPROJECT ( theScreenUpperLeft . x ) ;
float theScreenY = YPROJECT ( theScreenUpperLeft . y ) ;
float theWidth = XPROJECT ( theScreenLowerRight . x ) - theScreenX ;
float theHeight = YPROJECT ( theScreenLowerRight . y ) - theScreenY ;
//DrawScaledHUDSprite(inSpriteHandle, inRenderMode, 1, theScreenX, theScreenY, theWidth, theHeight, inFrame);
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteSetRenderMode ( inRenderMode ) ;
AvHSpriteDraw ( inSpriteHandle , inFrame , theScreenX , theScreenY , theScreenX + theWidth , theScreenY + theHeight , 0 , 0 , 1 , 1 ) ;
}
}
}
void AvHHud : : DrawOrderIcon ( const AvHOrder & inOrder )
{
if ( this - > mOrderSprite )
{
int theNumFrames = SPR_Frames ( this - > mOrderSprite ) ;
int theCurrentFrame = this - > GetFrameForOrderType ( inOrder . GetOrderType ( ) ) ;
if ( ( theCurrentFrame > = 0 ) & & ( theCurrentFrame < theNumFrames ) )
{
vec3_t theWorldPos ;
inOrder . GetLocation ( theWorldPos ) ;
if ( inOrder . GetOrderType ( ) = = ORDERTYPET_ATTACK ) {
theWorldPos [ 2 ] + = kAttackOrderZOffset ;
}
// Draw icon above pos, text below
2005-04-01 03:04:57 +00:00
theWorldPos . z + = BALANCE_VAR ( kOrderIconDrawSize ) ;
2005-03-09 01:31:56 +00:00
2005-04-01 03:04:57 +00:00
this - > DrawWorldSprite ( this - > mOrderSprite , kRenderTransAdd , theWorldPos , theCurrentFrame , BALANCE_VAR ( kOrderIconDrawSize ) ) ;
2005-03-09 01:31:56 +00:00
// If the order is our own order, draw the order indicator around it
if ( ( this - > GetHUDPlayMode ( ) = = PLAYMODE_PLAYING ) & & this - > GetIsMarine ( ) & & ! this - > GetInTopDownMode ( ) )
{
2005-04-01 03:04:57 +00:00
this - > DrawWorldSprite ( this - > mMarineOrderIndicator , kRenderTransAdd , theWorldPos , 0 , BALANCE_VAR ( kOrderIconDrawSize ) ) ;
2005-03-09 01:31:56 +00:00
//DrawScaledHUDSprite(theSpriteHandle, kRenderNormal, 1, thePosX, thePosY, theWidth, theHeight, theFrame, theStartU, theStartV, theEndU, theEndV);
}
}
}
}
void AvHHud : : DrawOrderText ( const AvHOrder & inOrder )
{
int theIndex = ( int ) ( inOrder . GetOrderType ( ) ) ;
// Now draw text describing the waypoint
string theTitle ;
sprintf ( theTitle , " Order%d " , theIndex ) ;
string theLocalizedTitle ( " " ) ;
LocalizeString ( theTitle . c_str ( ) , theLocalizedTitle ) ;
if ( ( theIndex = = ORDERTYPET_BUILD ) | | ( theIndex = = ORDERTYPET_GUARD ) | | ( theIndex = = ORDERTYPET_GET ) )
{
AvHUser3 theUser3 = inOrder . GetTargetUser3Type ( ) ;
string theUser3Name ;
if ( this - > GetTranslatedUser3Name ( theUser3 , theUser3Name ) )
{
// "Get %s" -> "Get heavy machine gun"
// "Guard %s -> "Guard soldier"
// "Build %s" -> "Build sentry turret"
string theTitleWithTarget ;
sprintf ( theTitleWithTarget , theLocalizedTitle . c_str ( ) , theUser3Name . c_str ( ) ) ;
theLocalizedTitle = theTitleWithTarget ;
}
}
vec3_t theOrderLocation ;
inOrder . GetLocation ( theOrderLocation ) ;
// Because the commander may not have information about the players heading to this waypoint (outside of his PVS), we
// can't draw a range for the commander
string theRangeDisplayString ;
if ( ! this - > GetInTopDownMode ( ) )
{
float theDistanceToWaypoint = VectorDistance ( gPredictedPlayerOrigin , theOrderLocation ) ;
int theVisibleDistance = max ( 1 , ( int ) theDistanceToWaypoint / 100 ) ;
string theVisibleUnits ;
if ( LocalizeString ( " Range " , theVisibleUnits ) )
{
sprintf ( theRangeDisplayString , theVisibleUnits . c_str ( ) , theVisibleDistance ) ;
}
}
string theLocationOfOrder ;
theLocationOfOrder = this - > GetNameOfLocation ( theOrderLocation ) ;
// It's OK if this fails, as only official maps will have these translated
string theTranslatedLocation = theLocationOfOrder ;
LocalizeString ( theLocationOfOrder . c_str ( ) , theTranslatedLocation ) ;
Vector theScreenPos ;
if ( AvHCUWorldToScreen ( ( float * ) theOrderLocation , ( float * ) & theScreenPos ) )
{
float theNormX = theScreenPos . x / ScreenWidth ( ) ;
float theNormY = theScreenPos . y / ScreenHeight ( ) ;
if ( ! this - > GetIsRegionBlockedByUI ( theNormX , theNormY ) )
{
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , false , false ) ;
string theFirstLine = theLocalizedTitle ;
if ( theRangeDisplayString ! = " " )
{
theFirstLine + = string ( " : " ) + theRangeDisplayString ;
}
// Draw order (icon above world position, text below it)
int theBaseX = theScreenPos . x ;
int theBaseY = theScreenPos . y ;
int theStringHeight = this - > GetHudStringHeight ( ) ;
this - > DrawHudStringCentered ( theBaseX , theBaseY + theStringHeight , ScreenWidth ( ) , theFirstLine . c_str ( ) , theR , theG , theB ) ;
// Draw location below it
this - > DrawHudStringCentered ( theBaseX , theBaseY + 2 * theStringHeight , ScreenWidth ( ) , theTranslatedLocation . c_str ( ) , theR , theG , theB ) ;
}
}
}
void AvHHud : : DrawOrders ( )
{
if ( 1 /*!this->mIsRenderingSelectionView*/ )
{
// Draw them blinking for soldiers, but always for commanders
float theFractionalLastUpdate = this - > mTimeOfLastUpdate - ( int ) this - > mTimeOfLastUpdate ;
if ( ( theFractionalLastUpdate > .25f ) | | ( this - > GetHUDUser3 ( ) = = AVH_USER3_COMMANDER_PLAYER ) )
{
OrderListType theOrders = this - > GetOrderList ( ) ;
EntityListType theDrawPlayerList = this - > GetDrawPlayerOrders ( ) ;
// Run through the order list type
for ( OrderListType : : iterator theIter = theOrders . begin ( ) ; theIter ! = theOrders . end ( ) ; theIter + + )
{
// For each one, if the order is for a player in the theDrawPlayerList, draw it
vec3_t theOrderLocation ;
theIter - > GetLocation ( theOrderLocation ) ;
if ( theIter - > GetOrderTargetType ( ) = = ORDERTARGETTYPE_TARGET )
{
int theTargetIndex = theIter - > GetTargetIndex ( ) ;
cl_entity_s * theEntity = gEngfuncs . GetEntityByIndex ( theTargetIndex ) ;
if ( theEntity )
{
//voogru: dont follow if they are cloaked, leave the waypoint active so they have a clue where they may be at, the wp should snap back to the baddy
//once they are spotted again.
if ( theEntity - > curstate . rendermode ! = kRenderTransTexture & & theEntity - > curstate . renderamt > 128 )
VectorCopy ( theEntity - > origin , theOrderLocation ) ;
}
}
// Draw the order if the order is for any plays that are in our draw player list
bool theDrawWaypoint = false ;
EntityInfo theReceiverPlayer = theIter - > GetReceiver ( ) ;
EntityListType : : iterator theSearchIter = std : : find ( theDrawPlayerList . begin ( ) , theDrawPlayerList . end ( ) , theReceiverPlayer ) ;
if ( theSearchIter ! = theDrawPlayerList . end ( ) & & * theSearchIter = = theReceiverPlayer )
{
//gEngfuncs.pEfxAPI->R_ParticleLine((float*)theEntity->origin, (float*)theOrderLocation, 0, 255, 0, .05f);
theDrawWaypoint = true ;
}
if ( theDrawWaypoint )
{
this - > DrawOrderIcon ( * theIter ) ;
this - > DrawOrderText ( * theIter ) ;
}
}
}
}
}
int AvHHud : : GetHelpIconFrameFromUser3 ( AvHUser3 inUser3 )
{
int theFrame = - 1 ;
switch ( inUser3 )
{
case AVH_USER3_WELD :
theFrame = 0 ;
break ;
case AVH_USER3_MARINEITEM :
theFrame = 1 ;
break ;
case AVH_USER3_HIVE :
theFrame = 2 ;
break ;
//case AVH_USER3_USEABLE:
// theFrame = 3;
// break;
case AVH_USER3_COMMANDER_STATION :
theFrame = 4 ;
break ;
//case AVH_USER3_BREAKABLE:
// theFrame = 5;
// break;
}
return theFrame ;
}
HSPRITE AvHHud : : GetHelpSprite ( ) const
{
return this - > mHelpSprite ;
}
void AvHHud : : DrawHelpIcons ( )
{
// Lookup table
// Only draw if enabled
//if(gEngfuncs.pfnGetCvarFloat(kvAutoHelp))
//{
// Iterate through help icons, drawing each one if we have an sprite for it
for ( HelpIconListType : : iterator theIter = this - > mHelpIcons . begin ( ) ; theIter ! = this - > mHelpIcons . end ( ) ; theIter + + )
{
int theUser3 = theIter - > second ;
int theFrame = GetHelpIconFrameFromUser3 ( AvHUser3 ( theUser3 ) ) ;
// Lookup sprite to see if it's loaded
// if(this->mHelpSprites[theUser3] == 0)
// {
// string theIconName = string(kHelpIconPrefix) + MakeStringFromInt(theUser3) + ".spr";
// this->mHelpSprites[theUser3] = Safe_SPR_Load(theIconName.c_str());
// }
//
// int theSpriteHandle = this->mHelpSprites[theUser3];
// if(theSpriteHandle > 0)
// {
// // Draw icon at entity center
// this->DrawWorldSprite(theSpriteHandle, kRenderTransAdd, theIter->first, 0);
// }
if ( ( theFrame > = 0 ) & & this - > mHelpSprite )
{
this - > DrawWorldSprite ( this - > mHelpSprite , kRenderTransAdd , theIter - > first , theFrame , kHelpIconDrawSize ) ;
}
}
//}
}
// inDrawMode determines if we're drawing text or sprites
void AvHHud : : DrawHUDStructureNotification ( )
{
const float kHUDStructureNotificationStartX = .02f ;
const float kHUDStructureNotificationStartY = .11f ;
const float kHUDStructureNotificationIconWidth = .03f ;
const float kHUDStructureNotificationIconHeight = kHUDStructureNotificationIconWidth * 1.333f ;
const float kHUDStructureNotificationIconHorizontalSpacing = .01f ;
const float kHUDStructureNotificationIconVerticalSpacing = kHUDStructureNotificationIconHorizontalSpacing * 1.333f ;
const float kHUDStructureNotificationMaxTextWidth = .2f ;
// Draw them all in order
if ( this - > GetIsAlive ( ) & & CVAR_GET_FLOAT ( kvBuildMessages ) )
{
// Get starting coords
float theCurrentX = kHUDStructureNotificationStartX ;
float theCurrentY = kHUDStructureNotificationStartY ;
for ( StructureHUDNotificationListType : : iterator theIter = this - > mStructureNotificationList . begin ( ) ; theIter ! = this - > mStructureNotificationList . end ( ) ; theIter + + )
{
// Draw icon
AvHMessageID theIconTech = theIter - > mStructureID ;
int theFrame = 0 ;
this - > DrawTechTreeSprite ( theIconTech , theCurrentX * ScreenWidth ( ) , theCurrentY * ScreenHeight ( ) , kHUDStructureNotificationIconWidth * ScreenWidth ( ) , kHUDStructureNotificationIconHeight * ScreenHeight ( ) , theFrame ) ;
string theLocationName = this - > GetNameOfLocation ( theIter - > mLocation ) ;
if ( theLocationName ! = " " )
{
int theStartX = ( theCurrentX + kHUDStructureNotificationIconWidth + kHUDStructureNotificationIconHorizontalSpacing ) * ScreenWidth ( ) ;
this - > DrawTranslatedString ( theStartX , theCurrentY * ScreenHeight ( ) , theLocationName . c_str ( ) , false , true ) ;
}
// Increment coords
theCurrentY + = ( kHUDStructureNotificationIconHeight + kHUDStructureNotificationIconVerticalSpacing ) ;
}
}
}
void AvHHud : : DrawInfoLocationText ( )
{
string theTimeLeftText ;
// Get drawing color and position
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , false , false ) ;
// Get position of health and draw to the right of it (must be left-justified)
int theX = 0 ;
int theY = 0 ;
if ( this - > GetInTopDownMode ( ) )
{
const float kLeftInset = .4f ;
theX = mViewport [ 0 ] + kLeftInset * ScreenWidth ( ) ;
theY = mViewport [ 1 ] + mViewport [ 3 ] - ( 1 - .78f ) * ScreenHeight ( ) ;
}
// Draw info location text the same for aliens and marines
else if ( this - > GetHUDUser3 ( ) ! = AVH_USER3_ALIEN_EMBRYO )
{
const float kLeftInset = .08f ;
theX = mViewport [ 0 ] + kLeftInset * ScreenWidth ( ) ;
theY = mViewport [ 1 ] + mViewport [ 3 ] - ( 1 - .88f ) * ScreenHeight ( ) ;
}
int theLeftEdge = theX ;
// Draw location text, translation if possible
string theLocalizedLocationText ;
if ( this - > mLocationText ! = " " )
{
LocalizeString ( this - > mLocationText . c_str ( ) , theLocalizedLocationText ) ;
if ( theLocalizedLocationText [ 0 ] = = ' # ' )
{
theLocalizedLocationText = theLocalizedLocationText . substr ( 1 , theLocalizedLocationText . size ( ) ) ;
}
// Draw handicap text as well
int theHandicap = ( int ) this - > GetHUDHandicap ( ) ;
if ( theHandicap < 100 )
{
// draw "(handicap 70%)"
string theHandicapString ;
if ( LocalizeString ( kHandicap , theHandicapString ) )
{
char theFormattedHandicapString [ 256 ] ;
sprintf ( theFormattedHandicapString , " (%d%% %s) " , theHandicap , theHandicapString . c_str ( ) ) ;
theLocalizedLocationText + = string ( theFormattedHandicapString ) ;
}
}
// Draw info location
if ( theLocalizedLocationText ! = " " )
{
char theCharArray [ 512 ] ;
sprintf ( theCharArray , " %s " , theLocalizedLocationText . c_str ( ) ) ;
this - > DrawHudString ( theX , theY , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
}
// Don't draw time when playing back, it isn't right and not worth breaking backward-compatibility over.
// TODO: Draw time next time demo version changes
if ( ! gEngfuncs . pDemoAPI - > IsPlayingback ( ) & & this - > GetHUDUser3 ( ) ! = AVH_USER3_ALIEN_EMBRYO )
{
// Whether we draw first line or not, increment for second line below
theY + = this - > GetHudStringHeight ( ) ;
// Optionally draw time left below it
int theTimeLimitSeconds = ( int ) this - > GetGameTimeLimit ( ) ;
int theTimeElapsed = this - > GetGameTime ( ) ;
int theMinutesElapsed = theTimeElapsed / 60 ;
int theSecondsElapsed = theTimeElapsed % 60 ;
int theTimeLeftSeconds = theTimeLimitSeconds - theTimeElapsed ;
int theMinutesLeft = theTimeLeftSeconds / 60 ;
int theSecondsLeft = theTimeLeftSeconds % 60 ;
int theMinutesLimit = theTimeLimitSeconds / 60 ;
int theSecondsLimit = theTimeLimitSeconds % 60 ;
// If we're in tournament mode or playing Combat, draw the timelimit
bool theTournyMode = ( gHUD . GetServerVariableFloat ( kvTournamentMode ) > 0 ) ;
bool theDisplayTimeLimit = theTournyMode | | gHUD . GetIsCombatMode ( ) ;
string theGameTimeText ;
if ( LocalizeString ( kGameTime , theGameTimeText ) )
{
bool theTimeVisible = true ;
// Flash time when we're almost out of time
if ( ( theMinutesLeft < 1 ) & & this - > GetGameStarted ( ) & & theDisplayTimeLimit )
{
float theTime = gHUD . GetTimeOfLastUpdate ( ) ;
float theTimeFraction = theTime - floor ( theTime ) ;
if ( theTimeFraction < .5f )
{
theTimeVisible = false ;
}
}
// Game time - 12:43
char theGameTimeCStr [ 256 ] ;
sprintf ( theGameTimeCStr , " - %02d:%02d " , theMinutesElapsed , theSecondsElapsed ) ;
theGameTimeText + = string ( theGameTimeCStr ) ;
if ( theTimeVisible )
{
this - > DrawHudString ( theX , theY , ScreenWidth ( ) , theGameTimeText . c_str ( ) , theR , theG , theB ) ;
}
// Increment X so time limit is drawn properly
theX + = this - > GetHudStringWidth ( theGameTimeText . c_str ( ) ) ;
}
if ( theDisplayTimeLimit )
{
string theTimeLimitString ;
if ( LocalizeString ( kTimeLimit , theTimeLimitString ) )
{
// Format: Time limit - 60:00
char theTimeLimitCStr [ 256 ] ;
sprintf ( theTimeLimitCStr , " %s - %02d:%02d " , theTimeLimitString . c_str ( ) , theMinutesLimit , theSecondsLimit ) ;
string theTimeLimitText = string ( theTimeLimitCStr ) ;
this - > DrawHudString ( theX , theY , ScreenWidth ( ) , theTimeLimitText . c_str ( ) , theR , theG , theB ) ;
}
if ( gHUD . GetIsCombatMode ( ) )
{
theY + = this - > GetHudStringHeight ( ) ;
// Draw "attacking" or "defending"
AvHTeamNumber theTeamNumber = this - > GetHUDTeam ( ) ;
string theDisplayString = " " ;
if ( theTeamNumber ! = TEAM_IND )
{
if ( theTeamNumber = = this - > GetCombatAttackingTeamNumber ( ) )
{
LocalizeString ( kAttacking , theDisplayString ) ;
}
else
{
LocalizeString ( kDefending , theDisplayString ) ;
}
this - > DrawHudString ( theLeftEdge , theY , ScreenWidth ( ) , theDisplayString . c_str ( ) , theR , theG , theB ) ;
}
}
}
}
}
void AvHHud : : DrawMouseCursor ( int inBaseX , int inBaseY )
{
if ( g_iVisibleMouse & & ! ( this - > GetInTopDownMode ( ) & & gEngfuncs . pDemoAPI - > IsPlayingback ( ) ) )
{
HSPRITE theCursorSprite ;
int theCursorFrame ;
GetCursor ( theCursorSprite , theCursorFrame ) ;
if ( theCursorSprite > 0 )
{
float theGammaSlope = this - > GetGammaSlope ( ) ;
ASSERT ( theGammaSlope > 0.0f ) ;
/*
int theColorComponent = 255 / theGammaSlope ;
SPR_Set ( this - > mCursorSprite , theColorComponent , theColorComponent , theColorComponent ) ;
// Draw the logo at 20 fps
//SPR_DrawAdditive( 0, this->mMouseCursorX - inBaseX, this->mMouseCursorY - inBaseY, NULL );
const int kMouseHotSpotX = - 1 ;
const int kMouseHotSpotY = - 1 ;
SPR_DrawHoles ( this - > mCurrentCursorFrame , this - > mMouseCursorX - inBaseX - kMouseHotSpotX , this - > mMouseCursorY - inBaseY - kMouseHotSpotY , NULL ) ;
*/
// Draw the mouse cursor.
const int kMouseHotSpotX = - 1 ;
const int kMouseHotSpotY = - 1 ;
AvHSpriteBeginFrame ( ) ;
AvHSpriteEnableVGUI ( true ) ;
AvHSpriteSetVGUIOffset ( inBaseX , inBaseY ) ;
float x = this - > mMouseCursorX - kMouseHotSpotX ;
float y = this - > mMouseCursorY - kMouseHotSpotY ;
float w = SPR_Width ( theCursorSprite , theCursorFrame ) ;
float h = SPR_Height ( theCursorSprite , theCursorFrame ) ;
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
AvHSpriteDraw ( theCursorSprite , theCursorFrame , x , y , x + w , y + h , 0 , 0 , 1 , 1 ) ;
// Draw the marquee if it's visible.
if ( mSelectionBoxVisible )
{
int sprite = Safe_SPR_Load ( kWhiteSprite ) ;
int r , g , b ;
GetPrimaryHudColor ( r , g , b , true , false ) ;
AvHSpriteSetRenderMode ( kRenderTransAdd ) ;
AvHSpriteSetColor ( r / 255.0 , g / 255.0 , b / 255.0 , 0.3 ) ;
AvHSpriteSetDrawMode ( kSpriteDrawModeFilled ) ;
AvHSpriteDraw ( sprite , 0 , mSelectionBoxX1 + 1 , mSelectionBoxY1 + 1 , mSelectionBoxX2 - 1 , mSelectionBoxY2 - 1 , 0 , 0 , 1 , 1 ) ;
AvHSpriteSetRenderMode ( kRenderNormal ) ;
AvHSpriteSetColor ( 1 , 1 , 1 , 1 ) ;
AvHSpriteSetDrawMode ( kSpriteDrawModeBorder ) ;
AvHSpriteDraw ( sprite , 0 , mSelectionBoxX1 , mSelectionBoxY1 , mSelectionBoxX2 , mSelectionBoxY2 , 0 , 0 , 1 , 1 ) ;
}
AvHSpriteEndFrame ( ) ;
}
}
}
void AvHHud : : DrawTopDownBG ( )
{
// If we're in top down mode, draw a black background
float theDrawBackgroundHeight = - 1 ; //cl_drawbg->value;
// Draw the bottom plane at the map's min view height, unless overridden by cl_drawbg (this variable is for for testing purposes only)
if ( theDrawBackgroundHeight = = - 1 )
{
if ( this - > mMapExtents . GetDrawMapBG ( ) )
{
theDrawBackgroundHeight = this - > mMapExtents . GetMinViewHeight ( ) ;
}
}
if ( theDrawBackgroundHeight ! = - 1 )
{
if ( this - > mBackgroundSprite )
{
// Build three points on plane described by max world dimensions at the draw background height
Vector theUpperLeftWorldPos ( - kMaxMapDimension , kMaxMapDimension , theDrawBackgroundHeight ) ;
Vector theUpperRightWorldPos ( kMaxMapDimension , kMaxMapDimension , theDrawBackgroundHeight ) ;
Vector theLowerLeftWorldPos ( - kMaxMapDimension , - kMaxMapDimension , theDrawBackgroundHeight ) ;
// Calculate plane info
float thePlaneD ;
Vector thePlaneNormal ;
CalculatePlaneInfo ( theUpperLeftWorldPos , theUpperRightWorldPos , theLowerLeftWorldPos , thePlaneD , thePlaneNormal ) ;
gEngfuncs . pTriAPI - > RenderMode ( kRenderNormal ) ;
gEngfuncs . pTriAPI - > CullFace ( TRI_NONE ) ;
gEngfuncs . pTriAPI - > Brightness ( 1 ) ;
if ( gEngfuncs . pTriAPI - > SpriteTexture ( ( struct model_s * ) gEngfuncs . GetSpritePointer ( this - > mBackgroundSprite ) , 0 ) )
{
gEngfuncs . pTriAPI - > Begin ( TRI_TRIANGLE_STRIP ) ;
gEngfuncs . pTriAPI - > Color4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
Vector thePoint ;
CalculatePointOnPlane ( 0 , ScreenHeight ( ) , GetViewOrigin ( ) , thePlaneNormal , thePlaneD , thePoint ) ;
gEngfuncs . pTriAPI - > TexCoord2f ( 0 , 1 ) ;
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePoint ) ;
CalculatePointOnPlane ( 0 , 0 , GetViewOrigin ( ) , thePlaneNormal , thePlaneD , thePoint ) ;
gEngfuncs . pTriAPI - > TexCoord2f ( 0 , 0 ) ;
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePoint ) ;
CalculatePointOnPlane ( ScreenWidth ( ) , ScreenHeight ( ) , GetViewOrigin ( ) , thePlaneNormal , thePlaneD , thePoint ) ;
gEngfuncs . pTriAPI - > TexCoord2f ( 1 , 1 ) ;
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePoint ) ;
CalculatePointOnPlane ( ScreenWidth ( ) , 0 , GetViewOrigin ( ) , thePlaneNormal , thePlaneD , thePoint ) ;
gEngfuncs . pTriAPI - > TexCoord2f ( 1 , 0 ) ;
gEngfuncs . pTriAPI - > Vertex3fv ( ( float * ) & thePoint ) ;
// Add in some buffer because of perspective
// pVector ver;
// ver.z = theDrawBackgroundHeight;
//
// // Lower left
// gEngfuncs.pTriAPI->TexCoord2f(0,1);
// ver.x = -kMaxMapDimension;
// ver.y = -kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
//
// // Upper left
// gEngfuncs.pTriAPI->TexCoord2f(0,0);
// ver.x = -kMaxMapDimension;
// ver.y = kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
//
// // Upper right
// gEngfuncs.pTriAPI->TexCoord2f(1,0);
// ver.x = kMaxMapDimension;
// ver.y = kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
//
// // Lower right
// gEngfuncs.pTriAPI->TexCoord2f(1,1);
// ver.x = kMaxMapDimension;
// ver.y = -kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
gEngfuncs . pTriAPI - > End ( ) ;
}
}
}
}
void AvHHud : : PostModelRender ( char * inModelName )
{
// Get our view model name
cl_entity_t * theViewEntity = gEngfuncs . GetViewModel ( ) ;
if ( theViewEntity )
{
// If this is our view model, that means we can now render our own stuff in screen space without z-buffering on top of everything else
if ( theViewEntity - > model )
{
if ( ! strcmp ( theViewEntity - > model - > name , inModelName ) )
{
this - > RenderNoZBuffering ( ) ;
}
}
}
}
float AvHHud : : GetHUDExperience ( ) const
{
vec3_t theVUser4 ;
theVUser4 . z = 0.0f ;
cl_entity_s * theLocalPlayer = gEngfuncs . GetLocalPlayer ( ) ;
if ( theLocalPlayer )
{
theVUser4 = theLocalPlayer - > curstate . vuser4 ;
}
if ( g_iUser1 = = OBS_IN_EYE )
{
cl_entity_t * theEnt = gEngfuncs . GetEntityByIndex ( g_iUser2 ) ;
if ( theEnt )
{
theVUser4 = theEnt - > curstate . vuser4 ;
}
}
float theExperience = theVUser4 . z / kNumericNetworkConstant ;
return theExperience ;
}
int AvHHud : : GetHUDExperienceLevel ( ) const
{
float theExperience = this - > GetHUDExperience ( ) ;
int theLevel = AvHPlayerUpgrade : : GetPlayerLevel ( theExperience ) ;
return theLevel ;
}
float AvHHud : : GetHUDHandicap ( ) const
{
float theHandicap = 100.0f ;
AvHTeamNumber theTeamNumber = this - > GetHUDTeam ( ) ;
switch ( theTeamNumber )
{
case TEAM_ONE :
theHandicap = this - > GetServerVariableFloat ( kvTeam1DamagePercent ) ;
break ;
case TEAM_TWO :
theHandicap = this - > GetServerVariableFloat ( kvTeam2DamagePercent ) ;
break ;
2005-04-01 03:04:57 +00:00
case TEAM_THREE :
theHandicap = this - > GetServerVariableFloat ( kvTeam3DamagePercent ) ;
break ;
case TEAM_FOUR :
theHandicap = this - > GetServerVariableFloat ( kvTeam4DamagePercent ) ;
break ;
2005-03-09 01:31:56 +00:00
}
return theHandicap ;
}
AvHUser3 AvHHud : : GetHUDUser3 ( ) const
{
AvHUser3 theUser3 = AVH_USER3_NONE ;
cl_entity_s * theLocalPlayer = gEngfuncs . GetLocalPlayer ( ) ;
if ( theLocalPlayer )
{
theUser3 = ( AvHUser3 ) ( theLocalPlayer - > curstate . iuser3 ) ;
}
if ( g_iUser1 = = OBS_IN_EYE )
{
cl_entity_t * theEnt = gEngfuncs . GetEntityByIndex ( g_iUser2 ) ;
if ( theEnt )
{
theUser3 = ( AvHUser3 ) ( theEnt - > curstate . iuser3 ) ;
}
}
return theUser3 ;
}
AvHTeamNumber AvHHud : : GetHUDTeam ( ) const
{
AvHTeamNumber theTeamNumber = TEAM_IND ;
cl_entity_s * thePlayer = this - > GetVisiblePlayer ( ) ;
if ( thePlayer )
{
theTeamNumber = AvHTeamNumber ( thePlayer - > curstate . team ) ;
}
return theTeamNumber ;
}
int AvHHud : : GetHUDUpgrades ( ) const
{
int theUpgrades = 0 ;
cl_entity_s * thePlayer = this - > GetVisiblePlayer ( ) ;
if ( thePlayer )
{
theUpgrades = thePlayer - > curstate . iuser4 ;
}
return theUpgrades ;
}
int AvHHud : : GetHUDMaxArmor ( ) const
{
int theHUDUpgrades = this - > GetHUDUpgrades ( ) ;
AvHUser3 theUser3 = this - > GetHUDUser3 ( ) ;
int theMaxArmor = AvHPlayerUpgrade : : GetMaxArmorLevel ( theHUDUpgrades , theUser3 ) ;
return theMaxArmor ;
}
int AvHHud : : GetHUDMaxHealth ( ) const
{
int theHUDUpgrades = this - > GetHUDUpgrades ( ) ;
AvHUser3 theUser3 = this - > GetHUDUser3 ( ) ;
int theHUDExperienceLevel = this - > GetHUDExperienceLevel ( ) ;
int theMaxHealth = AvHPlayerUpgrade : : GetMaxHealth ( theHUDUpgrades , theUser3 , theHUDExperienceLevel ) ;
return theMaxHealth ;
}
void AvHHud : : GetPrimaryHudColor ( int & outR , int & outG , int & outB , bool inIgnoreUpgrades , bool gammaCorrect ) const
{
if ( this - > GetIsMarine ( ) )
{
UnpackRGB ( outR , outG , outB , RGB_MARINE_BLUE ) ;
}
else
{
// HUD turns green when we're frenzying
//if(GetHasUpgrade(this->GetHUDUpgrades(), MASK_PRIMALSCREAM) && !inIgnoreUpgrades)
//{
// UnpackRGB(outR, outG, outB, RGB_GREENISH);
//}
//else
//{
UnpackRGB ( outR , outG , outB , RGB_YELLOWISH ) ;
//}
}
if ( gammaCorrect )
{
// Take into account current gamma?
float theGammaSlope = this - > GetGammaSlope ( ) ;
outR / = theGammaSlope ;
outG / = theGammaSlope ;
outB / = theGammaSlope ;
}
}
void AvHHud : : HandleFog ( )
{
float theFogColor [ 3 ] ;
theFogColor [ 0 ] = this - > mFogColor . x ;
theFogColor [ 1 ] = this - > mFogColor . y ;
theFogColor [ 2 ] = this - > mFogColor . z ;
gEngfuncs . pTriAPI - > Fog ( theFogColor , this - > mFogStart , this - > mFogEnd , this - > mFogActive ) ;
}
void AvHHud : : PreRenderFrame ( )
{
bool theRenderForTopDown = this - > mInTopDownMode /*&& !this->mIsRenderingSelectionView*/ ;
if ( ! theRenderForTopDown )
{
this - > HandleFog ( ) ;
}
else
{
this - > DrawTopDownBG ( ) ;
// Now draw commander HUD scaled
//void CreatePickingRay( int mousex, int mousey, Vector& outVecPickingRay )
// static int theCommanderHUDSprite = 0;
// if(!theCommanderHUDSprite)
// {
// theCommanderHUDSprite = Safe_SPR_Load("sprites/.spr");
// }
//
// if(theCommanderHUDSprite)
// {
// gEngfuncs.pTriAPI->RenderMode( kRenderNormal );
// gEngfuncs.pTriAPI->CullFace( TRI_NONE );
// gEngfuncs.pTriAPI->Brightness( 1 );
//
// if(gEngfuncs.pTriAPI->SpriteTexture((struct model_s *)gEngfuncs.GetSpritePointer(theCommanderHUDSprite), 0))
// {
// gEngfuncs.pTriAPI->Begin( TRI_QUADS );
//
// gEngfuncs.pTriAPI->Color4f(1.0f, 1.0f, 1.0f, .5f);
//
// pVector ver;
//
// // Lower left
// const float kMaxMapDimension = 4096;
// //ver.z = -kMaxMapDimension;
// ver.z = theDrawBackgroundHeight;
//
// gEngfuncs.pTriAPI->TexCoord2f(0,1);
// ver.x = -kMaxMapDimension;
// ver.y = -kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
//
// // Upper left
// gEngfuncs.pTriAPI->TexCoord2f(0,0);
// ver.x = -kMaxMapDimension;
// ver.y = kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
//
// // Upper right
// gEngfuncs.pTriAPI->TexCoord2f(1,0);
// ver.x = kMaxMapDimension;
// ver.y = kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
//
// // Lower right
// gEngfuncs.pTriAPI->TexCoord2f(1,1);
// ver.x = kMaxMapDimension;
// ver.y = -kMaxMapDimension;
// gEngfuncs.pTriAPI->Vertex3fv((float*)&ver);
//
// gEngfuncs.pTriAPI->End();
// }
// }
}
AvHScriptManager : : Instance ( ) - > DrawNormal ( ) ;
}
void AvHHud : : PostRenderFrame ( )
{
// Restore player angles and view position
// v_origin = gPlayerOrigin;
// v_angles = gPlayerAngles;
}
void AvHHud : : DrawActionButtons ( )
{
// Look up AvHActionButtons component
AvHActionButtons * theActionButtons = NULL ;
if ( this - > GetManager ( ) . GetVGUIComponentNamed ( kActionButtonsComponents , theActionButtons ) )
{
int theNumCols = theActionButtons - > GetNumCols ( ) ;
int theNumRows = theActionButtons - > GetNumRows ( ) ;
// Iterate through num cols
for ( int theCol = 0 ; theCol < theNumCols ; theCol + + )
{
// Iterate through num rows
for ( int theRow = 0 ; theRow < theNumRows ; theRow + + )
{
// Get current ActionButton
ActionButton * theActionButton = theActionButtons - > GetActionButtonAtPos ( theCol , theRow ) ;
ASSERT ( theActionButton ) ;
// Get message ID for button
AvHMessageID theMessageID = theActionButton - > GetMessageID ( ) ;
// Find the group that it belongs to (20, 30, 40, etc.)
int theMessageNumber = ( int ) theMessageID - ( theMessageID % 10 ) ;
// // Load sprite if not loaded
// bool theSpriteLoaded = (this->mActionButtonSprites[theMessageNumber] > 0);
// if(!theSpriteLoaded)
// {
// // Build sprite name for message ID
// char theMessageNumberString[16];
// sprintf(theMessageNumberString, "%d", (int)theMessageNumber);
// //string theSpriteName = kTechTreeSpriteDirectory + string("/") + kTechTreeSpritePrefix + string(theMessageIDString) + string(".spr");
// string theSpriteName = kTechTreeSpriteDirectory + string("/") + kTechTreeSpritePrefix + string(theMessageNumberString) + string("s.spr");
// int theSpriteHandle = Safe_SPR_Load(theSpriteName.c_str());
//
// // Sprite handle can be 0, as I don't have sprites for all tech yet
// this->mActionButtonSprites[theMessageNumber] = theSpriteHandle;
// }
// Get pos and size for component
int thePosX , thePosY ;
theActionButton - > getPos ( thePosX , thePosY ) ;
int theWidth , theHeight ;
theActionButton - > getSize ( theWidth , theHeight ) ;
// Set sprite frame depending if button is available, active
bool theTechEnabled = theActionButton - > GetTechEnabled ( ) ;
bool theMouseOver = theActionButton - > GetMouseOver ( ) ;
bool theCostMet = theActionButton - > GetCostMet ( ) ;
// 0 = default
// 1 = highlighted
// 2 = dark
// 3 = red
int theFrame = 2 ;
// If it's enabled, or if it's an icon in the "menu navigation" category, allow it to be highlighted
if ( theTechEnabled | | ( theMessageNumber = = 80 ) )
{
if ( theCostMet )
{
if ( theMouseOver )
{
theFrame = 1 ;
}
else
{
theFrame = 0 ;
}
}
else
{
theFrame = 3 ;
}
}
// Also highlight menu category headings for open menus, and for active nodes just pressed
if ( gCommanderHandler . GetDisplayMenuMessageID ( ) = = theMessageID )
{
theFrame = 1 ;
}
else
{
AvHMessageID theMessageJustActivated = MESSAGE_NULL ;
if ( gCommanderHandler . GetAndClearTechNodePressed ( theMessageJustActivated , false ) )
{
if ( theMessageJustActivated = = theMessageID )
{
if ( theTechEnabled )
{
theFrame = 1 ;
}
}
}
}
this - > DrawTechTreeSprite ( theMessageID , thePosX , thePosY , theWidth , theHeight , theFrame ) ;
}
}
}
}
int AvHHud : : GetTechTreeSprite ( AvHMessageID inMessageID )
{
// Find the group that it belongs to (20, 30, 40, etc.)
int theMessageNumber = ( int ) inMessageID - ( inMessageID % 10 ) ;
// Load sprite if not loaded
bool theSpriteLoaded = ( this - > mActionButtonSprites [ theMessageNumber ] > 0 ) ;
if ( ! theSpriteLoaded & & ( theMessageNumber ! = 0 ) )
{
// Build sprite name for message ID
char theMessageNumberString [ 16 ] ;
sprintf ( theMessageNumberString , " %d " , ( int ) theMessageNumber ) ;
//string theSpriteName = kTechTreeSpriteDirectory + string("/") + kTechTreeSpritePrefix + string(theMessageIDString) + string(".spr");
string theSpriteName = kTechTreeSpriteDirectory + string ( " / " ) + kTechTreeSpritePrefix + string ( theMessageNumberString ) + string ( " s.spr " ) ;
int theSpriteHandle = Safe_SPR_Load ( theSpriteName . c_str ( ) ) ;
// Sprite handle can be 0, as I don't have sprites for all tech yet
this - > mActionButtonSprites [ theMessageNumber ] = theSpriteHandle ;
}
// Fetch sprite handle
int theSpriteHandle = this - > mActionButtonSprites [ theMessageNumber ] ;
return theSpriteHandle ;
}
void AvHHud : : DrawTechTreeSprite ( AvHMessageID inMessageID , int inPosX , int inPosY , int inWidth , int inHeight , int inFrame )
{
if ( inMessageID ! = MESSAGE_NULL )
{
// Check for alien sprites
bool theIsAlienSprite = false ;
int theSpriteHandle = 0 ;
int theRenderMode = kRenderTransAlpha ; // kRenderNormal
switch ( inMessageID )
{
case ALIEN_BUILD_DEFENSE_CHAMBER :
theIsAlienSprite = true ;
inFrame = 0 ;
break ;
case ALIEN_BUILD_OFFENSE_CHAMBER :
theIsAlienSprite = true ;
inFrame = 1 ;
break ;
case ALIEN_BUILD_MOVEMENT_CHAMBER :
theIsAlienSprite = true ;
inFrame = 2 ;
break ;
case ALIEN_BUILD_SENSORY_CHAMBER :
theIsAlienSprite = true ;
inFrame = 3 ;
break ;
case ALIEN_BUILD_RESOURCES :
theIsAlienSprite = true ;
inFrame = 4 ;
break ;
case ALIEN_BUILD_HIVE :
theIsAlienSprite = true ;
inFrame = 5 ;
break ;
}
float theStartU = 0.0f ;
float theStartV = 0.0f ;
float theEndU = 1.0f ;
float theEndV = 1.0f ;
if ( theIsAlienSprite )
{
theRenderMode = kRenderTransAlpha ;
theSpriteHandle = this - > mAlienUIUpgradeCategories ;
}
else
{
// Fetch sprite handle
theSpriteHandle = this - > GetTechTreeSprite ( inMessageID ) ;
int theIndex = inMessageID % 10 ;
int theXIndex = theIndex % 4 ;
int theYIndex = ( theIndex / 4 ) ;
theStartU = theXIndex * .25f ;
theStartV = theYIndex * .25f ;
theEndU = ( theXIndex + 1 ) * .25f ;
theEndV = ( theYIndex + 1 ) * .25f ;
}
if ( theSpriteHandle > 0 )
{
// Draw sprite scaled here
AvHSpriteSetRenderMode ( theRenderMode ) ;
AvHSpriteDraw ( theSpriteHandle , inFrame , inPosX , inPosY , inPosX + inWidth , inPosY + inHeight , theStartU , theStartV , theEndU , theEndV ) ;
}
}
}
void AvHHud : : DrawHotgroups ( )
{
AvHMessageID theHotgroups [ kNumHotkeyGroups ] = { GROUP_SELECT_1 , GROUP_SELECT_2 , GROUP_SELECT_3 , GROUP_SELECT_4 , GROUP_SELECT_5 } ;
// Run through list of hotgroups, drawing them if they exist
for ( int i = 0 ; i < kNumHotkeyGroups ; i + + )
{
EntityListType & theHotgroup = this - > mGroups [ i ] ;
if ( theHotgroup . size ( ) > 0 )
{
// Get message ID to draw
AvHUser3 theGroupTypeUser3 = this - > mGroupTypes [ i ] ;
// Default is marine face
AvHMessageID theHotgroupIcon = MENU_SOLDIER_FACE ;
AvHSHUUser3ToMessageID ( theGroupTypeUser3 , theHotgroupIcon ) ;
// Build component name ("PendingImpulseXPanel", where X is the impulse)
AvHMessageID theHotgroupMessageID = theHotgroups [ i ] ;
char theComponentName [ 256 ] ;
sprintf ( theComponentName , kPendingImpulseSpecifier , ( int ) theHotgroupMessageID ) ;
AvHTechImpulsePanel * theTechImpulsePanel = NULL ;
if ( this - > GetManager ( ) . GetVGUIComponentNamed ( theComponentName , theTechImpulsePanel ) )
{
int thePosX , thePosY ;
theTechImpulsePanel - > getPos ( thePosX , thePosY ) ;
int theWidth , theHeight ;
theTechImpulsePanel - > getSize ( theWidth , theHeight ) ;
// Highlight if mouse is in region or if it's our current selection
bool theIsHighlighted = this - > GetIsMouseInRegion ( thePosX , thePosY , theWidth , theHeight ) | | ( this - > mSelected = = theHotgroup ) ;
int theFrame = theIsHighlighted ? 1 : 0 ;
int theSecondOfLastUpdate = ( int ) this - > mTimeOfLastUpdate ;
if ( ( this - > mGroupAlerts [ i ] = = ALERT_UNDER_ATTACK ) & & ( theSecondOfLastUpdate % 2 ) )
{
// Play blinking red frame when being attacked
theFrame = 3 ;
}
this - > DrawTechTreeSprite ( theHotgroupIcon , thePosX , thePosY , theWidth , theHeight , theFrame ) ;
2005-04-01 03:04:57 +00:00
theTechImpulsePanel - > SetVisualNumber ( ( int ) theHotgroup . size ( ) ) ;
2005-03-09 01:31:56 +00:00
}
}
}
}
// Draw pending requests
void AvHHud : : DrawPendingRequests ( )
{
// Run through list of requests and delete any entries with
PendingRequestListType : : iterator theIterator ;
for ( theIterator = this - > mPendingRequests . begin ( ) ; theIterator ! = this - > mPendingRequests . end ( ) ; /* nothing */ )
{
if ( theIterator - > second = = 0 )
{
PendingRequestListType : : iterator theSavedIter = theIterator ;
theSavedIter + + ;
this - > mPendingRequests . erase ( theIterator ) ;
theIterator = theSavedIter ;
}
else
{
theIterator + + ;
}
}
2005-04-01 03:04:57 +00:00
int theNumRequestsToDraw = ( int ) this - > mPendingRequests . size ( ) ;
2005-03-09 01:31:56 +00:00
int theCounter = 0 ;
for ( theIterator = this - > mPendingRequests . begin ( ) ; theIterator ! = this - > mPendingRequests . end ( ) ; theIterator + + )
{
// Draw each one above the minimap
AvHMessageID theMessageID = theIterator - > first ;
int theNumRequests = theIterator - > second ;
// Build component name ("PendingImpulseXPanel", where X is the impulse)
char theComponentName [ 256 ] ;
sprintf ( theComponentName , kPendingImpulseSpecifier , ( int ) theMessageID ) ;
AvHTechImpulsePanel * theTechImpulsePanel = NULL ;
if ( this - > GetManager ( ) . GetVGUIComponentNamed ( theComponentName , theTechImpulsePanel ) )
{
// Get size of panel and draw tech sprite there
int thePosX , thePosY ;
theTechImpulsePanel - > getPos ( thePosX , thePosY ) ;
int theWidth , theHeight ;
theTechImpulsePanel - > getSize ( theWidth , theHeight ) ;
AvHMessageID theMessageToDraw = theMessageID ;
switch ( theMessageID )
{
case COMMANDER_NEXTIDLE :
theMessageToDraw = MENU_SOLDIER_FACE ;
break ;
case COMMANDER_NEXTAMMO :
theMessageToDraw = BUILD_AMMO ;
break ;
case COMMANDER_NEXTHEALTH :
theMessageToDraw = BUILD_HEALTH ;
break ;
}
int theFrame = this - > GetIsMouseInRegion ( thePosX , thePosY , theWidth , theHeight ) ? 1 : 0 ;
this - > DrawTechTreeSprite ( theMessageToDraw , thePosX , thePosY , theWidth , theHeight , theFrame ) ;
theTechImpulsePanel - > SetVisualNumber ( theNumRequests ) ;
if ( theNumRequests > 0 )
{
theTechImpulsePanel - > setVisible ( true ) ;
}
else
{
theTechImpulsePanel - > setVisible ( false ) ;
}
//this->DrawHUDNumber(thePosX + kTileWidth, thePosY + kTileHeight, DHN_2DIGITS, theNumRequests);
}
// Draw indicator on sprite showing how many requests there are
theCounter + + ;
}
}
void AvHHud : : DrawBuildHealthEffectsForEntity ( int inEntityIndex )
{
// Get entity
int theUser3 = 0 ;
int theUser4 = 0 ;
float theFuser1 = 0.0f ;
int theEntityTeam = 0 ;
vec3_t theOrigin ;
vec3_t theMins ;
vec3_t theMaxs ;
bool theContinue = false ;
float theHealthPercentage = 0.0f ;
double theDistanceToEntity = 0 ;
2005-04-01 03:04:57 +00:00
cl_entity_s * theEntity = gEngfuncs . GetEntityByIndex ( inEntityIndex ) ;
if ( theEntity )
{
theUser3 = theEntity - > curstate . iuser3 ;
theUser4 = theEntity - > curstate . iuser4 ;
theFuser1 = theEntity - > curstate . fuser1 ;
theEntityTeam = theEntity - > curstate . team ;
//theOrigin = theEntity->curstate.origin;
theOrigin = AvHSHUGetRealLocation ( theEntity - > origin , theEntity - > curstate . mins , theEntity - > curstate . maxs ) ;
if ( theEntity - > player )
2005-03-09 01:31:56 +00:00
{
2005-04-01 03:04:57 +00:00
// Subtract half-height to be at feet
float theHeight = theEntity - > curstate . maxs [ 2 ] - theEntity - > curstate . mins [ 2 ] ;
theOrigin [ 2 ] - = theHeight / 2.0f ;
2005-03-09 01:31:56 +00:00
}
2005-04-01 03:04:57 +00:00
theDistanceToEntity = VectorDistance ( gPredictedPlayerOrigin , theOrigin ) ;
theMins = theEntity - > curstate . mins ;
theMaxs = theEntity - > curstate . maxs ;
theHealthPercentage = theEntity - > curstate . fuser2 / kNormalizationNetworkFactor ;
theContinue = true ;
}
2005-03-09 01:31:56 +00:00
// Get local player
cl_entity_s * theLocalPlayer = gEngfuncs . GetLocalPlayer ( ) ;
bool theDrewBuildInProgress = false ;
float theOversizeScalar = 1.0f ;
bool theEntityIsPlayer = ( ( inEntityIndex > 0 ) & & ( inEntityIndex < = gEngfuncs . GetMaxClients ( ) ) ) ;
bool theIsOnOurTeam = ( theEntityTeam = = ( int ) this - > GetHUDTeam ( ) ) ;
if ( AvHSHUGetDrawRingsForUser3 ( ( AvHUser3 ) theUser3 , theOversizeScalar ) )
{
if ( theContinue & & theLocalPlayer )
{
const kDrawEnemyBuildingDistance = 200 ;
// Draw effects if we are in top-down mode OR
if ( this - > GetInTopDownMode ( ) | |
// It's an unfriendly building that's very close OR
( ! theEntityIsPlayer & & ( theDistanceToEntity < kDrawEnemyBuildingDistance ) ) | |
// It's a friendly entity and we're a builder
( theIsOnOurTeam & & ( this - > GetHUDUser3 ( ) = = AVH_USER3_ALIEN_PLAYER2 ) )
)
{
// If they're not on opposite teams
//if((theEntityTeam == theLocalPlayer->curstate.team) || (theEntityTeam == 0))
//{
// Get entity build/research state
bool theIsBuilding = false ;
bool theIsResearching = false ;
float theNormalizedPercentage = 0.0f ;
// Calculate percentage full
AvHSHUGetBuildResearchState ( theUser3 , theUser4 , theFuser1 , theIsBuilding , theIsResearching , theNormalizedPercentage ) ;
bool theDrawHealth = true ;
int theSpriteToUse = this - > GetIsAlien ( ) ? this - > mAlienHealthSprite : this - > mMarineHealthSprite ;
bool theDrawAsRecyling = ( GetHasUpgrade ( theUser4 , MASK_RECYCLING ) & & theIsOnOurTeam ) ;
if ( ( theIsBuilding & & ( GetHasUpgrade ( theUser4 , MASK_BUILDABLE ) ) ) | | theDrawAsRecyling )
{
theSpriteToUse = this - > GetIsAlien ( ) ? this - > mAlienBuildSprite : this - > mMarineBuildSprite ;
theDrawHealth = false ;
// Draw progress inverted, as we're "undoing" the structure
if ( theDrawAsRecyling )
{
theNormalizedPercentage = ( 1.0f - theNormalizedPercentage ) ;
}
}
else
{
theNormalizedPercentage = theHealthPercentage ;
}
if ( theDrawHealth | | ( theEntityTeam = = theLocalPlayer - > curstate . team ) )
{
// Draw it
int theNumFrames = SPR_Frames ( theSpriteToUse ) ;
ASSERT ( theNumFrames > 0 ) ;
int theCurrentFrame ;
if ( ( theHealthPercentage < 1.0f ) | | theDrawAsRecyling )
{
theCurrentFrame = theNormalizedPercentage * ( theNumFrames - 1 ) ;
// tankefugl: 0000893
// quick hack to eliminate 1 red bar shown for dead players
if ( theEntity - > player )
theCurrentFrame = min ( max ( 0 , theCurrentFrame ) , theNumFrames - 1 ) ;
else
theCurrentFrame = min ( max ( 1 , theCurrentFrame ) , theNumFrames - 1 ) ;
// :tankefugl
}
else
{
theCurrentFrame = theNumFrames - 1 ;
}
// Get real position of entity
vec3_t thePosition ;
thePosition = AvHSHUGetRealLocation ( theOrigin , theMins , theMaxs ) ;
float theMaxX = theMaxs [ 0 ] - theMins [ 0 ] ;
float theMaxY = theMaxs [ 1 ] - theMins [ 1 ] ;
float theRadius = max ( theMaxX , theMaxY ) * theOversizeScalar ;
// Bring position off ground just a little to prevent z-fighting
thePosition . z + = kZFightingOffset ;
//GetHasUpgrade(this->GetHUDUpgrades(), MASK_PARASITED)
DrawSpriteOnGroundAtPoint ( thePosition , theRadius , theSpriteToUse , kRenderTransAdd , theCurrentFrame ) ;
theDrewBuildInProgress = true ;
}
}
}
}
}
void AvHHud : : DrawHUDNumber ( int inX , int inY , int inFlags , int inNumber )
{
// Draw number on HUD, in our HUD color
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , false , false ) ;
int theGammaSlope = this - > GetGammaSlope ( ) ;
theR / = theGammaSlope ;
theG / = theGammaSlope ;
theB / = theGammaSlope ;
this - > DrawHudNumber ( inX , inY , inFlags , inNumber , theR , theG , theB ) ;
}
void AvHHud : : DrawSelectionAndBuildEffects ( )
{
// Draw build effects
for ( SelectionListType : : iterator theSelectIter = this - > mSelectionEffects . begin ( ) ; theSelectIter ! = this - > mSelectionEffects . end ( ) ; theSelectIter + + )
{
// Draw selection effect around the entity
int theEntIndex = theSelectIter - > mEntIndex ;
this - > DrawBuildHealthEffectsForEntity ( theEntIndex ) ;
}
bool theDrawBuildingEffect = false ;
for ( EntityListType : : iterator theBuildingIter = this - > mBuildingEffectsEntityList . begin ( ) ; theBuildingIter ! = this - > mBuildingEffectsEntityList . end ( ) ; theBuildingIter + + )
{
int theEntIndex = * theBuildingIter ;
this - > DrawBuildHealthEffectsForEntity ( theEntIndex ) ;
}
}
void AvHHud : : Render ( )
{
if ( ! IEngineStudio . IsHardware ( ) )
{
// Don't show anything in software mode.
const char * theMessage = " Software mode is not supported by Natural Selection " ;
int theWidth ;
int theHeight ;
float gammaScale = 1.0f / GetGammaSlope ( ) ;
gEngfuncs . pfnDrawSetTextColor ( 0 , gammaScale , 0 ) ;
gEngfuncs . pfnDrawConsoleStringLen ( theMessage , & theWidth , & theHeight ) ;
gEngfuncs . pfnDrawConsoleString ( ( ScreenWidth ( ) - theWidth ) / 2 , ( ScreenHeight ( ) - theHeight ) / 2 , ( char * ) theMessage ) ;
return ;
}
if ( m_Spectator . IsInOverviewMode ( ) )
{
AvHSpriteSetViewport ( mSpecialViewport [ 0 ] , mSpecialViewport [ 1 ] ,
mSpecialViewport [ 0 ] + mSpecialViewport [ 2 ] , mSpecialViewport [ 1 ] + mSpecialViewport [ 3 ] ) ;
}
AvHSpriteBeginFrame ( ) ;
if ( mSteamUIActive )
{
// Use the old 2D method if we're in the Steam UI.
AvHSpriteEnableVGUI ( false ) ;
}
else
{
AvHSpriteEnableVGUI ( true ) ;
AvHSpriteSetVGUIOffset ( 0 , 0 ) ;
}
# ifdef DEBUG
if ( CVAR_GET_FLOAT ( " hud_hideview " ) ! = 0 )
{
// Black out the screen
int sprite = Safe_SPR_Load ( kWhiteSprite ) ;
AvHSpriteSetColor ( 0 , 0 , 0 , 1 ) ;
AvHSpriteDraw ( sprite , 0 , 0 , 0 , ScreenWidth ( ) , ScreenHeight ( ) , 0 , 0 , 1 , 1 ) ;
AvHSpriteSetColor ( 1 , 1 , 1 , 1 ) ;
}
# endif
// Don't draw the HUD while being digested.
if ( GetIsBeingDigested ( ) )
{
if ( this - > mDigestingSprite )
{
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteSetRenderMode ( kRenderNormal ) ;
DrawWarpedOverlaySprite ( mDigestingSprite , 4 , 3 , .02 , .02 , .3 , .15 ) ;
}
}
else
{
if ( this - > GetHUDPlayMode ( ) = = PLAYMODE_PLAYING | |
this - > GetHUDPlayMode ( ) = = PLAYMODE_READYROOM )
{
if ( ! mSteamUIActive )
{
this - > DrawReticleInfo ( ) ;
this - > DrawPlayerNames ( ) ;
this - > DrawToolTips ( ) ;
}
}
if ( this - > GetHUDPlayMode ( ) = = PLAYMODE_PLAYING )
{
RenderCommonUI ( ) ;
if ( GetIsMarine ( ) )
{
if ( GetInTopDownMode ( ) )
{
RenderCommanderUI ( ) ;
}
else
{
RenderMarineUI ( ) ;
}
}
else if ( GetIsAlien ( ) )
{
RenderAlienUI ( ) ;
}
}
}
AvHSpriteEndFrame ( ) ;
AvHSpriteClearViewport ( ) ;
}
void AvHHud : : RenderCommonUI ( )
{
if ( ! mSteamUIActive )
{
if ( gHUD . GetServerVariableFloat ( " sv_cheats " ) ! = 0 & & CVAR_GET_FLOAT ( " cl_showspeed " ) ! = 0 )
{
// Draw the speedometer.
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , true , false ) ;
extern playermove_s * pmove ;
char buffer [ 1024 ] ;
sprintf ( buffer , " Speed = %d " , ( int ) Length ( pmove - > velocity ) ) ;
mFont . DrawString ( 10 , 10 , buffer , theR , theG , theB ) ;
float theGroundSpeed = sqrtf ( pmove - > velocity [ 0 ] * pmove - > velocity [ 0 ] + pmove - > velocity [ 1 ] * pmove - > velocity [ 1 ] ) ;
sprintf ( buffer , " Ground speed = %d " , ( int ) theGroundSpeed ) ;
mFont . DrawString ( 10 , 12 + mFont . GetStringHeight ( ) , buffer , theR , theG , theB ) ;
}
DrawInfoLocationText ( ) ;
DrawHUDStructureNotification ( ) ;
this - > DrawOrders ( ) ;
this - > DrawHelpIcons ( ) ;
if ( this - > GetIsCombatMode ( ) )
{
// If we're in combat mode, draw our rank
const float kTitleYInset = ( kPlayerStatusVerticalInset + 5 * kPlayerStatusStatusSpacing ) ;
string theTitleText = this - > GetRankTitle ( true ) ;
char theCharArray [ 512 ] ;
sprintf ( theCharArray , theTitleText . c_str ( ) ) ;
// Draw it
int theX = mViewport [ 0 ] + kPlayerStatusHorizontalCenteredInset * ( mViewport [ 2 ] - mViewport [ 0 ] ) ;
int theY = mViewport [ 1 ] + mViewport [ 3 ] - ( 1 - kTitleYInset ) * ScreenHeight ( ) ;
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , true , false ) ;
this - > DrawHudStringCentered ( theX , theY , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
// If we're parasited, draw a message as such
if ( this - > GetIsAlive ( ) )
{
string theText ;
char theCharArray [ 512 ] ;
int theR , theG , theB ;
//UnpackRGB(theR, theG, theB, RGB_YELLOWISH);
this - > GetPrimaryHudColor ( theR , theG , theB , true , false ) ;
int theSecondOfLastUpdate = ( int ) this - > mTimeOfLastUpdate ;
// Draw blinking primal scream message
if ( GetHasUpgrade ( this - > GetHUDUpgrades ( ) , MASK_BUFFED ) & & ( theSecondOfLastUpdate % 2 ) )
{
if ( this - > GetIsAlien ( ) )
{
LocalizeString ( kPrimalScreamed , theText ) ;
}
else if ( this - > GetIsMarine ( ) )
{
LocalizeString ( kCatalysted , theText ) ;
}
// Draw it
sprintf ( theCharArray , " %s " , theText . c_str ( ) ) ;
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , kPlayerStatusVerticalInset * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
// Draw parasited indicator
if ( GetHasUpgrade ( this - > GetHUDUpgrades ( ) , MASK_PARASITED ) )
{
LocalizeString ( kParasited , theText ) ;
sprintf ( theCharArray , " %s " , theText . c_str ( ) ) ;
// Draw it
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , ( kPlayerStatusVerticalInset + kPlayerStatusStatusSpacing ) * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
// Draw umbraed indicator
if ( GetHasUpgrade ( this - > GetHUDUpgrades ( ) , MASK_UMBRA ) )
{
LocalizeString ( kUmbraed , theText ) ;
sprintf ( theCharArray , " %s " , theText . c_str ( ) ) ;
// Draw it
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , ( kPlayerStatusVerticalInset + 2 * kPlayerStatusStatusSpacing ) * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
// Draw blinking "webbed" message
if ( GetHasUpgrade ( this - > GetHUDUpgrades ( ) , MASK_ENSNARED ) & & ( theSecondOfLastUpdate % 2 ) )
{
LocalizeString ( kWebbed , theText ) ;
sprintf ( theCharArray , " %s " , theText . c_str ( ) ) ;
// Draw it
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , ( kPlayerStatusVerticalInset + 3 * kPlayerStatusStatusSpacing ) * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
// Draw "stunned" message (it's so fast, try not blinking it)
if ( GetHasUpgrade ( this - > GetHUDUpgrades ( ) , MASK_PLAYER_STUNNED ) /*&& (theSecondOfLastUpdate % 2)*/ )
{
LocalizeString ( kStunned , theText ) ;
sprintf ( theCharArray , " %s " , theText . c_str ( ) ) ;
// Draw it
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , ( kPlayerStatusVerticalInset + 4 * kPlayerStatusStatusSpacing ) * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
// Draw "being digested" or "digesting" message
if ( this - > GetIsBeingDigested ( ) & & ( theSecondOfLastUpdate % 2 ) )
{
LocalizeString ( kDigested , theText ) ;
sprintf ( theCharArray , " %s " , theText . c_str ( ) ) ;
// Draw it
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , ( kPlayerStatusVerticalInset + 5 * kPlayerStatusStatusSpacing ) * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
else if ( this - > GetIsDigesting ( ) & & ( theSecondOfLastUpdate % 2 ) )
{
// Look up player in progress entity
if ( ( this - > mProgressBarEntityIndex > = 1 ) & & ( this - > mProgressBarEntityIndex < = gEngfuncs . GetMaxClients ( ) ) )
{
hud_player_info_t thePlayerInfo ;
gEngfuncs . pfnGetPlayerInfo ( this - > mProgressBarEntityIndex , & thePlayerInfo ) ;
char * thePlayerName = thePlayerInfo . name ;
if ( thePlayerName )
{
LocalizeString ( kDigestingPlayer , theText ) ;
sprintf ( theCharArray , theText . c_str ( ) , thePlayerName ) ;
}
}
// Draw it
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , ( kPlayerStatusVerticalInset + 5 * kPlayerStatusStatusSpacing ) * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
// If we are in a squad, draw it on our HUD
if ( this - > mCurrentSquad > 0 )
{
string theSquadIndicator ;
if ( LocalizeString ( kSquadIndicator , theSquadIndicator ) )
{
sprintf ( theCharArray , theSquadIndicator . c_str ( ) , this - > mCurrentSquad ) ;
// Draw it
this - > DrawHudStringCentered ( kPlayerStatusHorizontalCenteredInset * ScreenWidth ( ) , ( kPlayerStatusVerticalInset + 6 * kPlayerStatusStatusSpacing ) * ScreenHeight ( ) , ScreenWidth ( ) , theCharArray , theR , theG , theB ) ;
}
}
}
// Draw the numerical effects.
if ( this - > GetIsAlive ( ) )
{
for ( NumericalInfoEffectListType : : iterator theIter = this - > mNumericalInfoEffects . begin ( ) ; theIter ! = this - > mNumericalInfoEffects . end ( ) ; theIter + + )
{
// Draw it
Vector theScreenPos ;
float theWorldPosition [ 3 ] ;
theIter - > GetPosition ( theWorldPosition ) ;
if ( AvHCUWorldToScreen ( theWorldPosition , ( float * ) & theScreenPos ) )
{
float theNormX = theScreenPos . x / ScreenWidth ( ) ;
float theNormY = theScreenPos . y / ScreenHeight ( ) ;
if ( ! this - > GetInTopDownMode ( ) | | ! this - > GetIsRegionBlockedByUI ( theNormX , theNormY ) )
{
float theNumber = theIter - > GetNumber ( ) ;
string thePrependString ( " + " ) ;
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , true , false ) ;
if ( theNumber < 0 )
{
// Red, minus for negatives
theR = 255 ;
theG = 0 ;
theB = 0 ;
// The "-" is prepended by MakeStringFromInt when negative
thePrependString = string ( " " ) ;
}
const char * thePostPendStringToTranslate = NULL ;
string thePostPendString ;
switch ( theIter - > GetEventType ( ) )
{
case kNumericalInfoResourcesEvent :
thePostPendStringToTranslate = kNumericalEventResources ;
break ;
case kNumericalInfoHealthEvent :
thePostPendStringToTranslate = kNumericalEventHealth ;
break ;
case kNumericalInfoResourcesDonatedEvent :
thePostPendStringToTranslate = kNumericalEventResourcesDonated ;
break ;
case kNumericalInfoAmmoEvent :
thePostPendStringToTranslate = kNumericalEventAmmo ;
break ;
}
if ( thePostPendStringToTranslate )
{
LocalizeString ( thePostPendStringToTranslate , thePostPendString ) ;
}
// Don't draw 0, so we can have other messages
string theNumberString ;
if ( theNumber ! = 0 )
{
theNumberString = thePrependString + MakeStringFromFloat ( theNumber ) + " " ;
}
string theDisplayString = theNumberString + thePostPendString ;
char theCharBuffer [ 512 ] ;
sprintf ( theCharBuffer , " %s " , theDisplayString . c_str ( ) ) ;
this - > DrawHudStringCentered ( theScreenPos . x , theScreenPos . y , ScreenWidth ( ) , theCharBuffer , theR , theG , theB ) ;
}
}
}
}
}
// Draw the combat HUD.
if ( this - > GetIsCombatMode ( ) )
{
// Now draw our current experience level, so people know how close they are to the next level
// Load alien resource and energy sprites
string theSpriteName = UINameToSprite ( kCombatExperienceSprite , ScreenWidth ( ) ) ;
int theExperienceSprite = Safe_SPR_Load ( theSpriteName . c_str ( ) ) ;
if ( theExperienceSprite )
{
const float kNormalizedWidth = .1f ;
const float kNormalizedYInset = .96f ;
const float kNormalizedHeight = .025f ;
const int kBaseIndex = this - > GetIsMarine ( ) ? 2 : 0 ;
// Draw full background
const int kXStart = mViewport [ 0 ] + ( .5f - kNormalizedWidth / 2.0f ) * ( mViewport [ 2 ] - mViewport [ 0 ] ) ;
const int kYStart = mViewport [ 1 ] + mViewport [ 3 ] - ( 1 - kNormalizedYInset ) * ScreenHeight ( ) ;
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
AvHSpriteDraw ( theExperienceSprite , kBaseIndex + 1 , kXStart , kYStart , kXStart + kNormalizedWidth * ScreenWidth ( ) , kYStart + kNormalizedHeight * ScreenHeight ( ) , 0 , 0 , 1 , 1 ) ;
// Draw overlay showing amount of experience
float thePercentToNextLevel = AvHPlayerUpgrade : : GetPercentToNextLevel ( this - > GetHUDExperience ( ) ) ;
if ( ( thePercentToNextLevel > = 0.0f ) & & ( thePercentToNextLevel < = 1.0f ) )
{
AvHSpriteDraw ( theExperienceSprite , kBaseIndex , kXStart , kYStart , kXStart + thePercentToNextLevel * kNormalizedWidth * ScreenWidth ( ) , kYStart + kNormalizedHeight * ScreenHeight ( ) , 0 , 0 , thePercentToNextLevel , 1.0f ) ;
}
}
if ( this - > GetIsAlive ( false ) )
{
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , false , false ) ;
this - > mCombatUpgradeMenu . SetR ( theR ) ;
this - > mCombatUpgradeMenu . SetG ( theG ) ;
this - > mCombatUpgradeMenu . SetB ( theB ) ;
this - > mCombatUpgradeMenu . Draw ( ) ;
}
}
// Draw top down help
if ( this - > GetInTopDownMode ( ) )
{
this - > mTopDownActionButtonHelp . Draw ( ) ;
}
}
void AvHHud : : RenderMiniMap ( int inX , int inY , int inWidth , int inHeight )
{
AvHOverviewMap & theOverviewMap = gHUD . GetOverviewMap ( ) ;
AvHOverviewMap : : DrawInfo theDrawInfo ;
theDrawInfo . mX = inX ;
theDrawInfo . mY = inY ;
theDrawInfo . mWidth = inWidth ;
theDrawInfo . mHeight = inHeight ;
theDrawInfo . mFullScreen = false ;
float worldViewWidth = 800.0f ;
float aspectRatio = ( float ) ( theDrawInfo . mHeight ) / theDrawInfo . mWidth ;
float thePlayerX ;
float thePlayerY ;
theOverviewMap . GetWorldPosition ( thePlayerX , thePlayerY ) ;
theDrawInfo . mViewWorldMinX = thePlayerX - worldViewWidth ;
theDrawInfo . mViewWorldMinY = thePlayerY - worldViewWidth * aspectRatio ;
theDrawInfo . mViewWorldMaxX = thePlayerX + worldViewWidth ;
theDrawInfo . mViewWorldMaxY = thePlayerY + worldViewWidth * aspectRatio ;
theOverviewMap . Draw ( theDrawInfo ) ;
}
void AvHHud : : RenderMarineUI ( )
{
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , false , false ) ;
if ( mMarineTopSprite & & ( this - > mMapMode = = MAP_MODE_NS ) )
{
float theX ;
float theY ;
float theWidth = .75f * ScreenWidth ( ) ;
float theHeight = ( ( float ) 256 / 768 ) * ScreenHeight ( ) ;
AvHSpriteSetRenderMode ( kRenderTransAdd ) ;
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteDrawTiles ( mMarineTopSprite , 3 , 1 , mViewport [ 2 ] - theWidth + mViewport [ 0 ] ,
mViewport [ 1 ] , mViewport [ 2 ] + mViewport [ 0 ] , mViewport [ 1 ] + theHeight , 0 , 0 , 1 , 1 ) ;
// Draw the minimap.
int theMiniMapX = mViewport [ 2 ] - 0.21f * ScreenWidth ( ) + mViewport [ 0 ] ;
int theMiniMapY = mViewport [ 1 ] + 0.013 * ScreenHeight ( ) ;
int theMiniMapWidth = 0.200 * ScreenWidth ( ) ;
int theMiniMapHeight = 0.202 * ScreenHeight ( ) ;
RenderMiniMap ( theMiniMapX , theMiniMapY , theMiniMapWidth , theMiniMapHeight ) ;
// Draw the resource label.
theHeight = ScreenHeight ( ) * 0.038 ;
std : : string theResourceText ;
char theResourceBuffer [ 64 ] ;
LocalizeString ( kMarineResourcePrefix , theResourceText ) ;
_snprintf ( theResourceBuffer , 64 , " %s %d " , theResourceText . c_str ( ) , this - > mVisualResources ) ;
theX = mViewport [ 0 ] + 0.3 * ScreenWidth ( ) ;
theY = mViewport [ 1 ] + 0.007 * ScreenHeight ( ) + ( theHeight - GetSmallFont ( ) . GetStringHeight ( ) ) / 2 ;
GetSmallFont ( ) . DrawString ( theX , theY , theResourceBuffer , theR , theG , theB ) ;
// Draw the commander status label.
std : : string theCommanderName ;
bool theCommanderNameVisible = true ;
if ( ! GetCommanderLabelText ( theCommanderName ) )
{
// Blink if there is no commander.
if ( ( int ) this - > mTimeOfLastUpdate % 2 )
{
theCommanderNameVisible = false ;
}
}
if ( theCommanderNameVisible )
{
theX = mViewport [ 0 ] + 0.50 * ScreenWidth ( ) ;
theY = mViewport [ 1 ] + 0.006 * ScreenHeight ( ) + ( theHeight - GetSmallFont ( ) . GetStringHeight ( ) ) / 2 ;
GetSmallFont ( ) . DrawString ( theX , theY , theCommanderName . c_str ( ) , theR , theG , theB ) ;
}
}
AvHSpriteEnableClippingRect ( false ) ;
// TODO: Draw various marine upgrades (assumes 256x256 sprite, with each upgrade being 64x64, listed right to left, top to bottom, armor upgrades first,
// weapon upgrades next, then motion-tracking, then jetpacks, then exoskeleton)
// Do we have a jetpack?
if ( GetHasUpgrade ( this - > GetHUDUpgrades ( ) , MASK_UPGRADE_7 ) )
{
// Draw jetpack energy indicator
if ( this - > mMarineUIJetpackSprite )
{
float theFactor = 1 - pmove - > fuser3 / kNormalizationNetworkFactor ;
int theFrame = 0 ;
string theOutputMessage ;
if ( LocalizeString ( kJetpackEnergyHUDText , theOutputMessage ) )
{
float theX = .9f * ScreenWidth ( ) ;
float theY = .8f * ScreenHeight ( ) ;
float theWidth = .02f * ScreenWidth ( ) ;
float theHeight = .1f * ScreenHeight ( ) ;
AvHSpriteSetRenderMode ( kRenderTransAdd ) ;
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteDraw ( mMarineUIJetpackSprite , 0 , theX , theY , theX + theWidth , theY + theHeight * theFactor , 0 , 0 , 1 , theFactor ) ;
AvHSpriteDraw ( mMarineUIJetpackSprite , 1 , theX , theY + theHeight * theFactor , theX + theWidth , theY + theHeight , 0 , theFactor , 1 , 1 ) ;
}
}
}
const int kNumUpgradesToDraw = 4 ;
AvHUpgradeMask kUpgradeToMaskTable [ kNumUpgradesToDraw ] = { MASK_UPGRADE_4 , MASK_UPGRADE_1 , MASK_UPGRADE_8 , MASK_UPGRADE_7 } ;
const float kAspectRatio = ScreenWidth ( ) / ScreenHeight ( ) ;
const float kNormalizedSpacing = 0.01f ;
const int kBaseRightOffset = kNormalizedSpacing * ScreenWidth ( ) ;
const int kVerticalUpgradeSpacing = kNormalizedSpacing * kAspectRatio * ScreenHeight ( ) ;
int theUpgradeVar = this - > GetHUDUpgrades ( ) ;
const int kUpgradeFrame = 0 ;
const float kUpgradeSize = 0.05 ;
int theUpgradeWidth = kUpgradeSize * ScreenWidth ( ) ;
int theUpgradeHeight = kUpgradeSize * kAspectRatio * ScreenHeight ( ) ;
for ( int i = 0 ; i < kNumUpgradesToDraw ; i + + )
{
AvHUpgradeMask theUpgradeMask = kUpgradeToMaskTable [ i ] ;
// Draw highest ammo upgrade level
if ( theUpgradeMask = = MASK_UPGRADE_4 )
{
if ( GetHasUpgrade ( theUpgradeVar , MASK_UPGRADE_5 ) )
{
theUpgradeMask = MASK_UPGRADE_5 ;
if ( GetHasUpgrade ( theUpgradeVar , MASK_UPGRADE_6 ) )
{
theUpgradeMask = MASK_UPGRADE_6 ;
}
}
}
// Draw highest armor level
if ( theUpgradeMask = = MASK_UPGRADE_1 )
{
if ( GetHasUpgrade ( theUpgradeVar , MASK_UPGRADE_2 ) )
{
theUpgradeMask = MASK_UPGRADE_2 ;
if ( GetHasUpgrade ( theUpgradeVar , MASK_UPGRADE_3 ) )
{
theUpgradeMask = MASK_UPGRADE_3 ;
}
}
}
// Draw heavy armor instead of jetpacks if they have it
if ( theUpgradeMask = = MASK_UPGRADE_7 )
{
if ( GetHasUpgrade ( theUpgradeVar , MASK_UPGRADE_13 ) )
{
theUpgradeMask = MASK_UPGRADE_13 ;
}
}
if ( GetHasUpgrade ( theUpgradeVar , theUpgradeMask ) )
{
int theFrame = 0 ;
switch ( theUpgradeMask )
{
case MASK_UPGRADE_4 :
theFrame = 0 ;
break ;
case MASK_UPGRADE_5 :
theFrame = 1 ;
break ;
case MASK_UPGRADE_6 :
theFrame = 2 ;
break ;
case MASK_UPGRADE_1 :
theFrame = 3 ;
break ;
case MASK_UPGRADE_2 :
theFrame = 4 ;
break ;
case MASK_UPGRADE_3 :
theFrame = 5 ;
break ;
case MASK_UPGRADE_8 :
theFrame = 6 ;
break ;
case MASK_UPGRADE_7 :
theFrame = 7 ;
break ;
case MASK_UPGRADE_13 :
theFrame = 8 ;
break ;
}
float theStartU = ( theFrame % 4 ) * .25f ;
float theStartV = ( theFrame / 4 ) * .333f ;
float theEndU = theStartU + .25f ;
float theEndV = theStartV + .333f ;
const int kBaseX = ScreenWidth ( ) - .05 * ScreenWidth ( ) ;
const int kBaseY = .75 * ScreenHeight ( ) ;
const int kIconWidth = .05 * ScreenWidth ( ) ;
const int kIconHeight = .05 * ScreenHeight ( ) ;
float x1 = kBaseX ;
float y1 = kBaseY + i * kIconHeight ;
float x2 = x1 + kIconWidth ;
float y2 = y1 + kIconHeight ;
AvHSpriteSetRenderMode ( kRenderTransAdd ) ;
AvHSpriteEnableClippingRect ( false ) ;
AvHSpriteSetColor ( 1 , 1 , 1 , this - > GetGammaSlope ( ) ) ;
AvHSpriteDraw ( mMarineUpgradesSprite , 0 , x1 , y1 , x2 , y2 , theStartU , theStartV , theEndU , theEndV ) ;
}
}
}
void AvHHud : : RenderCommanderUI ( )
{
RenderStructureRanges ( ) ;
// Draw command button
if ( this - > mCommandButtonSprite )
{
// Animate the button unless the mouse is over it (?)
int kNumFrames = 16 ; // Last frame is highlighted, first frame seems off
const float kFramesPerSecond = 10 ;
const float kCycleTime = ( 1.0f / kFramesPerSecond ) * kNumFrames ;
float theNumCycles = this - > mTimeOfLastUpdate / kCycleTime ;
int theFrame = 1 + ( theNumCycles - ( int ) theNumCycles ) * kNumFrames ;
const int kStartX = 890 ;
int theX = ( kStartX / 1024.0f ) * ScreenWidth ( ) ;
int theY = ( 525 / 768.0f ) * ScreenHeight ( ) ;
float theWidth = ( ( 1024 - kStartX ) / 1024.0f ) * ScreenWidth ( ) ;
float theHeight = ( 38 / 768.0f ) * ScreenHeight ( ) ;
float x1 = theX ;
float y1 = theY ;
float x2 = x1 + theWidth ;
float y2 = y1 + theHeight ;
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
AvHSpriteDraw ( mCommandButtonSprite , theFrame , x1 , y2 , x2 , y2 , 0 , 0 , 1 , 1 ) ;
}
// Draw "select all" button
if ( this - > mSelectAllSprite )
{
AvHTechImpulsePanel * theTechImpulsePanel = NULL ;
if ( this - > GetManager ( ) . GetVGUIComponentNamed ( kSelectAllImpulsePanel , theTechImpulsePanel ) )
{
if ( theTechImpulsePanel - > isVisible ( ) )
{
int theX , theY ;
theTechImpulsePanel - > getPos ( theX , theY ) ;
int theWidth , theHeight ;
theTechImpulsePanel - > getSize ( theWidth , theHeight ) ;
// Draw unhighlighted, highlighted, or active
int theFrame = 0 ;
// If mouse is over, use frame 1
if ( this - > GetIsMouseInRegion ( theX , theY , theWidth , theHeight ) )
{
theFrame = 1 ;
}
// If all troops selected, use frame 2
if ( ( this - > mSelected . size ( ) ) > 0 & & ( this - > mSelected = = this - > mSelectAllGroup ) )
{
theFrame = 2 ;
}
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
AvHSpriteDraw ( mSelectAllSprite , theFrame , theX , theY , theX + theWidth , theY + theHeight , 0 , 0 , 1 , 1 ) ;
}
}
}
// Draw blinking "under attack" indicator
if ( this - > mCommandStatusSprite )
{
int theFrame = 0 ;
int theX = ( 725 / 1024.0f ) * ScreenWidth ( ) ;
int theY = ( 702 / 768.0f ) * ScreenHeight ( ) ;
float theWidth = ( 61.5f / 1024.0f ) * ScreenWidth ( ) ;
float theHeight = ( 66 / 768.0f ) * ScreenHeight ( ) ;
// Blink button when an alert is set!
if ( this - > mBlinkingAlertType )
{
int theSecondOfLastUpdate = ( int ) this - > mTimeOfLastUpdate ;
if ( theSecondOfLastUpdate % 2 )
{
theFrame = this - > mBlinkingAlertType ;
}
}
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
AvHSpriteDraw ( mCommandStatusSprite , theFrame , theX , theY , theX + theWidth , theY + theHeight , 0 , 0 , 1 , 1 ) ;
}
if ( this - > mTopDownTopSprite )
{
float theHeight = ( ( float ) 128 / 768 ) * ScreenHeight ( ) ;
AvHSpriteDrawTiles ( mTopDownTopSprite , 4 , 1 , 0 , 0 , ScreenWidth ( ) , theHeight , 0 , 0 , 1 , 1 ) ;
}
if ( this - > mTopDownBottomSprite )
{
// The artwork is three 128s high
float theHeight = ( ( float ) 256 / 768 ) * ScreenHeight ( ) ;
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
AvHSpriteDrawTiles ( mTopDownBottomSprite , 4 , 1 , 0 , ScreenHeight ( ) - theHeight , ScreenWidth ( ) , ScreenHeight ( ) , 0 , 0 , 1 , 1 ) ;
}
// Draw scaled sprites for all ActionButtons
this - > DrawActionButtons ( ) ;
// Draw hotgroups
this - > DrawHotgroups ( ) ;
// Draw pending requests
this - > DrawPendingRequests ( ) ;
// Draw logout button
if ( this - > mLogoutSprite )
{
int theFrame = 0 ;
int theX = .785 * ScreenWidth ( ) ;
int theY = .013 * ScreenHeight ( ) ;
float theWidth = .197f * ScreenWidth ( ) ;
float theHeight = .083f * ScreenHeight ( ) ;
// Detect mouseover
if ( this - > GetIsMouseInRegion ( theX , theY , theWidth , theHeight ) )
{
theFrame = 1 ;
}
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
AvHSpriteDraw ( mLogoutSprite , theFrame , theX , theY , theX + theWidth , theY + theHeight , 0 , 0 , 1 , 1 ) ;
}
}
void AvHHud : : RenderStructureRanges ( )
{
float theRangeR = 0 ;
float theRangeG = 1 ;
float theRangeB = 0 ;
float theRangeA = 0.2f ;
// Draw range for current ghost building, if applicable
EntityListType theEntities ;
IntList theDistanceRequirements ;
float theZAdjustment = 0.0f ;
bool theSnapToLocation = false ;
bool theDrewGhostRegions = false ;
AvHSHUGetBuildRegions ( this - > mGhostBuilding , theEntities , theDistanceRequirements , theZAdjustment , theSnapToLocation ) ;
// For each entity to draw
int theDistanceCounter = 0 ;
for ( EntityListType : : iterator theRangeIter = theEntities . begin ( ) ; theRangeIter ! = theEntities . end ( ) ; theRangeIter + + , theDistanceCounter + + )
{
//cl_entity_s* theEntity = gEngfuncs.GetEntityByIndex(*theRangeIter);
physent_t * theEntity = gEngfuncs . pEventAPI - > EV_GetPhysent ( * theRangeIter ) ;
if ( theEntity )
{
vec3_t thePosition ;
thePosition = AvHSHUGetRealLocation ( theEntity - > origin , theEntity - > mins , theEntity - > maxs ) ;
//int theSprite = (theEntity->iuser3 == AVH_USER3_SIEGETURRET) ? this->mSiegeTurretSprite : this->mBuildCircleSprite;
int theSprite = this - > mBuildCircleSprite ;
int theDistanceRequirement = theDistanceRequirements [ theDistanceCounter ] ;
RenderStructureRange ( thePosition , theDistanceRequirement , theSprite , kRenderTransAdd , 0 , theRangeR , theRangeG , theRangeB , theRangeA ) ;
theDrewGhostRegions = true ;
}
}
// Draw selection as well
for ( EntityListType : : iterator theSelectedIter = this - > mSelected . begin ( ) ; theSelectedIter ! = this - > mSelected . end ( ) ; theSelectedIter + + )
{
cl_entity_s * theEntity = gEngfuncs . GetEntityByIndex ( * theSelectedIter ) ;
//physent_t* theEntity = gEngfuncs.pEventAPI->EV_GetPhysent(*theSelectedIter);
if ( theEntity )
{
vec3_t thePosition ;
thePosition = AvHSHUGetRealLocation ( theEntity - > curstate . origin , theEntity - > curstate . mins , theEntity - > curstate . maxs ) ;
AvHUser3 theUser3 = ( AvHUser3 ) ( theEntity - > curstate . iuser3 ) ;
int theRange = AvHSHUGetDrawRangeForUser3 ( theUser3 ) ;
if ( theRange > 0 )
{
// Don't draw structures that are recycling and therefore inactive
if ( ! GetHasUpgrade ( theEntity - > curstate . iuser4 , MASK_RECYCLING ) )
{
//int theSprite = (theEntity->curstate.iuser3 == AVH_USER3_SIEGETURRET) ? this->mSiegeTurretSprite : this->mBuildCircleSprite;
int theSprite = this - > mBuildCircleSprite ;
RenderStructureRange ( thePosition , theRange , theSprite , kRenderTransAdd , 0 , theRangeR , theRangeG , theRangeB , theRangeA ) ;
}
}
}
}
// Draw the minimum build radius violations.
EntityListType theBuildViolations ;
AvHSHUGetMinBuildRadiusViolations ( mGhostBuilding , mGhostWorldLocation , theBuildViolations ) ;
2005-04-01 03:04:57 +00:00
for ( EntityListType : : iterator theBuildViolationsIter = theBuildViolations . begin ( ) ; theBuildViolationsIter ! = theBuildViolations . end ( ) ; + + theBuildViolationsIter )
2005-03-09 01:31:56 +00:00
{
gEngfuncs . pEventAPI - > EV_SetUpPlayerPrediction ( false , true ) ;
// Store off the old count
gEngfuncs . pEventAPI - > EV_PushPMStates ( ) ;
// Now add in all of the players.
gEngfuncs . pEventAPI - > EV_SetSolidPlayers ( - 1 ) ;
physent_t * theEntity = gEngfuncs . pEventAPI - > EV_GetPhysent ( * theBuildViolationsIter ) ;
gEngfuncs . pEventAPI - > EV_PopPMStates ( ) ;
if ( theEntity )
{
vec3_t thePosition ;
thePosition = AvHSHUGetRealLocation ( theEntity - > origin , theEntity - > mins , theEntity - > maxs ) ;
AvHUser3 theUser3 = ( AvHUser3 ) ( theEntity - > iuser3 ) ;
vec3_t theMinSize , theMaxSize ;
AvHSHUGetSizeForUser3 ( theUser3 , theMinSize , theMaxSize ) ;
float theMaxRadius2 = max ( max ( theMinSize . x , theMaxSize . x ) , max ( theMinSize . y , theMaxSize . y ) ) ;
int theSprite = this - > mBuildCircleSprite ;
// joev: 0000291
// It's possible to place "on" marines if you're offset a little from center. This code and
// associated changes above and in AvHSharedUtil.cpp is to enforce a build distance around marines,
// in the same way as structures, to prevent this exploit.
float theMinMarineBuildDistance ;
if ( theUser3 = = AVH_USER3_MARINE_PLAYER ) {
2005-04-01 03:04:57 +00:00
theMinMarineBuildDistance = BALANCE_VAR ( kMinMarinePlayerBuildDistance ) ;
2005-03-09 01:31:56 +00:00
}
else
{
2005-04-01 03:04:57 +00:00
theMinMarineBuildDistance = BALANCE_VAR ( kMinMarineBuildDistance ) ;
2005-03-09 01:31:56 +00:00
}
// :joev
RenderStructureRange ( thePosition , theMinMarineBuildDistance + theMaxRadius2 , theSprite , kRenderTransAdd , 0 , 1 , 0 , 0 , 0.3f ) ;
}
}
}
void AvHHud : : RenderStructureRange ( vec3_t inOrigin , int inRadius , HSPRITE inSprite , int inRenderMode , int inFrame , float inR , float inG , float inB , float inAlpha )
{
vec3_t w1 ;
w1 [ 0 ] = inOrigin [ 0 ] - inRadius ;
w1 [ 1 ] = inOrigin [ 1 ] - inRadius ;
w1 [ 2 ] = inOrigin [ 2 ] ;
vec3_t s1 ;
gEngfuncs . pTriAPI - > WorldToScreen ( w1 , s1 ) ;
vec3_t w2 ;
w2 [ 0 ] = inOrigin [ 0 ] + inRadius ;
w2 [ 1 ] = inOrigin [ 1 ] + inRadius ;
w2 [ 2 ] = inOrigin [ 2 ] ;
vec3_t s2 ;
gEngfuncs . pTriAPI - > WorldToScreen ( w2 , s2 ) ;
float x1 = XPROJECT ( s1 [ 0 ] ) ;
float y1 = YPROJECT ( s1 [ 1 ] ) ;
float x2 = XPROJECT ( s2 [ 0 ] ) ;
float y2 = YPROJECT ( s2 [ 1 ] ) ;
AvHSpriteSetColor ( inR , inG , inB , inAlpha ) ;
AvHSpriteSetRenderMode ( inRenderMode ) ;
AvHSpriteDraw ( inSprite , inFrame , x1 , y1 , x2 , y2 , 0 , 0 , 1 , 1 ) ;
AvHSpriteSetColor ( 1 , 1 , 1 , 1 ) ;
}
void AvHHud : : RenderAlienUI ( )
{
const float kAspectRatio = ScreenWidth ( ) / ScreenHeight ( ) ;
// Draw the embryo overlay if the player is gestating.
if ( GetHUDUser3 ( ) = = AVH_USER3_ALIEN_EMBRYO )
{
if ( mMembraneSprite )
{
AvHSpriteSetRenderMode ( kRenderTransAdd ) ;
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
DrawWarpedOverlaySprite ( mMembraneSprite , 4 , 3 , .007 * 2 , .002 * 2 , .15 , .3 ) ;
}
return ;
}
AvHSpriteSetRenderMode ( kRenderTransAlpha ) ;
int theWidth = kResourceEnergyBarWidth * ScreenWidth ( ) ;
int theHeight = kResourceEnergyBarHeight * ScreenHeight ( ) ;
int theX = mViewport [ 0 ] ;
int theY = mViewport [ 3 ] - theHeight + mViewport [ 1 ] ;
// Draw resource text label.
if ( ! mSteamUIActive )
{
const float kTextInset = kResourceEnergyBarWidth * .5f ;
const int kNumericYOffset = 1.5 * this - > GetHudStringHeight ( ) ;
int theResourceLabelX = mViewport [ 0 ] + kTextInset * ScreenWidth ( ) ;
int theResourceLabelY = theY - + .05f * ScreenHeight ( ) ;
if ( this - > mMapMode = = MAP_MODE_NS )
{
string theLocalizedResourceDescription ;
if ( LocalizeString ( kAlienResourcePrefix , theLocalizedResourceDescription ) )
{
int theStringWidth = this - > GetHudStringWidth ( theLocalizedResourceDescription . c_str ( ) ) ;
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , false , false ) ;
this - > DrawHudString ( theResourceLabelX , theResourceLabelY , ScreenWidth ( ) , theLocalizedResourceDescription . c_str ( ) , theR , theG , theB ) ;
}
// Draw amount we have
char theBuffer [ 128 ] ;
sprintf ( theBuffer , " (%d/%d) " , this - > mVisualResources , this - > GetMaxAlienResources ( ) ) ;
this - > DrawTranslatedString ( theResourceLabelX , theResourceLabelY + kNumericYOffset , theBuffer ) ;
}
}
// Draw energy bar.
if ( mAlienUIEnergySprite )
{
theX = mViewport [ 2 ] - theWidth + mViewport [ 0 ] ;
float theFactor = 1 - this - > mVisualEnergyLevel ;
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteSetRenderMode ( kRenderTransTexture ) ;
AvHSpriteDraw ( mAlienUIEnergySprite , 0 , theX , theY , theX + theWidth , theY + theHeight * theFactor , 0 , 0 , 1 , theFactor ) ;
AvHSpriteDraw ( mAlienUIEnergySprite , 1 , theX , theY + theHeight * theFactor , theX + theWidth , theY + theHeight , 0 , theFactor , 1 , 1 ) ;
}
// Draw hive indicators.
if ( mHiveInfoSprite ) // && (this->mMapMode == MAP_MODE_NS)) // removed check to enable hive with health to be shown in combat
{
int theHiveIndex = 0 ;
for ( HiveInfoListType : : iterator theIter = this - > mHiveInfoList . begin ( ) ; theIter ! = this - > mHiveInfoList . end ( ) ; theIter + + , theHiveIndex + + )
{
// For this hive, figure out which frame to draw
int theFrame = theIter - > mStatus ;
// If under attack, make it blink red
int theSecondOfLastUpdate = ( int ) this - > mTimeOfLastUpdate ;
if ( theIter - > mUnderAttack & & ( theSecondOfLastUpdate % 2 ) )
{
theFrame = kHiveInfoStatusUnderAttack ;
}
int theHiveWidth = kHiveNormScreenWidth * ScreenWidth ( ) ;
// Draw hive
//float theNormX = theHiveWidth;
float theNormY = kHiveNormScreenY + kHiveNormScreenVerticalSpacing * theHiveIndex ;
//DrawScaledHUDSprite(this->mHiveInfoSprite, kRenderTransAlpha, 1, theNormX*ScreenWidth, theNormY*ScreenHeight(), kHiveNormScreenWidth*ScreenWidth, kHiveNormScreenHeight*ScreenHeight(), theFrame);
float x1 = mViewport [ 0 ] + mViewport [ 2 ] - theHiveWidth ;
float y1 = mViewport [ 1 ] + theNormY * ScreenHeight ( ) ;
float x2 = x1 + theHiveWidth ;
float y2 = y1 + kHiveNormScreenHeight * ScreenHeight ( ) ;
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteSetRenderMode ( kRenderTransTexture ) ;
AvHSpriteDraw ( mHiveInfoSprite , theFrame , x1 , y1 , x2 , y2 , 0 , 0 , 1 , 1 ) ;
// AvHSpriteSetColor(1,1,1);
// AvHSpriteSetRenderMode(kRenderTransTexture);
// AvHSpriteDraw(mHiveHealthSprite, 0, x1, y1, x1+100, y1+100, 0, 0, 1, 1);
// use the hive sprite height for the hivehealth sprite height and width
float theHealthSpriteHeight = ( float ) ( kHiveNormScreenHeight ) * ScreenHeight ( ) ;
float theHealthSpriteWidth = theHealthSpriteHeight ;
AvHSpriteSetColor ( 1 , 1 , 1 ) ;
AvHSpriteSetRenderMode ( kRenderTransTexture ) ;
// adjust the position for the sprite -- to the left
float w1 = mViewport [ 0 ] + mViewport [ 2 ] - ( kHiveNormScreenWidth + 0.02f ) * ScreenWidth ( ) ;
AvHSpriteDraw ( mHiveHealthSprite , 0 , w1 , y1 , w1 + theHealthSpriteWidth , y1 + theHealthSpriteHeight , 0 , 0 , 1 , 1 ) ;
if ( theIter - > mStatus > 0 ) {
if ( theIter - > mHealthPercentage < 100 ) {
AvHSpriteDraw ( mHiveHealthSprite , 0 , w1 , y1 , w1 + theHealthSpriteWidth , y1 + theHealthSpriteHeight , 0 , 0 , 1 , 1 ) ;
AvHSpriteDraw ( mHiveHealthSprite , 1 ,
w1 , y1 + theHealthSpriteHeight - theHealthSpriteHeight * ( ( float ) ( theIter - > mHealthPercentage ) * 0.92f / 100 ) ,
w1 + theHealthSpriteWidth , y1 + theHealthSpriteHeight ,
0 , 1 - ( ( float ) ( theIter - > mHealthPercentage ) * 0.92f / 100 ) ,
1 , 1 ) ;
} else {
AvHSpriteDraw ( mHiveHealthSprite , 1 , w1 , y1 , w1 + theHealthSpriteWidth , y1 + theHealthSpriteHeight , 0 , 0 , 1 , 1 ) ;
}
}
// Draw technology it's supporting
AvHMessageID theTechnology = ( AvHMessageID ) theIter - > mTechnology ;
theFrame = - 1 ;
switch ( theTechnology )
{
case ALIEN_BUILD_DEFENSE_CHAMBER :
theFrame = 0 ;
break ;
case ALIEN_BUILD_SENSORY_CHAMBER :
theFrame = 3 ;
break ;
case ALIEN_BUILD_MOVEMENT_CHAMBER :
theFrame = 2 ;
break ;
}
// Draw it inset
if ( theFrame > = 0 )
{
float x1 = mViewport [ 0 ] + mViewport [ 2 ] - theHiveWidth + ( kHiveTechnologyInsetXScalar * kHiveNormScreenWidth ) * ScreenWidth ( ) ;
float y1 = mViewport [ 1 ] + ( theNormY + kHiveTechnologyInsetYScalar * kHiveNormScreenHeight ) * ScreenHeight ( ) ;
float x2 = x1 + kHiveTechnologyInsetWidthScalar * kHiveNormScreenWidth * ScreenWidth ( ) ;
float y2 = y1 + kHiveTechnologyInsetHeightScalar * kHiveNormScreenHeight * ScreenHeight ( ) ;
AvHSpriteDraw ( mAlienUIUpgradeCategories , theFrame , x1 , y1 , x2 , y2 , 0 , 0 , 1 , 1 ) ;
}
}
}
// Draw the upgrades.
const int kNumberXInset = 2 ;
const int kNumberYInset = 2 ;
const int kBaseYOffset = .1 * ScreenHeight ( ) ;
// Now draw alien upgrades
const float kNormalizedSpacing = 0.01f ;
const int kBaseRightOffset = kNormalizedSpacing * ScreenWidth ( ) ;
const int kVerticalUpgradeSpacing = kNormalizedSpacing * kAspectRatio * ScreenHeight ( ) ;
int theUpgradeVar = this - > GetHUDUpgrades ( ) ;
const int kUpgradeFrame = 0 ;
const float kUpgradeSize = 0.05 ;
int theUpgradeWidth = kUpgradeSize * ScreenWidth ( ) ;
int theUpgradeHeight = kUpgradeSize * kAspectRatio * ScreenHeight ( ) ;
// In Combat mode, we can have multiple upgrades in each category
int theNumDrawnInCategory [ ALIEN_UPGRADE_CATEGORY_MAX_PLUS_ONE + 1 ] ;
memset ( theNumDrawnInCategory , 0 , sizeof ( int ) * ( ALIEN_UPGRADE_CATEGORY_MAX_PLUS_ONE + 1 ) ) ;
AvHUpgradeMask theUpgradeMasks [ kNumAlienUpgrades ] = { MASK_UPGRADE_1 , MASK_UPGRADE_2 , MASK_UPGRADE_3 , MASK_NONE , MASK_NONE , MASK_NONE , MASK_UPGRADE_4 , MASK_UPGRADE_5 , MASK_UPGRADE_6 , MASK_UPGRADE_7 , MASK_UPGRADE_8 , MASK_UPGRADE_9 } ;
for ( int i = 0 ; i < kNumAlienUpgrades ; i + + )
{
AvHUpgradeMask theUpgradeMask = theUpgradeMasks [ i ] ;
AvHAlienUpgradeCategory theCategory = ALIEN_UPGRADE_CATEGORY_INVALID ;
AvHGetAlienUpgradeCategoryFromMask ( theUpgradeMask , theCategory ) ;
int theCategoryNumber = ( int ) theCategory ;
//int theRowNumber = i % (kNumAlienUpgrades/kNumAlienUpgradeCategories);
// Quick hack: treat defense as offense for drawing purposes, because offense has been (temporarily?) removed
int theCategoryNumberOffset = ( int ) ( ( ( theCategory = = ALIEN_UPGRADE_CATEGORY_DEFENSE ) ? ALIEN_UPGRADE_CATEGORY_OFFENSE : theCategory ) ) ;
int theX = ScreenWidth ( ) - theUpgradeWidth - kBaseRightOffset ;
// Inset drawing of multiple upgrades in same category (needed for Combat mode)
theX - = ( theNumDrawnInCategory [ theCategory ] * theUpgradeWidth ) ;
int theEnergyHeight = kResourceEnergyBarHeight * ScreenHeight ( ) ;
int theY = ( 3 * kHiveNormScreenVerticalSpacing ) * ScreenHeight ( ) + kVerticalUpgradeSpacing + theCategoryNumberOffset * ( kVerticalUpgradeSpacing + theUpgradeHeight ) ;
if ( GetHasUpgrade ( theUpgradeVar , theUpgradeMask ) )
{
theNumDrawnInCategory [ theCategory ] + + ;
int theLevelOfUpgrade = AvHGetAlienUpgradeLevel ( theUpgradeVar , theUpgradeMask ) ;
for ( int theLevel = 0 ; theLevel < theLevelOfUpgrade ; theLevel + + )
{
// Draw them slightly overlapping
const float kOffset = .01f ;
float x1 = theX - theLevel * ( kOffset * ScreenWidth ( ) ) ;
float y1 = theY - theLevel * ( kOffset * ScreenHeight ( ) ) ;
float x2 = x1 + theUpgradeWidth ;
float y2 = y1 + theUpgradeHeight ;
AvHSpriteDraw ( mAlienUIUpgrades , i , x1 , y1 , x2 , y2 , 0 , 0 , 1 , 1 ) ;
}
}
else
{
if ( this - > GetGameStarted ( ) & & ! this - > GetIsCombatMode ( ) )
{
// If upgrade is pending, draw it blinking
for ( int i = 0 ; i < this - > mNumUpgradesAvailable ; i + + )
{
if ( this - > mCurrentUpgradeCategory [ i ] = = theCategory )
{
int theSecondOfLastUpdate = ( int ) this - > mTimeOfLastUpdate ;
if ( theSecondOfLastUpdate % 2 )
{
int theFrame = theCategory - 1 ;
float x1 = theX ;
float y1 = theY ;
float x2 = x1 + theUpgradeWidth ;
float y2 = y1 + theUpgradeHeight ;
AvHSpriteDraw ( mAlienUIUpgradeCategories , theFrame , x1 , y1 , x2 , y2 , 0 , 0 , 1 , 1 ) ;
}
break ;
}
}
}
}
}
if ( this - > GetIsAlien ( ) & & ( this - > GetHUDTeam ( ) ! = TEAM_IND ) )
{
bool theIsGestating = ( this - > GetHUDUser3 ( ) = = AVH_USER3_ALIEN_EMBRYO ) ;
bool theIsBeingDigested = this - > GetIsBeingDigested ( ) ;
this - > mSelectedNodeResourceCost = - 1 ;
// Find the blip nearest our view reticle
int theNearestBlip = - 1 ;
float theDotProductOfClosestBlip = - 1 ;
// Get view vector
Vector theViewVector ;
vec3_t theForward , theRight , theUp ;
AngleVectors ( v_angles , theForward , theRight , theUp ) ;
VectorNormalize ( theForward ) ;
for ( int theBlip = 0 ; theBlip < this - > mFriendlyBlips . mNumBlips ; theBlip + + )
{
// Get vector to current blip
Vector theVectorToBlip ;
VectorSubtract ( this - > mFriendlyBlips . mBlipPositions [ theBlip ] , gPredictedPlayerOrigin , theVectorToBlip ) ;
VectorNormalize ( theVectorToBlip ) ;
// Dot them
float theDotProduct = DotProduct ( theForward , theVectorToBlip ) ;
// Is dot product closer to 1 then best?
if ( theDotProduct > theDotProductOfClosestBlip )
{
// Save new blip and dot product
theNearestBlip = theBlip ;
theDotProductOfClosestBlip = theDotProduct ;
}
}
// Draw information about our friendly blips
theBlip = theNearestBlip ;
if ( theNearestBlip > = 0 )
{
ASSERT ( theNearestBlip < this - > mFriendlyBlips . mNumBlips ) ;
// Draw location when player under attack
int theBlipStatus = this - > mFriendlyBlips . mBlipStatus [ theBlip ] ;
//if((theBlipStatus == kVulnerableFriendlyBlipStatus) || ((theBlipStatus >= kSayingOne) && (theBlipStatus <= kSayingSix)))
//{
// Get location
string theLocationName = this - > GetNameOfLocation ( this - > mFriendlyBlips . mBlipPositions [ theBlip ] ) ;
// Get name of entity
string theBlipName ;
int theBlipInfo = this - > mFriendlyBlips . mBlipInfo [ theBlip ] ;
if ( theBlipInfo < = kBaseBlipInfoOffset )
{
hud_player_info_t thePlayerInfo ;
gEngfuncs . pfnGetPlayerInfo ( theBlipInfo , & thePlayerInfo ) ;
if ( thePlayerInfo . name )
{
theBlipName = thePlayerInfo . name ;
}
}
else
{
AvHUser3 theUser3 = AvHUser3 ( theBlipInfo - kBaseBlipInfoOffset ) ;
this - > GetTranslatedUser3Name ( theUser3 , theBlipName ) ;
}
string theBlipStatusText ;
char theBlipStatusString [ 512 ] ;
sprintf ( theBlipStatusString , " #%s%d " , kBlipStatusPrefix , theBlipStatus ) ;
LocalizeString ( theBlipStatusString , theBlipStatusText ) ;
Vector theScreenPos ;
Vector theMessageWorldPos = this - > mFriendlyBlips . mBlipPositions [ theBlip ] ;
const float kSpacingScalar = 1.2f ;
theMessageWorldPos . z - = ( kWorldBlipScale / 2.0f ) * kSpacingScalar ;
if ( AvHCUWorldToScreen ( theMessageWorldPos , ( float * ) & theScreenPos ) )
{
if ( ( theBlipName ! = " " ) & & ( theBlipStatusText ! = " " ) & & ( theLocationName ! = " " ) )
{
// "MonsieurEvil is under attack"
// "Resource tower is under attack"
char theFirstLine [ 512 ] ;
sprintf ( theFirstLine , " %s %s \n " , theBlipName . c_str ( ) , theBlipStatusText . c_str ( ) ) ;
this - > DrawTranslatedString ( theScreenPos [ 0 ] , theScreenPos [ 1 ] , theFirstLine , true , true ) ;
char theLocationNameCStr [ 512 ] ;
strcpy ( theLocationNameCStr , theLocationName . c_str ( ) ) ;
this - > DrawTranslatedString ( theScreenPos [ 0 ] , theScreenPos [ 1 ] + .022f * ScreenHeight ( ) , theLocationNameCStr , true , true , true ) ;
}
}
//}
}
// Draw hive locations under each hive indicator
if ( ! theIsGestating & & ! theIsBeingDigested & & ( this - > mMapMode = = MAP_MODE_NS ) )
{
int theHiveIndex = 0 ;
for ( HiveInfoListType : : iterator theIter = this - > mHiveInfoList . begin ( ) ; theIter ! = this - > mHiveInfoList . end ( ) ; theIter + + , theHiveIndex + + )
{
vec3_t theHivePosition ( theIter - > mPosX , theIter - > mPosY , theIter - > mPosZ ) ;
string theLocationName = this - > GetNameOfLocation ( theHivePosition ) ;
int theHiveWidth = kHiveNormScreenWidth * ScreenWidth ( ) ;
int theScreenPosX = mViewport [ 0 ] + mViewport [ 2 ] - theHiveWidth ;
int theScreenPosY = mViewport [ 1 ] + ( kHiveNormScreenY + theHiveIndex * kHiveNormScreenVerticalSpacing + kHiveNormScreenHeight ) * ScreenHeight ( ) ;
string theTranslatedLocationName ;
LocalizeString ( theLocationName . c_str ( ) , theTranslatedLocationName ) ;
AvHCUTrimExtraneousLocationText ( theTranslatedLocationName ) ;
int theR , theG , theB ;
this - > GetPrimaryHudColor ( theR , theG , theB , false , false ) ;
// Draw text in greyscale if hive isn't building or active
if ( theIter - > mStatus = = kHiveInfoStatusUnbuilt )
{
theR = theG = theB = 100 ;
}
this - > DrawHudStringReverse ( mViewport [ 0 ] + mViewport [ 2 ] - 5 , theScreenPosY , ScreenWidth ( ) , ( char * ) theTranslatedLocationName . c_str ( ) , theR , theG , theB ) ;
}
}
}
}
void AvHHud : : DrawWarpedOverlaySprite ( int spriteHandle , int numXFrames , int numYFrames , float inWarpXAmount , float inWarpYAmount , float inWarpXSpeed , float inWarpYSpeed )
{
float dx = ScreenWidth ( ) ;
float dy = ScreenHeight ( ) ;
float theCurrentTime = gHUD . GetTimeOfLastUpdate ( ) ;
float theNormXAmount = theCurrentTime * inWarpXSpeed - ( int ) ( theCurrentTime * inWarpXSpeed ) ; // Get fractional part of second
float theNormYAmount = theCurrentTime * inWarpYSpeed - ( int ) ( theCurrentTime * inWarpYSpeed ) ;
float theSinusoidalNormXAmount = cos ( theNormXAmount * 2.0f * M_PI ) ;
float theSinusoidalNormYAmount = sin ( theNormYAmount * 2.0f * M_PI ) ;
float theXAmount = theSinusoidalNormXAmount * inWarpXAmount ;
float theYAmount = theSinusoidalNormYAmount * inWarpYAmount ;
for ( int frameY = 0 ; frameY < numYFrames ; + + frameY )
{
for ( int frameX = 0 ; frameX < numXFrames ; + + frameX )
{
float theWarpXStartAmount = 0 ;
float theWarpYStartAmount = 0 ;
float theWarpXEndAmount = 0 ;
float theWarpYEndAmount = 0 ;
int frame = frameX + frameY * numXFrames ;
float pw = SPR_Width ( spriteHandle , frame ) ;
float ph = SPR_Height ( spriteHandle , frame ) ;
float fx1 = ( ( float ) ( frameX ) ) / numXFrames ;
float fy1 = ( ( float ) ( frameY ) ) / numYFrames ;
float fx2 = ( ( float ) ( frameX + 1 ) ) / numXFrames ;
float fy2 = ( ( float ) ( frameY + 1 ) ) / numYFrames ;
if ( frameX > 0 )
{
theWarpXStartAmount = theXAmount * ScreenWidth ( ) ;
}
if ( frameX < numXFrames - 1 )
{
theWarpXEndAmount = theXAmount * ScreenWidth ( ) ;
}
if ( frameY > 0 )
{
theWarpYStartAmount = theYAmount * ScreenHeight ( ) ;
}
if ( frameY < numYFrames - 1 )
{
theWarpYEndAmount = theYAmount * ScreenHeight ( ) ;
}
AvHSpriteDraw ( spriteHandle , frame ,
dx * fx1 + theWarpXStartAmount ,
dy * fy1 + theWarpYStartAmount ,
dx * fx2 + theWarpXEndAmount ,
dy * fy2 + theWarpYEndAmount ,
1 / pw , 1 / ph , 1 - 1 / pw , 1 - 1 / ph ) ;
}
}
}
void AvHHud : : RenderNoZBuffering ( )
{
if ( mSteamUIActive )
{
// Hack since the HUD doesn't get drawn while the Steam UI is open.
Render ( ) ;
}
// Don't draw this stuff while being digested
if ( this - > GetIsBeingDigested ( ) | | gParticleEditorHandler . GetInEditMode ( ) )
{
return ;
}
// Temporary, so we can make movies without having the UI flit around (known HL playback bug)
if ( /*gEngfuncs.pDemoAPI->IsPlayingback() ||*/ gViewPort - > IsOptionsMenuVisible ( ) )
{
return ;
}
const int theDistance = 50 ;
const float kAspectRatio = ScreenWidth ( ) / ScreenHeight ( ) ;
float m_vRenderOrigin [ 3 ] ;
pVector m_vUp ;
pVector m_vRight ;
pVector m_vNormal ;
//vec3_t theViewAngles;
//gEngfuncs.GetViewAngles((float*)theViewAngles)
//gEngfuncs.GetView
IEngineStudio . GetViewInfo ( m_vRenderOrigin , ( float * ) & m_vUp , ( float * ) & m_vRight , ( float * ) & m_vNormal ) ;
//float m_fSoftwareXScale, m_fSoftwareYScale;
//IEngineStudio.GetAliasScale( &m_fSoftwareXScale, &m_fSoftwareYScale );
//vec3_t theViewHeight;
//gEngfuncs.pEventAPI->EV_LocalPlayerViewheight(theViewHeight);
// pVector p;
// p.x = m_vRenderOrigin[0] + m_vNormal.x*theDistance;
// p.y = m_vRenderOrigin[1] + m_vNormal.y*theDistance;
// p.z = m_vRenderOrigin[2] + m_vNormal.z*theDistance;
// pVector p;
// p.x = m_vRenderOrigin[0];
// p.y = m_vRenderOrigin[1];
// p.z = m_vRenderOrigin[2];
// p.x = v_origin[0];
// p.y = v_origin[1];
// p.z = v_origin[2];
// Allow scripts to perform render
AvHScriptManager : : Instance ( ) - > DrawNoZBuffering ( ) ;
// if(cl_particleinfo->value)
// {
// // Draw particles here for debugging
// pVector theRealView;
// vec3_t angles, up, right, forward;
// gEngfuncs.pfnAngleVectors(pmove->angles, forward, right, up);
//
// theRealView.x = forward[0];
// theRealView.y = forward[1];
// theRealView.z = forward[2];
//
// AvHParticleSystemManager::Instance()->Draw(theRealView);
// }
//if(this->mMappingTechSprite && !this->mIsRenderingSelectionView && !this->mGameStarted)
//{
// float theXPercentage = 256/1024.0f;
// float theYPercentage = 64/768.0f;
// DrawScaledHUDSprite(this->mMappingTechSprite, kRenderTransColor, 1, 0, ScreenHeight/2, theXPercentage*ScreenWidth, theYPercentage*ScreenHeight());
//}
// Draw blips, orders, selection and build effects for spectators and demo watchers too
int theUpgradeVar = this - > GetHUDUpgrades ( ) ;
bool theHasHiveSightUpgrade = true ; //GetHasUpgrade(theUpgradeVar, MASK_ALIEN_UPGRADE_11);
if ( this - > GetIsAlien ( ) )
{
if ( theHasHiveSightUpgrade )
{
// Draw friendly blips
this - > mFriendlyBlips . Draw ( m_vNormal , kFriendlyBlipStatus ) ;
}
}
// Draw enemy blips
this - > mEnemyBlips . Draw ( m_vNormal , kEnemyBlipStatus ) ;
//this->DrawOrders(true);
this - > DrawSelectionAndBuildEffects ( ) ;
//this->DrawHelpIcons();
}
void AvHHud : : VidInit ( void )
{
UIHud : : VidInit ( ) ;
mOverviewMap . VidInit ( ) ;
int theScreenWidth = ScreenWidth ( ) ;
string theSpriteName ;
// theSpriteName = UINameToSprite(kEggSprite, theScreenWidth);
// this->mAlienUIEggSprite = Safe_SPR_Load(theSpriteName.c_str());
// theSpriteName = UINameToSprite(kHiveSprite, theScreenWidth);
// this->mAlienUIHiveSprite = Safe_SPR_Load(theSpriteName.c_str());
int i = 0 ;
// for(i = 0; i < kNumAlienLifeforms; i++)
// {
// char theBaseName[128];
// sprintf(theBaseName, "%s%d", kLifeformSprite, i+1);
// string theSpriteName = "sprites/level1_hud.spr";//UINameToSprite(theBaseName, theScreenWidth, true);
// this->mAlienUILifeforms[i] = Safe_SPR_Load(theSpriteName.c_str());
// }
char theBaseName [ 128 ] ;
sprintf ( theBaseName , " %s " , kAlienUpgradeSprite ) ;
theSpriteName = UINameToSprite ( theBaseName , theScreenWidth ) ;
this - > mAlienUIUpgrades = Safe_SPR_Load ( theSpriteName . c_str ( ) ) ;
sprintf ( theBaseName , " %s " , kAlienUpgradeCategory ) ;
theSpriteName = UINameToSprite ( theBaseName , theScreenWidth ) ;
this - > mAlienUIUpgradeCategories = Safe_SPR_Load ( theSpriteName . c_str ( ) ) ;
// Load jetpack sprite
theSpriteName = UINameToSprite ( kJetpackSprite , theScreenWidth ) ;
this - > mMarineUIJetpackSprite = Safe_SPR_Load ( theSpriteName . c_str ( ) ) ;
// Load alien energy sprite
theSpriteName = UINameToSprite ( kAlienEnergySprite , theScreenWidth ) ;
this - > mAlienUIEnergySprite = Safe_SPR_Load ( theSpriteName . c_str ( ) ) ;
// Load background for topdown mode
this - > mBackgroundSprite = Safe_SPR_Load ( kTopDownBGSprite ) ;
// Load HUD
this - > mTopDownTopSprite = Safe_SPR_Load ( kTopDownTopHUDSprite ) ;
this - > mTopDownBottomSprite = Safe_SPR_Load ( kTopDownBottomHUDSprite ) ;
this - > mMarineTopSprite = Safe_SPR_Load ( kMarineTopHUDSprite ) ;
this - > mLogoutSprite = Safe_SPR_Load ( kLogoutSprite ) ;
this - > mCommandButtonSprite = Safe_SPR_Load ( kCommandButtonSprite ) ;
this - > mCommandStatusSprite = Safe_SPR_Load ( kCommandStatusSprite ) ;
this - > mSelectAllSprite = Safe_SPR_Load ( kSelectAllSprite ) ;
//this->mTopDownBottomSprite = Safe_SPR_Load("sprites/distorttest.spr");
//this->mTopDownBottomSprite = Safe_SPR_Load("sprites/ns.spr");
//this->mTopDownBottomSprite = Safe_SPR_Load("sprites/distorttest.spr");
// Load overlays
this - > mMembraneSprite = Safe_SPR_Load ( kMembraneSprite ) ;
this - > mDigestingSprite = Safe_SPR_Load ( kDigestingSprite ) ;
// Load order sprite
theSpriteName = UINameToSprite ( kOrdersSprite , theScreenWidth ) ;
this - > mOrderSprite = Safe_SPR_Load ( theSpriteName . c_str ( ) ) ;
this - > mHiveInfoSprite = Safe_SPR_Load ( kHiveInfoSprite ) ;
this - > mHiveHealthSprite = Safe_SPR_Load ( kHiveHealthSprite ) ;
// Load cursor sprite
this - > mMarineCursor = Safe_SPR_Load ( kCursorsSprite ) ;
this - > mAlienCursor = Safe_SPR_Load ( kAlienCursorSprite ) ;
this - > mMarineOrderIndicator = Safe_SPR_Load ( kMarineOrderSprite ) ;
this - > mMarineUpgradesSprite = Safe_SPR_Load ( kMarineUpgradesSprite ) ;
//this->mMappingTechSprite = Safe_SPR_Load("sprites/ns.spr");
this - > mAlienBuildSprite = Safe_SPR_Load ( kAlienBuildSprite ) ;
this - > mMarineBuildSprite = Safe_SPR_Load ( kMarineBuildSprite ) ;
this - > mAlienHealthSprite = Safe_SPR_Load ( kAlienHealthSprite ) ;
this - > mMarineHealthSprite = Safe_SPR_Load ( kMarineHealthSprite ) ;
this - > mBuildCircleSprite = Safe_SPR_Load ( kBuildCircleSprite ) ;
//this->mSiegeTurretSprite = Safe_SPR_Load(kSiegeTurretSprite);
this - > mActionButtonSprites . clear ( ) ;
//this->mHelpSprites.clear();
string theIconName = string ( kHelpIconPrefix ) + " .spr " ;
this - > mHelpSprite = Safe_SPR_Load ( theIconName . c_str ( ) ) ;
this - > mEnemyBlips . VidInit ( ) ;
this - > mFriendlyBlips . VidInit ( ) ;
}