Battlefield Style Hitmarker: Difference between revisions
m (→WEAPON_X.CPP) |
|||
| Line 176: | Line 176: | ||
==WEAPON_X.CPP== | ==WEAPON_X.CPP== | ||
For this example I will be using the weapon_pistol.cpp, you will have to add this to all weapons used in your mod. The reasoning for this in my case is not all weapons use the <code>MAX_TRACE_LENGTH</code>, and I need to set this accordingly per weapon, else you could add this in the Baseclass:PrimaryAttack. | For this example I will be using the weapon_pistol.cpp, you will have to add this to all weapons used in your mod. The reasoning for this in my case is not all weapons use the <code>MAX_TRACE_LENGTH</code>, and I need to set this accordingly per weapon, else you could add this in the Baseclass::PrimaryAttack. | ||
Declare the following underneath the rest of the function declarations near the top of the file. | Declare the following underneath the rest of the function declarations near the top of the file. | ||
Revision as of 03:08, 9 January 2014
The Goal
We are going to re-create battlefield style hitmarkers for all weapons, complete with animation. This is going to be a very simple copy & paste tutorial, and there is room for contribution and tweaks.
The Code
Create the following files and place them inside your client (C:\MOD\src\game\client).
HUD_HITMARKER.H
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Hit Marker
//
//=============================================================================//
#include "hudelement.h"
#include "hud_numericdisplay.h"
#include <vgui_controls/Panel.h>
class CHudHitmarker : public vgui::Panel, public CHudElement
{
DECLARE_CLASS_SIMPLE( CHudHitmarker, vgui::Panel );
public:
CHudHitmarker( const char *pElementName );
void Init();
void Reset();
bool ShouldDraw();
void MsgFunc_ShowHitmarker( bf_read &msg );
protected:
virtual void ApplySchemeSettings(vgui::IScheme *scheme);
virtual void Paint( void );
private:
bool m_bHitmarkerShow;
CPanelAnimationVar( Color, m_HitmarkerColor, "HitMarkerColor", "255 255 255 255" );
};
HUD_HITMARKER.CPP
//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Hit Marker
//
//=============================================================================//
#include "cbase.h"
#include "hudelement.h"
#include "hud_macros.h"
#include "hud_hitmarker.h"
#include "iclientmode.h"
#include "c_baseplayer.h"
// VGUI panel includes
#include <vgui_controls/AnimationController.h>
#include <vgui/ISurface.h>
#include <vgui/ILocalize.h>
using namespace vgui;
// memdbgon must be the last include file in a .cpp file!
#include "tier0/memdbgon.h"
DECLARE_HUDELEMENT( CHudHitmarker );
DECLARE_HUD_MESSAGE( CHudHitmarker, ShowHitmarker );
//-----------------------------------------------------------------------------
// Purpose: Constructor
//-----------------------------------------------------------------------------
CHudHitmarker::CHudHitmarker( const char *pElementName ) : CHudElement(pElementName), BaseClass(NULL, "HudHitmarker")
{
vgui::Panel *pParent = g_pClientMode->GetViewport();
SetParent( pParent );
// Hitmarker will not show when the player is dead
SetHiddenBits( HIDEHUD_PLAYERDEAD );
int screenWide, screenTall;
GetHudSize(screenWide, screenTall);
SetBounds(0, 0, screenWide, screenTall);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudHitmarker::Init()
{
HOOK_HUD_MESSAGE( CHudHitmarker, ShowHitmarker );
SetAlpha( 0 );
m_bHitmarkerShow = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudHitmarker::Reset()
{
SetAlpha( 0 );
m_bHitmarkerShow = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudHitmarker::ApplySchemeSettings( vgui::IScheme *scheme )
{
BaseClass::ApplySchemeSettings(scheme);
SetPaintBackgroundEnabled(false);
SetPaintBorderEnabled(false);
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CHudHitmarker::ShouldDraw( void )
{
return ( m_bHitmarkerShow && CHudElement::ShouldDraw() );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudHitmarker::Paint( void )
{
C_BasePlayer* pPlayer = C_BasePlayer::GetLocalPlayer();
if (!pPlayer)
{
return;
}
if (m_bHitmarkerShow)
{
int x,y;
// Find our screen position to start from
x = XRES(320);
y = YRES(240);
vgui::surface()->DrawSetColor( m_HitmarkerColor );
vgui::surface()->DrawLine( x - 6, y - 5, x - 11, y - 10 );
vgui::surface()->DrawLine( x + 5, y - 5, x + 10, y - 10 );
vgui::surface()->DrawLine( x - 6, y + 5, x - 11, y + 10 );
vgui::surface()->DrawLine( x + 5, y + 5, x + 10, y + 10 );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CHudHitmarker::MsgFunc_ShowHitmarker(bf_read &msg)
{
m_bHitmarkerShow = msg.ReadByte();
g_pClientMode->GetViewportAnimationController()->StartAnimationSequence("HitMarkerShow");
}
Implementation
Once compiled, we now have the hud element created. The next step is to call it in the code, for this we will add a usermessage which gets called when a weapon fires and sucessfully hits an enemy.
X_USERMESSAGES.CPP
Depending on your mod base this will be hl2_usermessages.cpp or sdk_usermessages.cpp.
Add the following line to bottom of the file
usermessages->Register( "ShowHitmarker", 1); // Show Hit Marker
WEAPON_X.CPP
For this example I will be using the weapon_pistol.cpp, you will have to add this to all weapons used in your mod. The reasoning for this in my case is not all weapons use the MAX_TRACE_LENGTH, and I need to set this accordingly per weapon, else you could add this in the Baseclass::PrimaryAttack.
Declare the following underneath the rest of the function declarations near the top of the file.
void DrawHitmarker( void );
Implement the function you just declared as follows.
void CWeaponPistol::DrawHitmarker( void )
{
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( pPlayer == NULL )
{ return; }
#ifndef CLIENT_DLL
CSingleUserRecipientFilter filter(pPlayer);
UserMessageBegin(filter, "ShowHitmarker");
WRITE_BYTE(1);
MessageEnd();
#endif
}
Inside your weapon file find the ::PrimaryAttack function and add under CBasePlayer *pOwner = ToBasePlayer( GetOwner() ); add:
CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
if ( !pPlayer )
{ return; }
Finally, add this snippet at the bottom of the ::PrimaryAttack function.
// set up the vectors and traceline
trace_t tr;
Vector vecStart, vecStop, vecDir;
// get the angles
AngleVectors( pPlayer->EyeAngles( ), &vecDir );
// get the vectors
vecStart = pPlayer->Weapon_ShootPosition();
vecStop = vecStart + vecDir * MAX_TRACE_LENGTH;
// do the traceline
UTIL_TraceLine( vecStart, vecStop, MASK_ALL, pPlayer, COLLISION_GROUP_NONE, &tr );
// check to see if we hit a Player
if ( tr.m_pEnt )
{
if ( tr.m_pEnt->IsPlayer() )
{
DrawHitmarker();
}
}
}
Animation
Open up your hudanimations.txt file and add the following to the bottom of the file.
event HitMarkerShow
{
Animate HudHitmarker Alpha 255 Linear 0.2 0.4
RunEvent HitMarkerHide 0.4
}
event HitMarkerHide
{
Animate HudHitmarker Alpha 0 Linear 0.2 0.4
}
You can edit the values here to achieve the look and feel you like, but I feel these settings emulate Battlefield's Style nicely.
Finishing Up
Single Player Tweaks
For single player mods, you'll find you need to edit a line within the ::PrimaryAttack code we added, rather than detecting players we need to detect NPC's.
Simply change the following:
// check to see if we hit a Player
if ( tr.m_pEnt )
{
if ( tr.m_pEnt->IsPlayer() )
{
DrawHitmarker();
}
}
to this:
// check to see if we hit an NPC
if ( tr.m_pEnt )
{
if ( tr.m_pEnt->IsNPC() )
{
DrawHitmarker();
}
}
So there we go, a very basic but fully functional Battlefield Style Hitmarker.
There is a lot of room for tweaking, for instance this will currently show when you hit any Players/NPC's regardless of their Team or AI Relationship. You could think about adding in functionality to differentiate between friendly and enemy Players/NPC's and display different properties accordingly.
Enjoy,
Ferrety (ferrety6012@gmail.com)