mirror of
https://github.com/celisej567/source-engine.git
synced 2026-01-04 18:09:53 +03:00
1
This commit is contained in:
461
game/client/hl2/hud_damageindicator.cpp
Normal file
461
game/client/hl2/hud_damageindicator.cpp
Normal file
@@ -0,0 +1,461 @@
|
||||
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||||
//
|
||||
// Purpose:
|
||||
//
|
||||
//=============================================================================//
|
||||
|
||||
#include "cbase.h"
|
||||
#include "hud.h"
|
||||
#include "text_message.h"
|
||||
#include "hud_macros.h"
|
||||
#include "iclientmode.h"
|
||||
#include "view.h"
|
||||
#include <KeyValues.h>
|
||||
#include <vgui_controls/AnimationController.h>
|
||||
#include <vgui/ISurface.h>
|
||||
#include "VGuiMatSurface/IMatSystemSurface.h"
|
||||
#include "materialsystem/imaterial.h"
|
||||
#include "materialsystem/imesh.h"
|
||||
#include "materialsystem/imaterialvar.h"
|
||||
#include "IEffects.h"
|
||||
#include "hudelement.h"
|
||||
#include "clienteffectprecachesystem.h"
|
||||
#include "sourcevr/isourcevirtualreality.h"
|
||||
|
||||
using namespace vgui;
|
||||
|
||||
// memdbgon must be the last include file in a .cpp file!!!
|
||||
#include "tier0/memdbgon.h"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: HDU Damage indication
|
||||
//-----------------------------------------------------------------------------
|
||||
class CHudDamageIndicator : public CHudElement, public vgui::Panel
|
||||
{
|
||||
DECLARE_CLASS_SIMPLE( CHudDamageIndicator, vgui::Panel );
|
||||
|
||||
public:
|
||||
CHudDamageIndicator( const char *pElementName );
|
||||
void Init( void );
|
||||
void Reset( void );
|
||||
virtual bool ShouldDraw( void );
|
||||
|
||||
// Handler for our message
|
||||
void MsgFunc_Damage( bf_read &msg );
|
||||
|
||||
private:
|
||||
virtual void Paint();
|
||||
virtual void ApplySchemeSettings(vgui::IScheme *pScheme);
|
||||
|
||||
private:
|
||||
CPanelAnimationVarAliasType( float, m_flDmgX, "dmg_xpos", "10", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flDmgY, "dmg_ypos", "80", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flDmgWide, "dmg_wide", "30", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flDmgTall1, "dmg_tall1", "300", "proportional_float" );
|
||||
CPanelAnimationVarAliasType( float, m_flDmgTall2, "dmg_tall2", "240", "proportional_float" );
|
||||
|
||||
CPanelAnimationVar( Color, m_DmgColorLeft, "DmgColorLeft", "255 0 0 0" );
|
||||
CPanelAnimationVar( Color, m_DmgColorRight, "DmgColorRight", "255 0 0 0" );
|
||||
|
||||
CPanelAnimationVar( Color, m_DmgHighColorLeft, "DmgHighColorLeft", "255 0 0 0" );
|
||||
CPanelAnimationVar( Color, m_DmgHighColorRight, "DmgHighColorRight", "255 0 0 0" );
|
||||
|
||||
CPanelAnimationVar( Color, m_DmgFullscreenColor, "DmgFullscreenColor", "255 0 0 0" );
|
||||
|
||||
void DrawDamageIndicator(int side);
|
||||
void DrawFullscreenDamageIndicator();
|
||||
void GetDamagePosition( const Vector &vecDelta, float *flRotation );
|
||||
|
||||
CMaterialReference m_WhiteAdditiveMaterial;
|
||||
};
|
||||
|
||||
DECLARE_HUDELEMENT( CHudDamageIndicator );
|
||||
DECLARE_HUD_MESSAGE( CHudDamageIndicator, Damage );
|
||||
|
||||
enum
|
||||
{
|
||||
DAMAGE_ANY,
|
||||
DAMAGE_LOW,
|
||||
DAMAGE_HIGH,
|
||||
};
|
||||
|
||||
#define ANGLE_ANY 0.0f
|
||||
#define DMG_ANY 0
|
||||
|
||||
struct DamageAnimation_t
|
||||
{
|
||||
const char *name;
|
||||
int bitsDamage;
|
||||
float angleMinimum;
|
||||
float angleMaximum;
|
||||
int damage;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: List of damage animations, finds first that matches criteria
|
||||
//-----------------------------------------------------------------------------
|
||||
static DamageAnimation_t g_DamageAnimations[] =
|
||||
{
|
||||
{ "HudTakeDamageDrown", DMG_DROWN, ANGLE_ANY, ANGLE_ANY, DAMAGE_ANY },
|
||||
{ "HudTakeDamagePoison", DMG_POISON, ANGLE_ANY, ANGLE_ANY, DAMAGE_ANY },
|
||||
{ "HudTakeDamageBurn", DMG_BURN, ANGLE_ANY, ANGLE_ANY, DAMAGE_ANY },
|
||||
{ "HudTakeDamageRadiation", DMG_RADIATION, ANGLE_ANY, ANGLE_ANY, DAMAGE_ANY },
|
||||
{ "HudTakeDamageRadiation", DMG_ACID, ANGLE_ANY, ANGLE_ANY, DAMAGE_ANY },
|
||||
|
||||
{ "HudTakeDamageHighLeft", DMG_ANY, 45.0f, 135.0f, DAMAGE_HIGH },
|
||||
{ "HudTakeDamageHighRight", DMG_ANY, 225.0f, 315.0f, DAMAGE_HIGH },
|
||||
{ "HudTakeDamageHigh", DMG_ANY, ANGLE_ANY, ANGLE_ANY, DAMAGE_HIGH },
|
||||
|
||||
{ "HudTakeDamageLeft", DMG_ANY, 45.0f, 135.0f, DAMAGE_ANY },
|
||||
{ "HudTakeDamageRight", DMG_ANY, 225.0f, 315.0f, DAMAGE_ANY },
|
||||
{ "HudTakeDamageBehind", DMG_ANY, 135.0f, 225.0f, DAMAGE_ANY },
|
||||
|
||||
// fall through to front damage
|
||||
{ "HudTakeDamageFront", DMG_ANY, ANGLE_ANY, ANGLE_ANY, DAMAGE_ANY },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Constructor
|
||||
//-----------------------------------------------------------------------------
|
||||
CHudDamageIndicator::CHudDamageIndicator( const char *pElementName ) : CHudElement( pElementName ), BaseClass(NULL, "HudDamageIndicator")
|
||||
{
|
||||
vgui::Panel *pParent = g_pClientMode->GetViewport();
|
||||
SetParent( pParent );
|
||||
|
||||
m_WhiteAdditiveMaterial.Init( "vgui/white_additive", TEXTURE_GROUP_VGUI );
|
||||
|
||||
SetHiddenBits( HIDEHUD_HEALTH );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDamageIndicator::Reset( void )
|
||||
{
|
||||
m_DmgColorLeft[3] = 0;
|
||||
m_DmgColorRight[3] = 0;
|
||||
m_DmgHighColorLeft[3] = 0;
|
||||
m_DmgHighColorRight[3] = 0;
|
||||
m_DmgFullscreenColor[3] = 0;
|
||||
}
|
||||
|
||||
void CHudDamageIndicator::Init( void )
|
||||
{
|
||||
HOOK_HUD_MESSAGE( CHudDamageIndicator, Damage );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Save CPU cycles by letting the HUD system early cull
|
||||
// costly traversal. Called per frame, return true if thinking and
|
||||
// painting need to occur.
|
||||
//-----------------------------------------------------------------------------
|
||||
bool CHudDamageIndicator::ShouldDraw( void )
|
||||
{
|
||||
bool bNeedsDraw = m_DmgColorLeft[3] ||
|
||||
m_DmgColorRight[3] ||
|
||||
m_DmgHighColorLeft[3] ||
|
||||
m_DmgHighColorRight[3] ||
|
||||
m_DmgFullscreenColor[3];
|
||||
|
||||
return ( bNeedsDraw && CHudElement::ShouldDraw() );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draws a damage quad
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDamageIndicator::DrawDamageIndicator(int side)
|
||||
{
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_WhiteAdditiveMaterial );
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
||||
|
||||
int insetY = (m_flDmgTall1 - m_flDmgTall2) / 2;
|
||||
|
||||
int x1 = m_flDmgX;
|
||||
int x2 = m_flDmgX + m_flDmgWide;
|
||||
int y[4] = { (int)m_flDmgY, (int)(m_flDmgY + insetY), (int)(m_flDmgY + m_flDmgTall1 - insetY), (int)(m_flDmgY + m_flDmgTall1) };
|
||||
int alpha[4] = { 0, 1, 1, 0 };
|
||||
|
||||
// see if we're high damage
|
||||
bool bHighDamage = false;
|
||||
if ( m_DmgHighColorRight[3] > m_DmgColorRight[3] || m_DmgHighColorLeft[3] > m_DmgColorLeft[3] )
|
||||
{
|
||||
// make more of the screen be covered by damage
|
||||
x1 = GetWide() * 0.0f;
|
||||
x2 = GetWide() * 0.5f;
|
||||
y[0] = 0.0f;
|
||||
y[1] = 0.0f;
|
||||
y[2] = GetTall();
|
||||
y[3] = GetTall();
|
||||
alpha[0] = 1.0f;
|
||||
alpha[1] = 0.0f;
|
||||
alpha[2] = 0.0f;
|
||||
alpha[3] = 1.0f;
|
||||
bHighDamage = true;
|
||||
}
|
||||
|
||||
int r, g, b, a;
|
||||
if (side == 1)
|
||||
{
|
||||
if ( bHighDamage )
|
||||
{
|
||||
r = m_DmgHighColorRight[0], g = m_DmgHighColorRight[1], b = m_DmgHighColorRight[2], a = m_DmgHighColorRight[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
r = m_DmgColorRight[0], g = m_DmgColorRight[1], b = m_DmgColorRight[2], a = m_DmgColorRight[3];
|
||||
}
|
||||
|
||||
// realign x coords
|
||||
x1 = GetWide() - x1;
|
||||
x2 = GetWide() - x2;
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[0]);
|
||||
meshBuilder.TexCoord2f( 0,0,0 );
|
||||
meshBuilder.Position3f( x1, y[0], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[3] );
|
||||
meshBuilder.TexCoord2f( 0,0,1 );
|
||||
meshBuilder.Position3f( x1, y[3], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[2] );
|
||||
meshBuilder.TexCoord2f( 0,1,1 );
|
||||
meshBuilder.Position3f( x2, y[2], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[1] );
|
||||
meshBuilder.TexCoord2f( 0,1,0 );
|
||||
meshBuilder.Position3f( x2, y[1], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( bHighDamage )
|
||||
{
|
||||
r = m_DmgHighColorLeft[0], g = m_DmgHighColorLeft[1], b = m_DmgHighColorLeft[2], a = m_DmgHighColorLeft[3];
|
||||
}
|
||||
else
|
||||
{
|
||||
r = m_DmgColorLeft[0], g = m_DmgColorLeft[1], b = m_DmgColorLeft[2], a = m_DmgColorLeft[3];
|
||||
}
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[0] );
|
||||
meshBuilder.TexCoord2f( 0,0,0 );
|
||||
meshBuilder.Position3f( x1, y[0], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[1] );
|
||||
meshBuilder.TexCoord2f( 0,1,0 );
|
||||
meshBuilder.Position3f( x2, y[1], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[2] );
|
||||
meshBuilder.TexCoord2f( 0,1,1 );
|
||||
meshBuilder.Position3f( x2, y[2], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a * alpha[3] );
|
||||
meshBuilder.TexCoord2f( 0,0,1 );
|
||||
meshBuilder.Position3f( x1, y[3], 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
}
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Draws full screen damage fade
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDamageIndicator::DrawFullscreenDamageIndicator()
|
||||
{
|
||||
CMatRenderContextPtr pRenderContext( materials );
|
||||
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_WhiteAdditiveMaterial );
|
||||
|
||||
CMeshBuilder meshBuilder;
|
||||
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
|
||||
int r = m_DmgFullscreenColor[0], g = m_DmgFullscreenColor[1], b = m_DmgFullscreenColor[2], a = m_DmgFullscreenColor[3];
|
||||
|
||||
float wide = GetWide(), tall = GetTall();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a );
|
||||
meshBuilder.TexCoord2f( 0,0,0 );
|
||||
meshBuilder.Position3f( 0.0f, 0.0f, 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a );
|
||||
meshBuilder.TexCoord2f( 0,1,0 );
|
||||
meshBuilder.Position3f( wide, 0.0f, 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a );
|
||||
meshBuilder.TexCoord2f( 0,1,1 );
|
||||
meshBuilder.Position3f( wide, tall, 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.Color4ub( r, g, b, a );
|
||||
meshBuilder.TexCoord2f( 0,0,1 );
|
||||
meshBuilder.Position3f( 0.0f, tall, 0 );
|
||||
meshBuilder.AdvanceVertex();
|
||||
|
||||
meshBuilder.End();
|
||||
pMesh->Draw();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Paints the damage display
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDamageIndicator::Paint()
|
||||
{
|
||||
// draw fullscreen damage indicators
|
||||
DrawFullscreenDamageIndicator();
|
||||
|
||||
// draw side damage indicators
|
||||
DrawDamageIndicator(0);
|
||||
DrawDamageIndicator(1);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Message handler for Damage message
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDamageIndicator::MsgFunc_Damage( bf_read &msg )
|
||||
{
|
||||
int armor = msg.ReadByte(); // armor
|
||||
int damageTaken = msg.ReadByte(); // health
|
||||
long bitsDamage = msg.ReadLong(); // damage bits
|
||||
|
||||
Vector vecFrom;
|
||||
|
||||
vecFrom.x = msg.ReadFloat();
|
||||
vecFrom.y = msg.ReadFloat();
|
||||
vecFrom.z = msg.ReadFloat();
|
||||
|
||||
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
|
||||
if ( !pPlayer )
|
||||
return;
|
||||
|
||||
// player has just died, just run the dead damage animation
|
||||
if ( pPlayer->GetHealth() <= 0 )
|
||||
{
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( "HudPlayerDeath" );
|
||||
return;
|
||||
}
|
||||
|
||||
// ignore damage without direction
|
||||
// this should never happen, unless it's drowning damage,
|
||||
// or the player is forcibly killed, handled above
|
||||
if ( vecFrom == vec3_origin && !(bitsDamage & DMG_DROWN))
|
||||
return;
|
||||
|
||||
Vector vecDelta = (vecFrom - MainViewOrigin());
|
||||
VectorNormalize( vecDelta );
|
||||
|
||||
int highDamage = DAMAGE_LOW;
|
||||
if ( damageTaken > 25 )
|
||||
{
|
||||
highDamage = DAMAGE_HIGH;
|
||||
}
|
||||
|
||||
// if we have no suit, all damage is high
|
||||
if ( !pPlayer->IsSuitEquipped() )
|
||||
{
|
||||
highDamage = DAMAGE_HIGH;
|
||||
}
|
||||
|
||||
if ( damageTaken > 0 || armor > 0 )
|
||||
{
|
||||
// see which quandrant the effect is in
|
||||
float angle;
|
||||
GetDamagePosition( vecDelta, &angle );
|
||||
|
||||
// see which effect to play
|
||||
DamageAnimation_t *dmgAnim = g_DamageAnimations;
|
||||
for ( ; dmgAnim->name != NULL; ++dmgAnim )
|
||||
{
|
||||
if ( dmgAnim->bitsDamage && !(bitsDamage & dmgAnim->bitsDamage) )
|
||||
continue;
|
||||
|
||||
if ( dmgAnim->angleMinimum && angle < dmgAnim->angleMinimum )
|
||||
continue;
|
||||
|
||||
if ( dmgAnim->angleMaximum && angle > dmgAnim->angleMaximum )
|
||||
continue;
|
||||
|
||||
if ( dmgAnim->damage && dmgAnim->damage != highDamage )
|
||||
continue;
|
||||
|
||||
// we have a match, break
|
||||
break;
|
||||
}
|
||||
|
||||
if ( dmgAnim->name )
|
||||
{
|
||||
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence( dmgAnim->name );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: Convert a damage position in world units to the screen's units
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDamageIndicator::GetDamagePosition( const Vector &vecDelta, float *flRotation )
|
||||
{
|
||||
float flRadius = 360.0f;
|
||||
|
||||
// Player Data
|
||||
Vector playerPosition = MainViewOrigin();
|
||||
QAngle playerAngles = MainViewAngles();
|
||||
|
||||
Vector forward, right, up(0,0,1);
|
||||
AngleVectors (playerAngles, &forward, NULL, NULL );
|
||||
forward.z = 0;
|
||||
VectorNormalize(forward);
|
||||
CrossProduct( up, forward, right );
|
||||
float front = DotProduct(vecDelta, forward);
|
||||
float side = DotProduct(vecDelta, right);
|
||||
float xpos = flRadius * -side;
|
||||
float ypos = flRadius * -front;
|
||||
|
||||
// Get the rotation (yaw)
|
||||
*flRotation = atan2(xpos, ypos) + M_PI;
|
||||
*flRotation *= 180 / M_PI;
|
||||
|
||||
float yawRadians = -(*flRotation) * M_PI / 180.0f;
|
||||
float ca = cos( yawRadians );
|
||||
float sa = sin( yawRadians );
|
||||
|
||||
// Rotate it around the circle
|
||||
xpos = (int)((GetWide() / 2) + (flRadius * sa));
|
||||
ypos = (int)((GetTall() / 2) - (flRadius * ca));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: hud scheme settings
|
||||
//-----------------------------------------------------------------------------
|
||||
void CHudDamageIndicator::ApplySchemeSettings(vgui::IScheme *pScheme)
|
||||
{
|
||||
BaseClass::ApplySchemeSettings(pScheme);
|
||||
SetPaintBackgroundEnabled(false);
|
||||
|
||||
int vx, vy, vw, vh;
|
||||
vgui::surface()->GetFullscreenViewport( vx, vy, vw, vh );
|
||||
|
||||
SetForceStereoRenderToFrameBuffer( true );
|
||||
|
||||
if( UseVR() )
|
||||
{
|
||||
m_flDmgY = 0.125f * (float)vh;
|
||||
m_flDmgTall1 = 0.625f * (float)vh;
|
||||
m_flDmgTall2 = 0.4f * (float)vh;
|
||||
m_flDmgWide = 0.1f * (float)vw;
|
||||
}
|
||||
|
||||
SetSize(vw, vh);
|
||||
}
|
||||
Reference in New Issue
Block a user