Adding Weapon Inspect

From Valve Developer Community
Jump to navigation Jump to search
Wikipedia - Letter.png
This article has multiple issues. Please help improve it or discuss these issues on the talk page. (Learn how and when to remove these template messages)
Dead End - Icon.png
This article has no Wikipedia icon links to other VDC articles. Please help improve this article by adding links Wikipedia icon that are relevant to the context within the existing text.
January 2024

Adding Weapon Inspect

  • This will cover specifically adding weapon inspecting to the source 2013 MP code
  • What this wont cover is implementing weapon type enumerations for weapons that was ported from the 2007 SDK.
  • Adding enumerations for weapons, and adding new activities in the QC file of a weapons model is out of scope in this tutorial.

In_Buttons.h

Define IN_INSPECT in the in_buttons.h increment up or down the number on the right side of the bitwise operation.

#define    IN_INSPECT        (1 << 26)

The result should be something like this.

#ifndef IN_BUTTONS_H
#define IN_BUTTONS_H
#ifdef _WIN32
#pragma once
#endif

#define IN_ATTACK		(1 << 0)
#define IN_JUMP			(1 << 1)
#define IN_DUCK			(1 << 2)
#define IN_FORWARD		(1 << 3)
#define IN_BACK			(1 << 4)
#define IN_USE			(1 << 5)
#define IN_CANCEL		(1 << 6)
#define IN_LEFT			(1 << 7)
#define IN_RIGHT		(1 << 8)
#define IN_MOVELEFT		(1 << 9)
#define IN_MOVERIGHT	(1 << 10)
#define IN_ATTACK2		(1 << 11)
#define IN_RUN			(1 << 12)
#define IN_RELOAD		(1 << 13)
#define IN_ALT1			(1 << 14)
#define IN_ALT2			(1 << 15)
#define IN_SCORE		(1 << 16)   // Used by client.dll for when scoreboard is held down
#define IN_SPEED		(1 << 17)	// Player is holding the speed key
#define IN_WALK			(1 << 18)	// Player holding walk key
#define IN_ZOOM			(1 << 19)	// Zoom key for HUD zoom
#define IN_WEAPON1		(1 << 20)	// weapon defines these bits
#define IN_WEAPON2		(1 << 21)	// weapon defines these bits
#define IN_BULLRUSH		(1 << 22)
#define IN_GRENADE1		(1 << 23)	// grenade 1
#define IN_GRENADE2		(1 << 24)	// grenade 2
#define	IN_ATTACK3		(1 << 25)
#define	IN_INSPECT		(1 << 26)

#endif // IN_BUTTONS_H

IN_MAIN.CPP

Next, Open in_main.cpp and find:

kbutton_t	in_ducktoggle;

And put this below it

static    kbutton_t    in_inspect;

Next go to

void IN_Attack3Up( const CCommand &args ) { KeyUp(&in_attack3, args[1] );}

And put this after it

void IN_InspectDown(const CCommand& args) { KeyDown(&in_inspect, args[1]); }
void IN_InspectUp(const CCommand& args) { KeyUp(&in_inspect, args[1]); }

Next find

CalcButtonBits( bits, IN_ATTACK3, s_ClearInputState, &in_attack3, bResetState );

And put below it:

CalcButtonBits(bits, IN_INSPECT, s_ClearInputState, &in_inspect, bResetState);

Next find:

static ConCommand endattack3("-attack3", IN_Attack3Up);

Now put the following below that line.

static ConCommand startinspect("+inspect", IN_InspectDown);
static ConCommand endinspect("-inspect", IN_InspectUp);

That is all for in_main.cpp.

Implementing the activities.

Open ai_activity.h

Find the following:

// Inspect
ACT_PRIMARY_VM_INSPECT_START,
ACT_PRIMARY_VM_INSPECT_IDLE,
ACT_PRIMARY_VM_INSPECT_END,

ACT_SECONDARY_VM_INSPECT_START,
ACT_SECONDARY_VM_INSPECT_IDLE,
ACT_SECONDARY_VM_INSPECT_END,

ACT_MELEE_VM_INSPECT_START,
ACT_MELEE_VM_INSPECT_IDLE,
ACT_MELEE_VM_INSPECT_END,

If you do not find them go to

ACT_VM_DRAW_DEPLOYED

And put them under it.

ai_activity.cpp

Go to InitDefaultActivitySR

Try to find:

ACT_PRIMARY_VM_INSPECT_START

