Adding Weapon Inspect
January 2024
You can help by adding links to this article from other relevant articles.
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.