diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /game/client/tf/tf_hud_damageindicator.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'game/client/tf/tf_hud_damageindicator.cpp')
| -rw-r--r-- | game/client/tf/tf_hud_damageindicator.cpp | 330 |
1 files changed, 330 insertions, 0 deletions
diff --git a/game/client/tf/tf_hud_damageindicator.cpp b/game/client/tf/tf_hud_damageindicator.cpp new file mode 100644 index 0000000..9e48cea --- /dev/null +++ b/game/client/tf/tf_hud_damageindicator.cpp @@ -0,0 +1,330 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Hud element that indicates the direction of damage taken by the player +// +//=============================================================================// + +#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" + +using namespace vgui; + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +class CHudDamageIndicator : public CHudElement, public vgui::Panel +{ + DECLARE_CLASS_SIMPLE( CHudDamageIndicator, vgui::Panel ); +public: + CHudDamageIndicator( const char *pElementName ); + void Init( void ); + void VidInit( void ); + void Reset( void ); + virtual bool ShouldDraw( void ); + + // Handler for our message + void MsgFunc_Damage( bf_read &msg ); + +private: + virtual void OnThink(); + virtual void Paint(); + virtual void ApplySchemeSettings(vgui::IScheme *pScheme); + + // Painting + void GetDamagePosition( const Vector &vecDelta, float flRadius, float *xpos, float *ypos, float *flRotation ); + void DrawDamageIndicator(int x0, int y0, int x1, int y1, float alpha, float flRotation ); + +private: + // Indication times + + CPanelAnimationVarAliasType( float, m_flMinimumWidth, "MinimumWidth", "10", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flMaximumWidth, "MaximumWidth", "100", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flMinimumHeight, "MinimumHeight", "20", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flMaximumHeight, "MaximumHeight", "100", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flStartRadius, "StartRadius", "140", "proportional_float" ); + CPanelAnimationVarAliasType( float, m_flEndRadius, "EndRadius", "120", "proportional_float" ); + + CPanelAnimationVar( float, m_iMaximumDamage, "MaximumDamage", "100" ); + CPanelAnimationVar( float, m_flMinimumTime, "MinimumTime", "1" ); + CPanelAnimationVar( float, m_flMaximumTime, "MaximumTime", "2" ); + CPanelAnimationVar( float, m_flTravelTime, "TravelTime", ".1" ); + CPanelAnimationVar( float, m_flFadeOutPercentage, "FadeOutPercentage", "0.7" ); + CPanelAnimationVar( float, m_flNoise, "Noise", "0.1" ); + + // List of damages we've taken + struct damage_t + { + int iScale; + float flLifeTime; + float flStartTime; + Vector vecDelta; // Damage origin relative to the player + }; + CUtlVector<damage_t> m_vecDamages; + + CMaterialReference m_WhiteAdditiveMaterial; +}; + +DECLARE_HUDELEMENT( CHudDamageIndicator ); +DECLARE_HUD_MESSAGE( CHudDamageIndicator, Damage ); + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +CHudDamageIndicator::CHudDamageIndicator( const char *pElementName ) : + CHudElement( pElementName ), BaseClass(NULL, "HudDamageIndicator") +{ + vgui::Panel *pParent = g_pClientMode->GetViewport(); + SetParent( pParent ); + + SetHiddenBits( HIDEHUD_HEALTH ); + + m_WhiteAdditiveMaterial.Init( "VGUI/damageindicator", TEXTURE_GROUP_VGUI ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudDamageIndicator::Init( void ) +{ + HOOK_HUD_MESSAGE( CHudDamageIndicator, Damage ); + Reset(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudDamageIndicator::Reset( void ) +{ + m_vecDamages.Purge(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudDamageIndicator::VidInit( void ) +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudDamageIndicator::OnThink() +{ +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CHudDamageIndicator::ShouldDraw( void ) +{ + if ( !CHudElement::ShouldDraw() ) + return false; + + // Don't draw if we don't have any damage to indicate + if ( !m_vecDamages.Count() ) + return false; + + return true; +} + +//----------------------------------------------------------------------------- +// Purpose: Convert a damage position in world units to the screen's units +//----------------------------------------------------------------------------- +void CHudDamageIndicator::GetDamagePosition( const Vector &vecDelta, float flRadius, float *xpos, float *ypos, float *flRotation ) +{ + // 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); + *xpos = flRadius * -side; + *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)((ScreenWidth() / 2) + (flRadius * sa)); + *ypos = (int)((ScreenHeight() / 2) - (flRadius * ca)); +} + +//----------------------------------------------------------------------------- +// Purpose: Draw a single damage indicator +//----------------------------------------------------------------------------- +void CHudDamageIndicator::DrawDamageIndicator(int x0, int y0, int x1, int y1, float alpha, float flRotation ) +{ + CMatRenderContextPtr pRenderContext( materials ); + IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, m_WhiteAdditiveMaterial ); + + // Get the corners, since they're being rotated + int wide = x1 - x0; + int tall = y1 - y0; + Vector2D vecCorners[4]; + Vector2D center( x0 + (wide * 0.5f), y0 + (tall * 0.5f) ); + float yawRadians = -flRotation * M_PI / 180.0f; + Vector2D axis[2]; + axis[0].x = cos(yawRadians); + axis[0].y = sin(yawRadians); + axis[1].x = -axis[0].y; + axis[1].y = axis[0].x; + Vector2DMA( center, -0.5f * wide, axis[0], vecCorners[0] ); + Vector2DMA( vecCorners[0], -0.5f * tall, axis[1], vecCorners[0] ); + Vector2DMA( vecCorners[0], wide, axis[0], vecCorners[1] ); + Vector2DMA( vecCorners[1], tall, axis[1], vecCorners[2] ); + Vector2DMA( vecCorners[0], tall, axis[1], vecCorners[3] ); + + // Draw the sucker + CMeshBuilder meshBuilder; + meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 ); + + int iAlpha = alpha * 255; + meshBuilder.Color4ub( 255,255,255, iAlpha ); + meshBuilder.TexCoord2f( 0,0,0 ); + meshBuilder.Position3f( vecCorners[0].x,vecCorners[0].y,0 ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Color4ub( 255,255,255, iAlpha ); + meshBuilder.TexCoord2f( 0,1,0 ); + meshBuilder.Position3f( vecCorners[1].x,vecCorners[1].y,0 ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Color4ub( 255,255,255, iAlpha ); + meshBuilder.TexCoord2f( 0,1,1 ); + meshBuilder.Position3f( vecCorners[2].x,vecCorners[2].y,0 ); + meshBuilder.AdvanceVertex(); + + meshBuilder.Color4ub( 255,255,255, iAlpha ); + meshBuilder.TexCoord2f( 0,0,1 ); + meshBuilder.Position3f( vecCorners[3].x,vecCorners[3].y,0 ); + meshBuilder.AdvanceVertex(); + + meshBuilder.End(); + pMesh->Draw(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CHudDamageIndicator::Paint() +{ + // Iterate backwards, because we might remove them as we go + int iSize = m_vecDamages.Count(); + for (int i = iSize-1; i >= 0; i--) + { + // Scale size to the damage + float clampedDamage = clamp( (float) m_vecDamages[i].iScale, 0.f, m_iMaximumDamage ); + + int iWidth = RemapVal(clampedDamage, 0, m_iMaximumDamage, m_flMinimumWidth, m_flMaximumWidth) * 0.5; + int iHeight = RemapVal(clampedDamage, 0, m_iMaximumDamage, m_flMinimumHeight, m_flMaximumHeight) * 0.5; + + // Find the place to draw it + float xpos, ypos; + float flRotation; + float flTimeSinceStart = ( gpGlobals->curtime - m_vecDamages[i].flStartTime ); + float flRadius = RemapVal( MIN( flTimeSinceStart, m_flTravelTime ), 0, m_flTravelTime, m_flStartRadius, m_flEndRadius ); + GetDamagePosition( m_vecDamages[i].vecDelta, flRadius, &xpos, &ypos, &flRotation ); + + // Calculate life left + float flLifeLeft = ( m_vecDamages[i].flLifeTime - gpGlobals->curtime ); + if ( flLifeLeft > 0 ) + { + float flPercent = flTimeSinceStart / (m_vecDamages[i].flLifeTime - m_vecDamages[i].flStartTime); + float alpha; + if ( flPercent <= m_flFadeOutPercentage ) + { + alpha = 1.0; + } + else + { + alpha = 1.0 - RemapVal( flPercent, m_flFadeOutPercentage, 1.0, 0.0, 1.0 ); + } + DrawDamageIndicator( xpos-iWidth, ypos-iHeight, xpos+iWidth, ypos+iHeight, alpha, flRotation ); + } + else + { + m_vecDamages.Remove(i); + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: Message handler for Damage message +//----------------------------------------------------------------------------- +void CHudDamageIndicator::MsgFunc_Damage( bf_read &msg ) +{ + damage_t damage; + damage.iScale = msg.ReadShort(); + msg.ReadLong(); // Read & ignored + if ( !msg.ReadOneBit() ) + return; + + if ( damage.iScale > m_iMaximumDamage ) + { + damage.iScale = m_iMaximumDamage; + } + Vector vecOrigin; + msg.ReadBitVec3Coord( vecOrigin ); + + damage.flStartTime = gpGlobals->curtime; + damage.flLifeTime = gpGlobals->curtime + RemapVal(damage.iScale, 0, m_iMaximumDamage, m_flMinimumTime, m_flMaximumTime); + + if ( vecOrigin == vec3_origin ) + { + vecOrigin = MainViewOrigin(); + } + + damage.vecDelta = (vecOrigin - MainViewOrigin()); + VectorNormalize( damage.vecDelta ); + + // Add some noise + damage.vecDelta[0] += random->RandomFloat( -m_flNoise, m_flNoise ); + damage.vecDelta[1] += random->RandomFloat( -m_flNoise, m_flNoise ); + damage.vecDelta[2] += random->RandomFloat( -m_flNoise, m_flNoise ); + VectorNormalize( damage.vecDelta ); + + m_vecDamages.AddToTail( damage ); +} + +//----------------------------------------------------------------------------- +// Purpose: hud scheme settings +//----------------------------------------------------------------------------- +void CHudDamageIndicator::ApplySchemeSettings(vgui::IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + SetPaintBackgroundEnabled(false); + + // set our size + int screenWide, screenTall; + int x, y; + GetPos(x, y); + GetHudSize(screenWide, screenTall); + SetBounds(0, y, screenWide, screenTall - y); +} |