If you do not have them already add the following:

ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_INSPECT_START );
ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_INSPECT_IDLE );
ADD_ACTIVITY_TO_SR( ACT_PRIMARY_VM_INSPECT_END );

ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_INSPECT_START );
ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_INSPECT_IDLE );
ADD_ACTIVITY_TO_SR( ACT_SECONDARY_VM_INSPECT_END );

ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_INSPECT_START );
ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_INSPECT_IDLE );
ADD_ACTIVITY_TO_SR( ACT_MELEE_VM_INSPECT_END );

activitylist.cpp

open activitylist.cpp and find:

ActivityList_RegisterSharedActivities

Then inside that function find:

ACT_PRIMARY_VM_INSPECT_START

If not already there add the following:

REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_INSPECT_START );
REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_INSPECT_IDLE );
REGISTER_SHARED_ACTIVITY( ACT_PRIMARY_VM_INSPECT_END );

REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_INSPECT_START );
REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_INSPECT_IDLE );
REGISTER_SHARED_ACTIVITY( ACT_SECONDARY_VM_INSPECT_END );

REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_INSPECT_START );
REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_INSPECT_IDLE );
REGISTER_SHARED_ACTIVITY( ACT_MELEE_VM_INSPECT_END );

That is all for the activities. Note: these should be there already in 2013 mp.

hl2mp_player.h

Open hl2mp_player.h and add the following in CHL2MP_Player under the public area of the class.

void			InspectButtonPressed(void);
void			InspectButtonReleased(void);

bool			IsInspecting(void) const;

hl2mp_player.cpp

Now open hl2mp_player.cpp and add:

bool  CHL2MP_Player::IsInspecting(void) const
{
	if (m_nButtons & IN_INSPECT)
		return true;

	return false;
}

void CHL2MP_Player::InspectButtonPressed(void)
{
	if (!FlashlightIsOn())
		FlashlightTurnOn();
	else
		FlashlightTurnOff();
}

void CHL2MP_Player::InspectButtonReleased(void)
{
}

Now find:

CHL2MP_Player::PreThink

Then somewhere in the function (doesn't matter I don't think) add the following:

if (m_afButtonPressed & IN_INSPECT)
	InspectButtonPressed();

if (m_afButtonReleased & IN_INSPECT)
	 InspectButtonReleased();

That should be all for hl2mp_player.

weapon_hl2mpbase.h

Open weapon_hl2mpbase.h and in the class CWeaponHL2MPBase under public add:

CNetworkVar(int, m_nInspectStage);
CNetworkVar(float, m_flInspectAnimEndTime);

virtual bool		CanInspect(void) const { return true; }

virtual void HandleInspect(void);

int GetInspectActivity(void);

int GetActivityWeaponRole(void);

weapon_hl2mpbase.cpp

Now open weapon_hl2mpbase.cpp. After:

#include "weapon_hl2mpbase.h"

Add the following:

#ifndef CLIENT_DLL
#include "hl2mp_player.h"
#endif

In this section:

// ----------------------------------------------------------------------------- //
// CWeaponHL2MPBase tables.
// ----------------------------------------------------------------------------- //

IMPLEMENT_NETWORKCLASS_ALIASED( WeaponHL2MPBase, DT_WeaponHL2MPBase )

BEGIN_NETWORK_TABLE( CWeaponHL2MPBase, DT_WeaponHL2MPBase )

#ifdef CLIENT_DLL
  
#else
	// world weapon models have no aminations
  //	SendPropExclude( "DT_AnimTimeMustBeFirst", "m_flAnimTime" ),
//	SendPropExclude( "DT_BaseAnimating", "m_nSequence" ),
//	SendPropExclude( "DT_LocalActiveWeaponData", "m_flTimeWeaponIdle" ),
#endif
	
END_NETWORK_TABLE()

Add the following after DT_LocalActiveWeaponData

SendPropInt(SENDINFO(m_nInspectStage), 3, SPROP_UNSIGNED),

Under #ifdef CLIENT_DLL Add the following:

RecvPropInt(RECVINFO(m_nInspectStage)),

Now in the contructor CWeaponHL2MPBase() Add the following:

m_nInspectStage = 0;
m_flInspectAnimEndTime = 0;

Add the following functions to the code:

