General SDK Snippets & Fixes

From Valve Developer Community
Revision as of 17:44, 31 March 2021 by GamerDude27 (talk | contribs) (Added the snippet "Enabling shadow receiving on viewmodels")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search


Replace zombie blood with human blood

Human blood for zombies.

In src/game/server/hl2/npc_zombie.cpp, go to line 279.

       SetBloodColor ( BLOOD_COLOR_ZOMBIE );

Modify it to look like this:

       SetBloodColor ( BLOOD_COLOR_RED );

Remove headcrab from zombies

How to remove headcrab from zombies.

In src/game/server/hl2/npc_zombie.cpp look for void CZombie::Spawn( void ) then find this line.

m_fIsHeadless = false;

and simply change it to this

m_fIsHeadless = true;

Now open src/game/server/hl2/npc_BaseZombie.cpp and change the HeadcrabRelease_t CNPC_BaseZombie::ShouldReleaseHeadcrab( const CTakeDamageInfo &info, float flDamageThreshold ) section to look like this:

// Purpose: A zombie has taken damage. Determine whether he release his headcrab.
// Output : YES, IMMEDIATE, or SCHEDULED (see HeadcrabRelease_t)
HeadcrabRelease_t CNPC_BaseZombie::ShouldReleaseHeadcrab( const CTakeDamageInfo &info, float flDamageThreshold )
	return ( m_iHealth <= 0 && m_fIsTorso && IsChopped( info ) ) ? RELEASE_RAGDOLL_SLICED_OFF : RELEASE_NO;

Fixing imported CS:S weapons in HL2 based mods

Main article: Importing CSS Weapons Into HL2

Crossbow bolt going through glass (func_breakable)

Open src/game/server/hl2/weapon_crossbow.cpp

Start off by adding #include "func_break.h"

Then in CCrossbowBolt::BoltTouch( CBaseEntity *pOther ), after:

if ( pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS )

Insert the following code:

if ( FClassnameIs(pOther, "func_breakable") )
    CBreakable* pOtherEntity = static_cast<CBreakable*>( pOther );
    if ( pOtherEntity->GetMaterialType() == matGlass )

To do: This could be taken further, allowing the bolts to go through matWeb or through any func_breakable_surf for example.

Ignite ragdolls

In your player's class (CSDKPlayer or CBasePlayer) find the Event_Killed() function. Add this inside of it:

if( info.GetDamageType() & (DMG_BLAST|DMG_BURN) )
    if( m_hRagdoll )
        CBaseAnimating *pRagdoll = (CBaseAnimating *)CBaseEntity::Instance(m_hRagdoll);
        if( info.GetDamageType() & (DMG_BURN|DMG_BLAST) )
            pRagdoll->Ignite(45, false, 10 );

If you don't have a ragdoll to ignite before that is called, make sure that code is placed after a call to CreateRagdollEntity(). If you're not doing that, add it in right above the if( info.GetDamageType() & (DMG_BLAST|DMG_BURN) ) line.

Control height and width of icon progress bars

This allows you to control the height and width of progress bars drawn with icons instead of the bars being the same dimensions as the textures.
In the file src/game/client/hud.h add the function declaration:

void	DrawIconProgressBarExt( int x, int y, int w, int h, CHudTexture *icon, CHudTexture *icon2, float percentage, Color &clr, int type );

Underneath the old declaration:

void    DrawIconProgressBar( int x, int y, CHudTexture *icon, CHudTexture *icon2, float percentage, Color& clr, int type );

Then in src/game/client/hud_redraw.cpp add the function itself:

void CHud::DrawIconProgressBarExt( int x, int y, int w, int h, CHudTexture *icon, CHudTexture *icon2, float percentage, Color& clr, int type )
	if ( icon == NULL )

	//Clamp our percentage
	percentage = min( 1.0f, percentage );
	percentage = max( 0.0f, percentage );

	int	height = icon->Height();
	int	width  = icon->Width();

	//Draw a vertical progress bar
	if ( type == HUDPB_VERTICAL )
		int	barOfs = height * percentage;

			x, y,  // Pos
			0, 0, width, barOfs, // Cropped subrect
			w, (h * percentage), clr );

			x, y + (h * percentage), 
			0, barOfs, width, height - barOfs, // Cropped subrect
			w, h - (h * percentage), clr );

This was tested with vertical bars, horizontal bars haven't been tested.

