Adding Weapon Inspect

== 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.
Category:Weapons programming
Category:Tutorials