Quick Grenade

From Valve Developer Community
Revision as of 05:09, 25 January 2015 by ExoBacon (talk | contribs) (Created page with "This is a copy and paste tutorial for adding a quick grenade function seen in many newer games. What this will do is simply holster the viewmodel, create a second viewmodel wi...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This is a copy and paste tutorial for adding a quick grenade function seen in many newer games. What this will do is simply holster the viewmodel, create a second viewmodel with the v_grenade model, play the throw animation, remove the second viewmodel then draw the first viewmodel. Has been tested on a near-new Source 2013 codebase.

Requirements

  • A brain (This one is REALLY important)
  • Knowledge of how to copy and paste text

Creating the throw button

First file is in_buttons.h. Add this to the end:

#define IN_THROWGRENADE (1 << 26)

NOTE: You see how the last number on that line is 26? Well if you look at the in_buttons file you will see that the last number in each line counts upwards from 0. So for instance if the last line on the defines is 30, your new line should end with 31. Got that?

Second piece of code is in in_main.cpp. First thing your going to have to search for is a big clump of lines starting with CalcButtonBits. It should start at approximately line 1457.

CalcButtonBits(bits, IN_THROWGRENADE, s_ClearInputState, &in_throwgrenade, bResetState);

Now we have to jump up to the top of the file and define in_throwgrenade. Just below the includes and convars there should be a bunch of lines starting with kbutton_t. We just add this code to the bottom of the final kbutton_t.

kbutton_t	in_throwgrenade;

Then we go down a bit further to where all the keys are worked out. Just search for void IN_Attack3Up and stick this directly below it.

void IN_ThrowGrenadeDown(const CCommand &args) { KeyDown(&in_throwgrenade, args[1]); }
void IN_ThrowGrenadeUp(const CCommand &args) { KeyUp(&in_throwgrenade, args[1]); }

Now we search for where all the code can be called by the player with ConCommands. The lines should start with "static ConCommand" at approximately line 1570. Put this after the last "static ConCommand"

static ConCommand startgrenadethrow("+throwgrenade", IN_ThrowGrenadeDown);
static ConCommand endgrenadethrow("-throwgrenade", IN_ThrowGrenadeUp);

The Actual Function

First file is hl2_player.h (or hl2mp_player.h or sdk_player.h) Go down to line 263 and you should see the code declaration

void  HandleSpeedChanges( void );

If you don't, search for it.

Once you've found that line, paste these underneath it.

void  HandleThrowGrenade(void);
void  ThrowGrenade(void);
void  CreateGrenade(void);

Then scroll down a bit right to the end of that class where you should see the line

friend class CHL2GameMovement;

Again, if you don't, search for it

And again, paste these underneath.

float				timeholster;
float				timethrow;
float				timedeploy;
bool				WantThrow;

Now we move to hl2_player.cpp.

You can put this anywhere in the file, I put it underneath HandleSpeedChanges.

void CHL2_Player::HandleThrowGrenade(void)
{
	if ((m_afButtonPressed & IN_THROWGRENADE) && !WantThrow && HasAnyAmmoOfType(12) && HasWeapons())
	{
		timeholster = NULL;
		timethrow = NULL;
		timedeploy = NULL;
		WantThrow = true;
	}

	ThrowGrenade();
}

void CHL2_Player::ThrowGrenade(void)
{
	if (WantThrow)
	{
		CBaseViewModel *vm = GetViewModel(0);
		CBaseViewModel *vm2 = GetViewModel(1);

		//2nd viewmodel creation
		if (!vm2)
		{
			CreateViewModel(1);
			vm2 = GetViewModel(1);
		}

		//HOLSTER SEQUENCING
		int sequence1 = vm->SelectWeightedSequence(ACT_VM_HOLSTER);
		if ((timeholster == NULL) && (sequence1 >= 0))
		{
			vm->SendViewModelMatchingSequence(sequence1);
			timeholster = (gpGlobals->curtime + vm->SequenceDuration(sequence1) + 0.5f);
		}

		//THROW SEQUENCING
		if ((timeholster < gpGlobals->curtime) && (timeholster != NULL))
		{
			vm->AddEffects(EF_NODRAW);
			vm2->SetWeaponModel("models/weapons/v_grenade.mdl", NULL);
			
			
			int sequence2 = vm2->SelectWeightedSequence(ACT_VM_THROW);
			if ((timethrow == NULL) && (sequence2 >= 0))
			{
				vm2->SendViewModelMatchingSequence(sequence2);
				timethrow = (gpGlobals->curtime + vm2->SequenceDuration(sequence2));
				CreateGrenade();
			}
		}

		if ((timethrow < gpGlobals->curtime) && (timethrow != NULL))
		{
			vm2->SetWeaponModel(NULL, NULL);
			UTIL_RemoveImmediate(vm2);
			vm->RemoveEffects(EF_NODRAW);
			int sequence3 = vm->SelectWeightedSequence(ACT_VM_DRAW);
			if ((timedeploy == NULL) && (sequence3 >= 0))
			{
				vm->SendViewModelMatchingSequence(sequence3);
				timedeploy = (gpGlobals->curtime + vm->SequenceDuration(sequence3));
			}
		}

		if ((timedeploy < gpGlobals->curtime) && (timedeploy != NULL))
		{
			//Successfully Thrown A Grenade! Decrement ammo
			RemoveAmmo(1, 12);
			WantThrow = false;
		}
	}
}

void CHL2_Player::CreateGrenade(void)
{
	Vector	vecEye = EyePosition();
	Vector	vForward, vRight;

	EyeVectors(&vForward, &vRight, NULL);
	Vector vecSrc = vecEye + vForward * 18.0f + vRight * 8.0f;
	trace_t tr;

	UTIL_TraceHull(vecEye, vecSrc, -Vector(4.0f + 2, 4.0f + 2, 4.0f + 2), Vector(4.0f + 2, 4.0f + 2, 4.0f + 2),
		PhysicsSolidMaskForEntity(), this, GetCollisionGroup(), &tr);

	if (tr.DidHit())
	{
		vecSrc = tr.endpos;
	}
	vForward[2] += 0.1f;

	Vector vecThrow;
	GetVelocity(&vecThrow, NULL);
	vecThrow += vForward * 1200;
	Fraggrenade_Create(vecSrc, vec3_angle, vecThrow, AngularImpulse(600, random->RandomInt(-1200, 1200), 0), this, 3.0f, false);

	gamestats->Event_WeaponFired(this, true, GetClassname());
}

Okay, you have all of that? It compiles? If not, leave me an angry message telling me why I should not exist and I'll get right onto fixing it. If so, start the game, bind a key to +throwgrenade, give yourself some grenades and a weapon (just use "impulse 101" to give you everything) and see what happens. Hopefully the gun should holster, then throw a grenade then draw the weapon again.

Credits

One tired programmer who hasn't had his coffee fix Valve

Editing/Usage

For all I care, do whatever the bleepin bleep you want with it.