Enabling func_precipitation rendering whilst in a point_viewcontrol

In src/game/client/viewrender.cpp find and delete:

if ( CurrentViewID() == VIEW_MONITOR )

Randomizing models

Have some global constant char* of every model:

static const char* modelnames[] = {
   "Model1", // 0
   "Model2", // 1
   "Model3", // 2

And choose one at random in the Spawn() function:

SetModel (modelnames[ random->RandomInt( 0, ARRAYSIZE(modelnames) - 1 ) ]);

And if you wish to have a different skin for each model (provided your model was compiled with multiple skins), then you can add:

m_nSkin = random->RandomInt( 0, GetModelPtr()->numskinfamilies() - 1 );

Simple camera animation implementation for weapons

Go to src/game/client/view.cpp then head over to void CViewRender::Render( vrect_t *rect )

Scroll down until you find RenderView( view, nClearFlags, flags );, then paste this code above it:

if ( pPlayer && pPlayer->InFirstPersonView() && pPlayer->GetViewModel( 0 ) )
	int iCamAttachment = pPlayer->GetViewModel( 0 )->LookupAttachment( "camera" );

	if ( iCamAttachment != -1 )
		Vector cameraOrigin = Vector(0, 0, 0);
		QAngle cameraAngles = QAngle(0, 0, 0);
		pPlayer->GetViewModel( 0 )->GetAttachmentLocal( iCamAttachment, cameraOrigin, cameraAngles );
		view.angles += cameraAngles;
		view.origin += cameraOrigin;
Note.png Note: Valve uses the "attach_camera" attachment name in Left 4 Dead 2 and "cam_driver" in Counter-Strike: Global Offensive, if you prefer backwards compatibility.

A way to suppress the "Node Graph out of Date. Rebuilding..." message

This snippet will hide the message from appearing unless developer mode is enabled.

Go to src/game/server/ai_networkmanager.cpp then head over to void CAI_NetworkManager::DelayedInit( void )

Scroll down until you find this line of code: (Should be near line 1113)

UTIL_CenterPrintAll( "Node Graph out of Date. Rebuilding...\n" );

And simply change it this:

if ( developer.GetBool() )
	UTIL_CenterPrintAll( "Node Graph out of Date. Rebuilding...\n" );
Idea:For those of you that want to keep this in but wants to spice things up a bit, replace "Rebuilding..." with "Refunding..."

Self casting player shadows

Go to src/game/client/c_baseplayer.h, scroll down until you find

virtual ShadowType_t ShadowCastType() { return SHADOWS_NONE; }

and simply change that to:

virtual ShadowType_t ShadowCastType() { return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC; }

Your playermodel (by default player.mdl) should now cast shadows.

Enabling shadow receiving on viewmodels

Go to src/game/shared/baseviewmodel_shared.h, scroll down until you find

virtual bool ShouldReceiveProjectedTextures( int flags )
	return false;

and simply change that to:

virtual bool ShouldReceiveProjectedTextures( int flags )
	return true;

Your viewmodels should now be able to receive shadows.


Stopping viewmodels from getting rotated when zooming

In src/game/client/view.cpp find void CViewRender::SetUpViews() and search for the line

view.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset;

and replace it with

view.fovViewmodel = fabs( g_pClientMode->GetViewModelFOV() - flFOVOffset );

That will simply stop negative FOVs to occur, which were causing a rotating of 180°.

Restoring the Combine Elite Soldier's ability to use the alt-fire of the SMG1

In src/game/server/hl2/weapon_smg1.cpp, go to line 48 and replace WeaponRangeAttack2Condition( float flDot, float flDist ) with this:

int WeaponRangeAttack2Condition();

Now from the lines 249 to 274 (all the disabled code) replace it with this code:

	CAI_BaseNPC *npc = pOperator->MyNPCPointer();

	Vector vecShootOrigin, vecShootDir;
	vecShootOrigin = pOperator->Weapon_ShootPosition();
	//vecShootDir = npc->GetShootEnemyDir( vecShootOrigin );

	//Checks if it can fire the grenade

	Vector vecThrow = m_vecTossVelocity;

	//If on the rare case the vector is 0 0 0, cancel for avoid launching the grenade without speed
	//This should be on WeaponRangeAttack2Condition(), but for some unknown reason return CASE_NONE
	//doesn't stop the launch
	if (vecThrow == Vector(0, 0, 0)){

	CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create("grenade_ar2", vecShootOrigin, vec3_angle, npc);
	pGrenade->SetAbsVelocity( vecThrow );
	pGrenade->SetLocalAngularVelocity(RandomAngle(-400, 400)); //tumble in air


	pGrenade->SetGravity(0.5); // lower gravity since grenade is aerodynamic and engine doesn't know it.

	if (g_pGameRules->IsSkillLevel(SKILL_HARD))
		m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(2, 3);
		m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.


Now go to the int CWeaponSMG1::WeaponRangeAttack2Condition( float flDot, float flDist ) function and replace it with this:

int CWeaponSMG1::WeaponRangeAttack2Condition()

And near the top of the function, comment out return COND_NONE; like so:

//return COND_NONE;

For the last step, since this is only cosmetic, go to src/game/server/hl2/npc_combine.cpp.

On line 381, disable the DevWarning (only in case you don't want to see it neither on DEV mode):

//DevWarning("**Combine Elite Soldier MUST be equipped with AR2\n");

Between lines 2321 and 2325, you can replace that part of the code with the following, so you no longer hear the AR2 effect when using the SMG1:

if ( pEvent->event == COMBINE_AE_BEGIN_ALTFIRE )
	//We want it to use different sounds depending on the weapon
	if ( FClassnameIs(GetActiveWeapon(), "weapon_ar2") )
		EmitSound( "Weapon_CombineGuard.Special1" );
	else if ( FClassnameIs(GetActiveWeapon(), "weapon_smg1") )
		EmitSound( "Weapon_SMG1.Double" ); 
		EmitSound( "Weapon_CombineGuard.Special1" ); // We let this play by default
	handledEvent = true;

Restoring dropship container gun rotation functionality

This is to make it so that the gun on the combine dropship can rotate again

Go to line 873 in src/game/server/hl2/npc_combinedropship.cpp and in the PopulatePoseParameters( void ) function replace the following lines

m_poseWeapon_Pitch = LookupPoseParameter( "weapon_pitch" );
m_poseWeapon_Yaw = LookupPoseParameter( "weapon_yaw" );


m_poseWeapon_Pitch = m_hContainer->LookupPoseParameter( "weapon_pitch" );
m_poseWeapon_Yaw = m_hContainer->LookupPoseParameter( "weapon_yaw" );

Now your gun should rotate and shoot again!

Fixing the acid damage white flash sticking around bug

This is a very easy fix, I'm surprised no one has patched this.

Go to src/game/shared/hl2/hl2_gamerules.cpp and at line 209 add DMG_ACID, like so:


And it's fixed. Someone, please spread this knowledge.

Schrodinger's/Quantum crouch fix


Another easy fix.

Go to src/game/shared/gamemovement.cpp then head over to void CGameMovement::FinishDuck( void ) (Line 4194)

At the very top, you should see this:

if ( player->GetFlags() & FL_DUCKING )

Now all you have to do is comment it out, that's it!

Fixing the NPC not blinking bug

NPCs not being able to blink has been a bug for mods ever since the Steampipe update. It was fixed in an update for HL2 + episodes on the 26th of September 2019, but the code was never pushed to the public repo.

Fixing this is as easy as correcting a single line of code.

Go to src/game/client/c_baseflex.cpp then head over to the void C_BaseFlex::SetupWeights( ... ) function.

Then at line 1152 correct the following line of code from:

m_iBlink = AddGlobalFlexController( "UH" );


m_iBlink = AddGlobalFlexController( "blink" );

Congratulations! You have successfully fixed NPC blinking, it was as easy as that.

Fix smooth friction sounds using the incorrect soundhandle

Fixes a tiny inconsistency. The bug causes the incorrect sound params to be used.

Go to src/game/shared/physics_shared.cpp then head over to void PhysFrictionSound( ... )

Near the bottom of the function, you should see this line of code within an if statement:

soundHandle = &psurf->soundhandles.scrapeRough;

Now all you have to do is change that to this:

soundHandle = &psurf->soundhandles.scrapeSmooth;

Restoring the Combine Soldier's ability to emit pain sounds

Go to src/game/server/hl2/npc_combine.h and find void PainSound( void );

And change it to this:

void PainSound( const CTakeDamageInfo &info );

Now head over to src/game/server/hl2/npc_combine.cpp and find void CNPC_Combine::PainSound ( void )

And like before, change it to this:

void CNPC_Combine::PainSound( const CTakeDamageInfo &info )