/-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponHL2MPBase::HandleInspect(void)
{
	CHL2MP_Player* pOwner = ToHL2MPPlayer(GetOwner());
	if (!pOwner)
		return;

	if (m_nInspectStage >= 3)
	{
		m_nInspectStage = 0;
		return;
	}

	if (m_nInspectStage == 0)
	{
		SendWeaponAnim(GetInspectActivity());
		m_flInspectAnimEndTime = SequenceDuration();
	}
	else if (m_nInspectStage == 1)
	{
		SendWeaponAnim(GetInspectActivity());
		m_flInspectAnimEndTime = SequenceDuration();
	}
	else if (m_nInspectStage == 2)
	{
		SendWeaponAnim(GetInspectActivity());
	}

	if (m_flInspectAnimEndTime > gpGlobals->curtime)
	{
		if (m_nInspectStage == 0)
			m_nInspectStage = 1;
		else if (m_nInspectStage == 1)
			m_nInspectStage = 1;
	}
}

// -----------------------------------------------------------------------------
// Purpose:
// -----------------------------------------------------------------------------
int CWeaponHL2MPBase::GetActivityWeaponRole(void)
{
	int iWeaponRole = GetWeaponID();

	return iWeaponRole;
}

// -----------------------------------------------------------------------------
// Purpose:
// -----------------------------------------------------------------------------
int CWeaponHL2MPBase::GetInspectActivity(void)
{
	CHL2MP_Player* pOwner = ToHL2MPPlayer(GetOwner());
	if (!pOwner)
		return ACT_PRIMARY_VM_INSPECT_START;

	int iActivity = ACT_PRIMARY_VM_INSPECT_START;

	switch (GetActivityWeaponRole())
	{
	case WEAPON_SHOTGUN:
	default:
		if (m_nInspectStage == 1)
			iActivity = ACT_PRIMARY_VM_INSPECT_START;
		else if (m_nInspectStage == 2)
			iActivity = ACT_PRIMARY_VM_INSPECT_END;
		else
			iActivity = ACT_PRIMARY_VM_INSPECT_IDLE;
		break;
	case WEAPON_CROSSBOW:
		if (m_nInspectStage == 1)
			iActivity = ACT_SECONDARY_VM_INSPECT_START;
		else if (m_nInspectStage == 2)
			iActivity = ACT_SECONDARY_VM_INSPECT_END;
		else
			iActivity = ACT_SECONDARY_VM_INSPECT_IDLE;
		break;
	case WEAPON_CROWBAR:
		if (m_nInspectStage == 1)
			iActivity = ACT_MELEE_VM_INSPECT_START;
		else if (m_nInspectStage == 2)
			iActivity = ACT_MELEE_VM_INSPECT_END;
		else
			iActivity = ACT_MELEE_VM_INSPECT_IDLE;
		break;
	case WEAPON_PHYSCANNON:
		if (m_nInspectStage == 1)
			iActivity = ACT_PRIMARY_VM_INSPECT_START;
		else if (m_nInspectStage == 2)
			iActivity = ACT_PRIMARY_VM_INSPECT_END;
		else
			iActivity = ACT_PRIMARY_VM_INSPECT_IDLE;
		break;
	case WEAPON_PYTHON357:
		if (m_nInspectStage == 1)
			iActivity = ACT_SECONDARY_VM_INSPECT_START;
		else if (m_nInspectStage == 2)
			iActivity = ACT_SECONDARY_VM_INSPECT_END;
		else
			iActivity = ACT_SECONDARY_VM_INSPECT_IDLE;
		break;

	case WEAPON_RPG:
		if (m_nInspectStage == 1)
			iActivity = ACT_PRIMARY_VM_INSPECT_START;
		else if (m_nInspectStage == 2)
			iActivity = ACT_PRIMARY_VM_INSPECT_END;
		else
			iActivity = ACT_PRIMARY_VM_INSPECT_IDLE;
		break;
	}

	return iActivity;
}

Note: for each weapon you will need to have a case for it, and its own enum weapon type it returns.

Adding the ability for a weapon to use inspect

Open all the weapons you want to add an Inspect to.

If the weapon has an ItemPostFrame

Add this near the top of the function:

//Note: you do not need this pOwner if you have it already.
CBasePlayer *pOwner = ToBasePlayer( GetOwner() );
	if (!pOwner)
	{
		return;
	}
	

if (CanInspect())
{
	if (pOwner->m_afButtonPressed & IN_INSPECT)
		HandleInspect();

	if (pOwner->m_afButtonReleased & IN_INSPECT)
		m_nInspectStage = 2;
}

If you do not have an ItemPostFrame for the weapon you will need to make an override function, add the above, and call the Baseclass::ItemPostFrame

You should now have Weapon Inspecting.