Prediction/Sample weapon

From Valve Developer Community
Jump to: navigation, search

This weapon will print data to the console when prediction events occur. Equip it with give weapon_test.

C++

Include this in both your client and server projects.

#include "cbase.h"

#ifdef CLIENT_DLL
	#include "prediction.h"
	#define CTestWeapon C_TestWeapon
#endif

class CTestWeapon : public CBaseCombatWeapon
{
public:
	DECLARE_CLASS( CTestWeapon, CBaseCombatWeapon );
	DECLARE_NETWORKCLASS();

#ifdef CLIENT_DLL
	DECLARE_PREDICTABLE();
	virtual bool ShouldPredict();
#endif

	virtual bool IsPredicted() const { return true; }
	CTestWeapon() { SetPredictionEligible(true); iTest = 0; }

	void PrimaryAttack();
	void SecondaryAttack();

	void ShootBullet(bool bRapidFire);

#ifdef GAME_DLL
	CNetworkVar( int, iTest );
#elif CLIENT_DLL
	int iTest;
#endif
};

LINK_ENTITY_TO_CLASS( weapon_test, CTestWeapon );
PRECACHE_WEAPON_REGISTER( weapon_test );

IMPLEMENT_NETWORKCLASS_ALIASED( TestWeapon, DT_TestWeapon )

#ifdef CLIENT_DLL
BEGIN_PREDICTION_DATA( CTestWeapon )
	DEFINE_PRED_FIELD( iTest, FIELD_INTEGER, FTYPEDESC_NOERRORCHECK)
END_PREDICTION_DATA()

bool CTestWeapon::ShouldPredict()
{
	if ( GetOwner() && GetOwner() == C_BasePlayer::GetLocalPlayer() )
		return true;
	else
		return BaseClass::ShouldPredict();
}

void RecvProxy_TestWeapon( const CRecvProxyData *pData, void *pStruct, void *pOut )
{
		int value =  *((unsigned long*)&pData->m_Value.m_Int);
		static int oldvalue = 0;

		if ( value != oldvalue ) 
			Warning( "Client updated to shot %i\n", value );

		oldvalue = value;
		*((unsigned long*)pOut) = value;
}

#endif // CLIENT_DLL

BEGIN_NETWORK_TABLE( CTestWeapon, DT_TestWeapon )
#ifdef GAME_DLL
	SendPropInt( SENDINFO(iTest) ),
#elif CLIENT_DLL
	RecvPropInt( RECVINFO(iTest),-1, RecvProxy_TestWeapon ),
#endif
END_NETWORK_TABLE()

void CTestWeapon::PrimaryAttack()
{
	ShootBullet(false);
	m_flNextPrimaryAttack = gpGlobals->curtime + 0.75;
}

void CTestWeapon::SecondaryAttack()
{
	ShootBullet(true);
	m_flNextSecondaryAttack = gpGlobals->curtime + 0.25;
}

void CTestWeapon::ShootBullet(bool bRapidFire)
{
	iTest++;

#ifdef CLIENT_DLL
	if ( prediction->IsFirstTimePredicted() )
		Msg( "Client made shot %i\n", iTest );
	else
		Msg( "\tClient testing shot %i\n", iTest );
#elif GAME_DLL
	Warning("Server received shot %i\n",iTest);
#endif

	FireBulletsInfo_t attack;

	CBasePlayer* pPlayer = ToBasePlayer( GetOwner() );
	if ( pPlayer )
	{
		pPlayer->RemoveAmmo( attack.m_iShots, m_iPrimaryAmmoType );
 		pPlayer->DoMuzzleFlash();
		pPlayer->SetAnimation( PLAYER_ATTACK1 );

		attack.m_vecSrc = pPlayer->Weapon_ShootPosition();
	}
	else
		attack.m_vecSrc = GetOwner()->GetAbsOrigin();

	attack.m_flDistance = MAX_TRACE_LENGTH;
	attack.m_iAmmoType = m_iPrimaryAmmoType;
	attack.m_iTracerFreq = 2;

	Vector fwd;
	AngleVectors(GetOwner()->GetAbsAngles(),&fwd);
	attack.m_vecDirShooting = fwd;

	if ( bRapidFire )
	{
		attack.m_vecSpread = VECTOR_CONE_10DEGREES;
		attack.m_bPrimaryAttack = false;
	}

	GetOwner()->FireBullets( attack );
	
	WeaponSound(SINGLE);
	SendWeaponAnim( GetPrimaryAttackActivity() );
}

Script

Save this as mod\scripts\weapon_test.txt. Remember to change the ammo in use from "pistol" to something your AmmoDef recognises.

WeaponData
{	
	printname		"Prediction test weapon"
	viewmodel		models/weapons/v_357.mdl
	playermodel		models/weapons/w_357.mdl
	anim_prefix		python
	bucket			1
	bucket_position	1

	clip_size			-1
	clip2_size			-1
	primary_ammo		pistol
	secondary_ammo		pistol

	weight		7

	SoundData
	{
		empty		Weapon_Pistol.Empty
		single_shot	Weapon_357.Single
	}

	TextureData
	{
		weapon
		{
				font		WeaponIcons
				character	e
		}
		weapon_s
		{	
				font		WeaponIconsSelected
				character	e
		}
		weapon_small
		{
				font		WeaponIconsSmall
				character	e
		}
		ammo
		{
				font		WeaponIconsSmall
				character	q
		}
		crosshair
		{
				font		Crosshairs
				character	Q
		}
		autoaim
		{
				file		sprites/crosshairs
				x			0
				y			48
				width		24
				height		24
		}
	}
}