Dropping empty magazines (GoldSrc)

From Valve Developer Community
Revision as of 09:23, 11 October 2005 by Draco (talk | contribs) (Initial tutorial)

(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Introduction

A small visual effect can add alot of polish to your game. One such effect is actually dropping your empty clips/magazines when you reload a suitable gun. If you time it right, players will see other players drop the empty clip when the player animation does so. I am working off the blank MP SDK, so you may need to place the code in different places.(I recommend you use the blank SDK anyway, for it will yield greater results in the long run.) Before we start remember that '...' in the code means that there are other, unrelated lines there.

Ejecting the clip

To do this in HL1(and I assume The Specialists did something similar for their clip dropping) I used the EjectBrass function but with my clip model as the model instead of a bullet. EjectBrass in source is a little different, taking a model index as the argument. I have created my own function for this purpose.

in c_te_legacytempents.cpp

void CTempEnts::EjectClip( const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, model_t *pModel )
{
	if ( pModel == NULL )
		return;

	C_LocalTempEntity	*pTemp = TempEntAlloc( pos1, ( model_t * ) pModel );

	if ( pTemp == NULL )
		return;

	pTemp->m_nBody	= 0;

	pTemp->flags |= ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE );

	pTemp->m_vecTempEntAngVelocity[0] = random->RandomFloat(-1024,1024);
	pTemp->m_vecTempEntAngVelocity[1] = random->RandomFloat(-1024,1024);
	pTemp->m_vecTempEntAngVelocity[2] = random->RandomFloat(-1024,1024);

	//Face forward
	pTemp->SetAbsAngles( gunAngles );

	pTemp->SetRenderMode( kRenderNormal );
	pTemp->tempent_renderamt = 255;		// Set this for fadeout

	Vector	dir;

	AngleVectors( angles, &dir );

	dir *= random->RandomFloat( 150.0f, 200.0f );

	pTemp->SetVelocity( Vector(dir[0] + random->RandomFloat(-64,64),
						dir[1] + random->RandomFloat(-64,64),
						dir[2] + random->RandomFloat(  0,64) ) );

	pTemp->die = gpGlobals->curtime + 20;
}

make sure you add the prototype to the CTempEnts class, found in c_te_legacytempents.h

class CTempEnts : public ITempEnts
{
...
virtual void EjectClip( const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, model_t *pModel );
...
};

Then add it to ITempEnts, found in the same file

class ITempEnts
{
...
virtual void EjectClip( const Vector &pos1, const QAngle &angles, const QAngle &gunAngles, model_t *pModel ) = 0;
...
};

Reloading

Now let's add this to one of your guns. Find one that will suit the effect, such as a pistol. I will use the Falcon 2 pistol from my mod.

bool CWeaponFalcon2::Reload()
{
...
#ifdef CLIENT_DLL
	model_t *pModel = (model_t *)engine->LoadModel( pWeaponInfo.szClipModel );
	tempents->EjectClip( pPlayer->GetLocalOrigin(), pPlayer->GetLocalAngles(), pPlayer->GetAbsAngles(), pModel );
#endif
...
}

As you can see I have this all on the client. First you load a model into a model info pointer for use as the clip model. I am using the weapon scripts to specify the path to model, I will demonstrate how shortly.

That will spawn a clip model, that bounces, collides, falls and stays alive for 20 seconds.

Loading the model with the weapon script

Another thing Source has over HL1 is the weapon script parser. I don't know what I ever did without it. We shall add another token to the scripts that you can use to set a model for EjectClip.

Find the parser files, in the blank sdk it is called sdk_weapon_parse. Open sdk_weapon_parse.h(or equilivant for your sdk) and add this to CSDKWeaponInfo:

class CSDKWeaponInfo : public FileWeaponInfo_t
{
...
char	szClipModel[MAX_WEAPON_STRING];	// Clip model of this weapon
...
};

now open sdk_weapon_parse.cpp and add this:

void CSDKWeaponInfo::Parse( KeyValues *pKeyValuesData, const char *szWeaponName )
{
...
Q_strncpy( szClipModel, pKeyValuesData->GetString( "clipmodel" ), MAX_WEAPON_STRING );
...
}

now you can simply find the model path in the code by accessing szClipModel, like so:

const CSDKWeaponInfo &pWeaponInfo = GetSDKWpnData();
model_t *pModel = (model_t *)engine->LoadModel( pWeaponInfo.szClipModel );

It is easy to make new tokens for anything in your weapon script.

Now let's add that to the script itself. Find your weapons script file. mine is PerfectDark/scripts/weapon_falcon2.cpp.

// Weapon data is loaded by both the Game and Client DLLs.
"printname"			"#PD_FALCON2"
"viewmodel"			"models/v_falcon2.mdl"
"playermodel"			"models/w_falcon2.mdl"
"clipmodel"			"models/w_falconclip.mdl"
"PlayerAnimationExtension"	"Pistol"

Easy peasy.

If you have any problems you can PM me here User_talk:Draco Or you can contact me at #ausbg on GameSurge IRC.