Difference between revisions of "General SDK Snippets & Fixes"

From Valve Developer Community
Jump to: navigation, search
m (Crossbow Bolt going through glass (func_breakable): Cleaned up a sentence that I added 3 years ago...)
m (Schrodinger's/Quantum crouch fix: Give line numbers, people!)
 
(18 intermediate revisions by 4 users not shown)
Line 1: Line 1:
 
__FORCETOC__
 
__FORCETOC__
  
=Replace zombie's blood with human's blood=
+
=Replace zombie blood with human blood=
Human blood for zombie.
 
  
in hl2_dll\npc_zombie.cpp, go to line 279.
+
Human blood for zombies.
  
<pre>#ifdef HL2_EPISODIC
+
In '''src/game/server/hl2/npc_zombie.cpp''', go to line 279.
      SetBloodColor ( BLOOD_COLOR_ZOMBIE );</pre>
 
  
modify it to look like this:
+
<source lang="cpp">
 +
#ifdef HL2_EPISODIC
 +
      SetBloodColor ( BLOOD_COLOR_ZOMBIE );
 +
</source>
  
<pre>#ifdef HL2_EPISODIC
+
Modify it to look like this:
       SetBloodColor ( BLOOD_COLOR_RED );</pre>
+
<source lang="cpp">
 +
#ifdef HL2_EPISODIC
 +
       SetBloodColor ( BLOOD_COLOR_RED );
 +
</source>
  
 +
=Remove headcrab from zombies=
  
 +
How to remove headcrab from zombies.
  
=Remove Head Crab=
+
In '''src/game/server/hl2/npc_zombie.cpp''' look for <code>void CZombie::Spawn( void )</code> then find this line.
How to Remove HeadCrab from zombie
+
<source lang="cpp">
 +
m_fIsHeadless = false;
 +
</source>
  
in hl2_dll\npc_zombie.cpp look for void CZombie::Spawn( void ) then find this line.
+
and simply change it to this
m_fIsHeadless = false;
+
<source lang="cpp">
and simply change it to read this
+
m_fIsHeadless = true;
m_fIsHeadless = true;
+
</source>
Now open hl2_dll\npc_BaseZombie.cpp and change this section to look like this.
+
 
<pre>
+
Now open '''src/game/server/hl2/npc_BaseZombie.cpp''' and change the <code>HeadcrabRelease_t CNPC_BaseZombie::ShouldReleaseHeadcrab( const CTakeDamageInfo &info, float flDamageThreshold )</code> section to look like this:
 +
<source lang="cpp">
 
//-----------------------------------------------------------------------------
 
//-----------------------------------------------------------------------------
 
// Purpose: A zombie has taken damage. Determine whether he release his headcrab.
 
// Purpose: A zombie has taken damage. Determine whether he release his headcrab.
Line 31: Line 40:
 
HeadcrabRelease_t CNPC_BaseZombie::ShouldReleaseHeadcrab( const CTakeDamageInfo &info, float flDamageThreshold )
 
HeadcrabRelease_t CNPC_BaseZombie::ShouldReleaseHeadcrab( const CTakeDamageInfo &info, float flDamageThreshold )
 
{
 
{
return ( m_iHealth <= 0 && m_fIsTorso && IsChopped( info ) )?RELEASE_RAGDOLL_SLICED_OFF:RELEASE_NO;
+
return ( m_iHealth <= 0 && m_fIsTorso && IsChopped( info ) ) ? RELEASE_RAGDOLL_SLICED_OFF : RELEASE_NO;
 
}
 
}
</pre>
+
</source>
  
=Working CS:S Muzzle Flashes without Model Editing=
+
=Working CS:S muzzle flashes without model editing=
  
In c_baseanimating.cpp, at line 4130 (after the big switch statement), comment out the code so it looks like this
+
In '''src/game/client/c_baseanimating.cpp''', at line 4130 (after the big switch statement), comment out the code so it looks like this
 +
<source lang="cpp">
 +
if ( iAttachment != -1 && m_Attachments.Count() > iAttachment )
 +
{
 +
/*
 +
GetAttachment( iAttachment+1, attachOrigin, attachAngles );
 +
int entId = render->GetViewEntity();
 +
ClientEntityHandle_t hEntity = ClientEntityList().EntIndexToHandle( entId );
 +
tempents->MuzzleFlash( attachOrigin, attachAngles, atoi( options ), hEntity, bFirstPerson );
 +
*/
 +
}
 +
</source>
  
if ( iAttachment != -1 && m_Attachments.Count() > iAttachment )
+
and insert the following code below the commented out code.
{
+
<source lang="cpp">
/*
+
if ( input->CAM_IsThirdPerson() )
GetAttachment( iAttachment+1, attachOrigin, attachAngles );
+
{
int entId = render->GetViewEntity();
+
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
ClientEntityHandle_t hEntity = ClientEntityList().EntIndexToHandle( entId );
+
pWeapon->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
tempents->MuzzleFlash( attachOrigin, attachAngles, atoi( options ), hEntity, bFirstPerson );
+
}
*/
+
else
}
+
{
 
+
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
and insert the following code after the comment.
+
CBaseViewModel *vm = pPlayer->GetViewModel();
 
+
vm->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
<pre>
+
engine->GetViewAngles( attachAngles );
if ( input->CAM_IsThirdPerson() )
+
}
{
+
g_pEffects->MuzzleFlash( attachOrigin, attachAngles, 1.0, MUZZLEFLASH_TYPE_DEFAULT );
C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
+
</source>
pWeapon->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
 
}
 
else
 
{
 
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
 
CBaseViewModel *vm = pPlayer->GetViewModel();
 
vm->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
 
engine->GetViewAngles( attachAngles );
 
}
 
g_pEffects->MuzzleFlash( attachOrigin, attachAngles, 1.0, MUZZLEFLASH_TYPE_DEFAULT );
 
</pre>
 
  
Go to fx.cpp, under the statement <code>pParticle->m_vecVelocity.Init();</code> in <code>FX_MuzzleEffect</code>, place the following code.
+
Go to '''src/game/client/fx.cpp''', under the statement <code>pParticle->m_vecVelocity.Init();</code> in <code>void FX_MuzzleEffect( ... )</code>, place the following code.
 +
<source lang="cpp">
 +
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
 +
Vector velocity = pPlayer->GetLocalVelocity();
 +
pParticle->m_vecVelocity += velocity;
 +
</source>
  
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
+
=Crossbow bolt going through glass (func_breakable)=
Vector velocity = pPlayer->GetLocalVelocity();
 
pParticle->m_vecVelocity += velocity;
 
  
=Crossbow Bolt going through glass (func_breakable)=
+
Open '''src/game/server/hl2/weapon_crossbow.cpp'''
  
Open weapon_crossbow.cpp
+
Start off by adding <code>#include "func_break.h"</code>
  
In <code>CCrossbowBolt::BoltTouch( CBaseEntity *pOther )</code> After :
+
Then in <code>CCrossbowBolt::BoltTouch( CBaseEntity *pOther )</code>, after:
<pre>
+
<source lang="cpp">
 
if ( pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS )
 
if ( pOther->GetCollisionGroup() == COLLISION_GROUP_BREAKABLE_GLASS )
 
return;
 
return;
</pre>
+
</source>
Insert the following code :
+
 
<pre>
+
Insert the following code:
if(FClassnameIs(pOther, "func_breakable"))
+
<source lang="cpp">
 +
if ( FClassnameIs(pOther, "func_breakable") )
 
{
 
{
     CBreakable* pOtherEntity = static_cast<CBreakable*> (pOther);
+
     CBreakable* pOtherEntity = static_cast<CBreakable*>( pOther );
     if(pOtherEntity->GetMaterialType() == matGlass)
+
     if ( pOtherEntity->GetMaterialType() == matGlass )
 
         return;
 
         return;
 
}
 
}
</pre>
+
</source>
Don't forget to #include "func_break.h". This could be taken further, allowing the bolts to go through "matWeb" or through any "func_breakable_surf" for example.
+
 
 +
 
 +
{{todo|This could be taken further, allowing the bolts to go through <code>matWeb</code> or through any '''func_breakable_surf''' for example.}}
 +
 
 +
=Ignite ragdolls=
  
=Ignite Your Ragdolls=
+
In your player's class (<code>CSDKPlayer</code> or <code>CBasePlayer</code>) find the <code>Event_Killed()</code> function. Add this inside of it:
In your player's class (CSDKPlayer or CBasePlayer) find the Event_Killed() function. Add this inside of it:
+
<source lang="cpp">
<pre>
 
 
if( info.GetDamageType() & (DMG_BLAST|DMG_BURN) )
 
if( info.GetDamageType() & (DMG_BLAST|DMG_BURN) )
 
{
 
{
Line 107: Line 123:
 
     }
 
     }
 
}
 
}
</pre>
+
</source>
  
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 you don't have a ragdoll to ignite before that is called, make sure that code is placed after a call to <code>CreateRagdollEntity()</code>.
<code>
+
If you're not doing that, add it in right above the <code>if( info.GetDamageType() & (DMG_BLAST|DMG_BURN) )</code> line.
if( info.GetDamageType() & (DMG_BLAST|DMG_BURN) )
 
</code>
 
line.
 
  
 
=Control height and width of icon progress bars=
 
=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.<br>
 
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.<br>
In the file <code>hud.h</code> add the function declaration:
+
In the file '''src/game/client/hud.h''' add the function declaration:
<pre>
+
<source lang="cpp">
 
void DrawIconProgressBarExt( int x, int y, int w, int h, CHudTexture *icon, CHudTexture *icon2, float percentage, Color &clr, int type );
 
void DrawIconProgressBarExt( int x, int y, int w, int h, CHudTexture *icon, CHudTexture *icon2, float percentage, Color &clr, int type );
</pre>
+
</source>
 +
 
 
Underneath the old declaration:
 
Underneath the old declaration:
<pre>
+
<source lang="cpp">
 
void    DrawIconProgressBar( int x, int y, CHudTexture *icon, CHudTexture *icon2, float percentage, Color& clr, int type );
 
void    DrawIconProgressBar( int x, int y, CHudTexture *icon, CHudTexture *icon2, float percentage, Color& clr, int type );
</pre>
+
</source>
  
Then in <code>hud_redraw.cpp</code> add the function itself:
+
Then in '''src/game/client/hud_redraw.cpp''' add the function itself:
<pre>
+
<source lang="cpp">
 
void CHud::DrawIconProgressBarExt( int x, int y, int w, int h, CHudTexture *icon, CHudTexture *icon2, float percentage, Color& clr, int type )
 
void CHud::DrawIconProgressBarExt( int x, int y, int w, int h, CHudTexture *icon, CHudTexture *icon2, float percentage, Color& clr, int type )
 
{
 
{
Line 156: Line 171:
 
}
 
}
 
}
 
}
</pre>
+
</source>
 +
 
 
This was tested with vertical bars, horizontal bars haven't been tested.
 
This was tested with vertical bars, horizontal bars haven't been tested.
  
 
=Enabling func_precipitation rendering whilst in a point_viewcontrol=
 
=Enabling func_precipitation rendering whilst in a point_viewcontrol=
  
In viewrender.cpp find and delete:
+
In '''src/game/client/viewrender.cpp''' find and delete:
 +
<source lang="cpp">
 +
if ( CurrentViewID() == VIEW_MONITOR )
 +
  return;
 +
</source>
  
if ( CurrentViewID() == VIEW_MONITOR )
+
=Randomizing models=
    return;
 
  
=Randomizing Models=
 
 
Have some global constant char* of every model:
 
Have some global constant char* of every model:
<pre>static const char* modelnames[] = {
+
<source lang="cpp">
"Model1", //0
+
static const char* modelnames[] = {
"Model2", //1
+
  "Model1", // 0
"Model3", //2
+
  "Model2", // 1
};</pre>
+
  "Model3", // 2
And choose one at random in Spawn:
+
};
<pre>SetModel (modelnames[ random->RandomInt( 0, ARRAYSIZE(modelnames) - 1 ) ]);</pre>
+
</source>
 +
 
 +
And choose one at random in the <code>Spawn()</code> function:
 +
<source lang="cpp">
 +
SetModel (modelnames[ random->RandomInt( 0, ARRAYSIZE(modelnames) - 1 ) ]);
 +
</source>
  
 
And if you wish to have a different skin for each model (provided your model was compiled with multiple skins), then you can add:
 
And if you wish to have a different skin for each model (provided your model was compiled with multiple skins), then you can add:
<pre>m_nSkin = random->RandomInt( 0, GetModelPtr()->numskinfamilies() - 1 );</pre>
+
<source lang="cpp">
 +
m_nSkin = random->RandomInt( 0, GetModelPtr()->numskinfamilies() - 1 );
 +
</source>
  
 
=Stopping viewmodels from getting rotated when zooming=
 
=Stopping viewmodels from getting rotated when zooming=
in CViewRender::SetUpView (view.cpp) search the line
+
 
<source lang="cpp">m_View.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset;</source>
+
In '''src/game/client/view.cpp''' find <code>void CViewRender::SetUpViews()</code> and search for the line
 +
<source lang="cpp">
 +
view.fovViewmodel = g_pClientMode->GetViewModelFOV() - flFOVOffset;
 +
</source>
 +
 
 
and replace it with
 
and replace it with
<source lang="cpp">m_View.fovViewmodel = abs(g_pClientMode->GetViewModelFOV() - flFOVOffset);</source>
+
<source lang="cpp">
 +
view.fovViewmodel = fabs(g_pClientMode->GetViewModelFOV() - flFOVOffset);
 +
</source>
 +
 
 
That will simply stop negative FOVs to occur, which were causing a rotating of 180°.
 
That will simply stop negative FOVs to occur, which were causing a rotating of 180°.
  
=Restoring Combine Elite Soldier hability to use the alt fire of the SMG1=
+
=Restoring the Combine Elite Soldier's ability to use the alt-fire of the SMG1=
On server/hl2/weapon_smg1.cpp, go to the line 48 and replace '''''WeaponRangeAttack2Condition( float flDot, float flDist )''''' for this:
 
<source lang="cpp">int WeaponRangeAttack2Condition();</source>
 
  
Now from the lines 231 to 256 (all the disabled code) replace it with this code:
+
In '''src/game/server/hl2/weapon_smg1.cpp''', go to line 48 and replace <code>WeaponRangeAttack2Condition( float flDot, float flDist )</code> with this:
<div style="max-height:10em; overflow:auto;"><source lang="cpp">case EVENT_WEAPON_AR2_ALTFIRE:
+
<source lang="cpp">
{
+
int WeaponRangeAttack2Condition();
CAI_BaseNPC *npc = pOperator->MyNPCPointer();
+
</source>
 +
 
 +
Now from the lines 249 to 274 (all the disabled code) replace it with this code:
 +
<source lang="cpp">
 +
case EVENT_WEAPON_AR2_ALTFIRE:
 +
{
 +
CAI_BaseNPC *npc = pOperator->MyNPCPointer();
  
Vector vecShootOrigin, vecShootDir;
+
Vector vecShootOrigin, vecShootDir;
vecShootOrigin = pOperator->Weapon_ShootPosition();
+
vecShootOrigin = pOperator->Weapon_ShootPosition();
//vecShootDir = npc->GetShootEnemyDir( vecShootOrigin );
+
//vecShootDir = npc->GetShootEnemyDir( vecShootOrigin );
  
//Checks if it can fire the grenade
+
//Checks if it can fire the grenade
WeaponRangeAttack2Condition();
+
WeaponRangeAttack2Condition();
  
Vector vecThrow = m_vecTossVelocity;
+
Vector vecThrow = m_vecTossVelocity;
  
//If on the rare case the vector is 0 0 0, cancel for avoid launching the grenade without speed
+
//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
+
//This should be on WeaponRangeAttack2Condition(), but for some unknown reason return CASE_NONE
//doesn't stop the launch
+
//doesn't stop the launch
if (vecThrow == Vector(0, 0, 0)){
+
if (vecThrow == Vector(0, 0, 0)){
break;
+
break;
}
+
}
  
CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create("grenade_ar2", vecShootOrigin, vec3_angle, npc);
+
CGrenadeAR2 *pGrenade = (CGrenadeAR2*)Create("grenade_ar2", vecShootOrigin, vec3_angle, npc);
pGrenade->SetAbsVelocity( vecThrow );
+
pGrenade->SetAbsVelocity( vecThrow );
pGrenade->SetLocalAngularVelocity(RandomAngle(-400, 400)); //tumble in air
+
pGrenade->SetLocalAngularVelocity(RandomAngle(-400, 400)); //tumble in air
pGrenade->SetMoveType(MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE);
+
pGrenade->SetMoveType(MOVETYPE_FLYGRAVITY, MOVECOLLIDE_FLY_BOUNCE);
  
pGrenade->SetThrower(GetOwner());
+
pGrenade->SetThrower(GetOwner());
  
pGrenade->SetGravity(0.5); // lower gravity since grenade is aerodynamic and engine doesn't know it.
+
pGrenade->SetGravity(0.5); // lower gravity since grenade is aerodynamic and engine doesn't know it.
 
 
pGrenade->SetDamage(sk_plr_dmg_smg1_grenade.GetFloat());
+
pGrenade->SetDamage(sk_plr_dmg_smg1_grenade.GetFloat());
  
if (g_pGameRules->IsSkillLevel(SKILL_HARD))
+
if (g_pGameRules->IsSkillLevel(SKILL_HARD))
{
+
{
m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(2, 3);
+
m_flNextGrenadeCheck = gpGlobals->curtime + RandomFloat(2, 3);
}
+
}
else{
+
else{
m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
+
m_flNextGrenadeCheck = gpGlobals->curtime + 6;// wait six seconds before even looking again to see if a grenade can be thrown.
}
+
}
  
m_iClip2--;
+
m_iClip2--;
}
+
}
break;</source></div>
+
break;
 +
</source>
  
On next go to line 397 (or where is declared the WeaponRangeAttack2Condition() function) and replace it with this:
+
Now go to the <code>int CWeaponSMG1::WeaponRangeAttack2Condition( float flDot, float flDist )</code> function and replace it with this:
<div style="max-height:10em; overflow:auto;"><source lang="cpp">int CWeaponSMG1::WeaponRangeAttack2Condition()
+
<source lang="cpp">
{
+
int CWeaponSMG1::WeaponRangeAttack2Condition()
CAI_BaseNPC *npcOwner = GetOwner()->MyNPCPointer();
+
</source>
  
//return COND_NONE;
+
And near the top of the function, comment out <code>return COND_NONE;</code> like so:
 +
<source lang="cpp">
 +
//return COND_NONE;
 +
</source>
  
/*
+
For the last step, since this is only cosmetic, go to '''src/game/server/hl2/npc_combine.cpp'''.
// --------------------------------------------------------
 
// Assume things haven't changed too much since last time
 
// --------------------------------------------------------
 
if (gpGlobals->curtime < m_flNextGrenadeCheck )
 
return m_lastGrenadeCondition;
 
*/
 
  
// -----------------------
+
On line 381, disable the <code>DevWarning</code> (only in case you don't want to see it neither on DEV mode):
// If moving, don't check.
+
<source lang="cpp">
// -----------------------
+
//DevWarning("**Combine Elite Soldier MUST be equipped with AR2\n");
if ( npcOwner->IsMoving())
+
</source>
return COND_NONE;
 
  
CBaseEntity *pEnemy = npcOwner->GetEnemy();
+
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:
 
+
<source lang="cpp">
if (!pEnemy)
+
if ( pEvent->event == COMBINE_AE_BEGIN_ALTFIRE )
return (COND_NONE);
+
{
 
+
//We want it to use different sounds depending on the weapon
Vector vecEnemyLKP = npcOwner->GetEnemyLKP();
+
if ( FClassnameIs(GetActiveWeapon(), "weapon_ar2") )
if ( !( pEnemy->GetFlags() & FL_ONGROUND ) && pEnemy->GetWaterLevel() == 0 && vecEnemyLKP.z > (GetAbsOrigin().z + WorldAlignMaxs().z) )
 
 
{
 
{
//!!!BUGBUG - we should make this check movetype and make sure it isn't FLY? Players who jump a lot are unlikely to
+
EmitSound( "Weapon_CombineGuard.Special1" );
// be grenaded.
 
// don't throw grenades at anything that isn't on the ground!
 
return (COND_NONE);
 
 
}
 
}
+
else if ( FClassnameIs(GetActiveWeapon(), "weapon_smg1") )
// --------------------------------------
 
//  Get target vector
 
// --------------------------------------
 
Vector vecTarget;
 
if (random->RandomInt(0,1))
 
 
{
 
{
// magically know where they are
+
EmitSound( "Weapon_SMG1.Double" );  
vecTarget = pEnemy->WorldSpaceCenter();
 
 
}
 
}
 
else
 
else
 
{
 
{
// toss it to where you last saw them
+
EmitSound( "Weapon_CombineGuard.Special1" ); // We let this play by default
vecTarget = vecEnemyLKP;
 
 
}
 
}
// vecTarget = m_vecEnemyLKP + (pEnemy->BodyTarget( GetLocalOrigin() ) - pEnemy->GetLocalOrigin());
+
handledEvent = true;
// estimate position
+
}
// vecTarget = vecTarget + pEnemy->m_vecVelocity * 2;
+
</source>
 +
 
 +
=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 add these two lines to the bottom of the <code>if ( m_hContainer )</code> statement:
 +
<source lang="cpp">
 +
m_poseWeapon_Pitch = m_hContainer->LookupPoseParameter( "weapon_pitch" );
 +
m_poseWeapon_Yaw = m_hContainer->LookupPoseParameter( "weapon_yaw" );
 +
</source>
 +
 
 +
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 <code>DMG_ACID</code>, like so:
 +
<source lang="cpp">
 +
return ( ( iDmgType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) ) != 0 );
 +
</source>
 +
 
 +
And it's fixed. Someone, please spread this knowledge.
 +
 
 +
=Schrodinger's/Quantum crouch fix=
 +
 
 +
See: https://wiki.sourceruns.org/wiki/Schrodinger's_Crouch
 +
 
 +
 
 +
Another easy fix.
 +
 
 +
Go to '''src/game/shared/gamemovement.cpp''' then head over to <code>void CGameMovement::FinishDuck( void )</code> (Line 4194)
 +
 
 +
At the very top, you should see this:
 +
<source lang="cpp">
 +
if ( player->GetFlags() & FL_DUCKING )
 +
return;
 +
</source>
 +
 
 +
Now all you have to do is comment it out, that's it!
 +
 
 +
=Simple camera animation implementation for weapons=
  
 +
Go to '''src/game/client/view.cpp''' then head over to <code>void CViewRender::Render( vrect_t *rect )</code>
  
if ( ( vecTarget - npcOwner->GetLocalOrigin() ).Length2D() <= COMBINE_MIN_GRENADE_CLEAR_DIST )
+
Scroll down until you find <code>RenderView( view, nClearFlags, flags );</code>, then paste this code above it:
 +
<source lang="cpp">
 +
if ( pPlayer && pPlayer->InFirstPersonView() && pPlayer->GetViewModel( 0 ) )
 +
{
 +
int iCamAttachment = pPlayer->GetViewModel( 0 )->LookupAttachment( "camera" );
 +
 
 +
if ( iCamAttachment != -1 )
 
{
 
{
// crap, I don't want to blow myself up
+
Vector cameraOrigin = Vector(0, 0, 0);
m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second.
+
QAngle cameraAngles = QAngle(0, 0, 0);
return (COND_NONE);
+
pPlayer->GetViewModel( 0 )->GetAttachmentLocal( iCamAttachment, cameraOrigin, cameraAngles );
 +
view.angles += cameraAngles;
 +
view.origin += cameraOrigin;
 
}
 
}
 +
}
 +
</source>
  
// ---------------------------------------------------------------------
+
{{note|Valve uses the "attach_camera" attachment name in {{l4d2}} and "cam_driver" in {{csgo}}, if you prefer backwards compatibility.}}
// Are any friendlies near the intended grenade impact area?
 
// ---------------------------------------------------------------------
 
CBaseEntity *pTarget = NULL;
 
  
while ( ( pTarget = gEntList.FindEntityInSphere( pTarget, vecTarget, COMBINE_MIN_GRENADE_CLEAR_DIST ) ) != NULL )
+
=A way to suppress the "Node Graph out of Date. Rebuilding..." message=
{
+
 
//Check to see if the default relationship is hatred, and if so intensify that
+
This snippet will hide the message from appearing unless [[Developer|developer]] mode is enabled.
if ( npcOwner->IRelationType( pTarget ) == D_LI )
+
 
{
+
 
// crap, I might blow my own guy up. Don't throw a grenade and don't check again for a while.
+
Go to '''src/game/server/ai_networkmanager.cpp''' then head over to <code>void CAI_NetworkManager::DelayedInit( void )</code>
m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second.
+
 
return (COND_WEAPON_BLOCKED_BY_FRIEND);
+
Scroll down until you find this line of code: (Should be near line 1113)
}
+
<source lang="cpp">
}
+
UTIL_CenterPrintAll( "Node Graph out of Date. Rebuilding...\n" );
 +
</source>
 +
 
 +
And simply change it this:
 +
<source lang="cpp">
 +
if ( developer.GetBool() )
 +
UTIL_CenterPrintAll( "Node Graph out of Date. Rebuilding...\n" );
 +
</source>
 +
 
 +
{{idea|For those of you that want to keep this in but wants to spice things up a bit, replace '''"Rebuilding..."''' with '''"Refunding..."'''}}
 +
 
 +
=Fixing the NPC not blinking bug=
 +
 
 +
In Source SDK 2013 NPC's not being able to blink has been a bug for a while.
  
// ---------------------------------------------------------------------
 
// Check that throw is legal and clear
 
// ---------------------------------------------------------------------
 
// FIXME: speed is based on difficulty...
 
  
Vector vecToss = VecCheckThrow( this, npcOwner->GetLocalOrigin() + Vector(0,0,60), vecTarget, 600.0, 0.5 );
+
Fixing this is as easy as removing a single line of code.
  
if (vecToss != vec3_origin)
+
Go to '''src/game/client/c_baseflex.cpp''' then head over to <code>void C_BaseFlex::SetupWeights( ... )</code>
{
 
m_vecTossVelocity = vecToss;
 
  
// don't check again for a while.
+
And remove the following line:
// JAY: HL1 keeps checking - test?
+
<source lang=cpp>
//m_flNextGrenadeCheck = gpGlobals->curtime;
+
m_iBlink = AddGlobalFlexController( "UH" );
m_flNextGrenadeCheck = gpGlobals->curtime + 0.3; // 1/3 second.
+
</source>
return (COND_CAN_RANGE_ATTACK2);
 
}
 
else
 
{
 
// don't check again for a while.
 
m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second.
 
return (COND_WEAPON_SIGHT_OCCLUDED);
 
}
 
}</source></div>
 
  
For the last step, since this is only cosmetic, go to server/hl2/npc_combine.npc.
+
Congratulations! You have successfully fixed NPC blinking, it was as easy as that.
  
On line 381, disable the DevWarning (only in case you don't want to see it neither on DEV mode):
+
=Fix smooth friction sounds using the incorrect soundhandle=
<source lang="cpp">//DevWarning("**Combine Elite Soldier MUST be equipped with AR2\n");</source>
 
  
Between lines 2321 and 2325, you can replace that part of the code with the following, so you not longer hear the AR2 effect when using the SMG1:
+
Fixes a tiny inconsistency. The bug causes the incorrect sound params to be used.
<source lang="cpp">if ( pEvent->event == COMBINE_AE_BEGIN_ALTFIRE )
 
{
 
//We want it use different sounds depending of the weapon
 
if (FClassnameIs(GetActiveWeapon(), "weapon_ar2"))
 
{
 
EmitSound("Weapon_CombineGuard.Special1");
 
}
 
else if (FClassnameIs(GetActiveWeapon(), "weapon_smg1"))
 
{
 
EmitSound("Weapon_SMG1.Double");
 
}
 
else
 
{
 
EmitSound("Weapon_CombineGuard.Special1"); //We left this play by default
 
}
 
handledEvent = true;
 
}</source>
 
  
=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 901 in server/hl2/npc_combinedropship.cpp and add these two line:
+
Go to '''src/game/shared/physics_shared.cpp''' then head over to <code>void PhysFrictionSound( ... )</code>
<source lang="cpp">if ( m_hContainer )
 
{
 
  
m_hContainer->SetName( AllocPooledString("dropship_container") );
+
Near the bottom of the function, you should see this line of code within an <code>if</code> statement:
m_hContainer->SetAbsOrigin( GetAbsOrigin() );
+
<source lang=cpp>
m_hContainer->SetAbsAngles( GetAbsAngles() );
+
soundHandle = &psurf->soundhandles.scrapeRough;
m_hContainer->SetParent(this, 0);
+
</source>
m_hContainer->SetOwnerEntity(this);
 
m_hContainer->Spawn();
 
  
IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject();
+
Now all you have to do is change that to this:
if ( pPhysicsObject )
+
<source lang=cpp>
{
+
soundHandle = &psurf->soundhandles.scrapeSmooth;
pPhysicsObject->SetShadow( 1e4, 1e4, false, false );
+
</source>
pPhysicsObject->UpdateShadow( m_hContainer->GetAbsOrigin(), m_hContainer->GetAbsAngles(), false, 0 );
 
}
 
  
m_hContainer->SetMoveType( MOVETYPE_PUSH );
+
=Self casting player shadows=
m_hContainer->SetGroundEntity( NULL );
 
  
// Cache off container's attachment points
+
Go to '''src/game/client/hl2/c_basehlplayer.h''' scroll down to <code>bool IsWeaponLowered( void ) { ... }</code>
m_iAttachmentTroopDeploy = m_hContainer->LookupAttachment( "deploy_landpoint" );
 
m_iAttachmentDeployStart = m_hContainer->LookupAttachment( "Deploy_Start" );
 
m_iMuzzleAttachment = m_hContainer->LookupAttachment( "muzzle" );
 
m_iMachineGunBaseAttachment = m_hContainer->LookupAttachment( "gun_base" );
 
// NOTE: gun_ref must have the same position as gun_base, but rotates with the gun
 
m_iMachineGunRefAttachment = m_hContainer->LookupAttachment( "gun_ref" );
 
  
m_poseWeapon_Pitch = m_hContainer->LookupPoseParameter("weapon_pitch"); //added these two lines
+
And right below it add this:
m_poseWeapon_Yaw = m_hContainer->LookupPoseParameter("weapon_yaw");
+
<source lang=cpp>
 +
virtual ShadowType_t ShadowCastType() { return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC; } // Should this object cast shadows?
 +
</source>
  
}</source>
+
=Restoring the Combine Soldier's ability to emit pain sounds=
  
Now your gun should rotate and shoot again!
+
Go to '''src/game/server/hl2/npc_combine.h''' and find <code>void PainSound( void );</code>
  
=Fixing the acid damge white flash sticking around bug=
+
And change it to this:
This is a very easy fix, I'm surprised no one has patched this.
+
<source lang=cpp>
go to shared/hl2/hl2_gamerules.cpp and go to line 209
+
void PainSound( const CTakeDamageInfo &info );
 +
</source>
  
<source lang="cpp">bool CHalfLife2::Damage_IsTimeBased( int iDmgType )
+
Now head over to '''src/game/server/hl2/npc_combine.cpp''' and find <code>void CNPC_Combine::PainSound ( void )</code>
{
 
// Damage types that are time-based.
 
#ifdef HL2_EPISODIC
 
// This makes me think EP2 should have its own rules, but they are #ifdef all over in here.
 
return ( ( iDmgType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) ) != 0 ); //add DMG_ACID to this line
 
#else
 
return BaseClass::Damage_IsTimeBased( iDmgType );
 
#endif
 
}</source>
 
  
And it's fixed. Someone please spread this knowledge.
+
And like before, change it to this:
 +
<source lang=cpp>
 +
void CNPC_Combine::PainSound( const CTakeDamageInfo &info )
 +
</source>
  
  
 
[[Category:Snippets]][[Category:Programming]]
 
[[Category:Snippets]][[Category:Programming]]

Latest revision as of 19:20, 18 April 2020


Replace zombie blood with human blood

Human blood for zombies.

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

#ifdef HL2_EPISODIC
       SetBloodColor ( BLOOD_COLOR_ZOMBIE );

Modify it to look like this:

#ifdef HL2_EPISODIC
       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;
}

Working CS:S muzzle flashes without model editing

In src/game/client/c_baseanimating.cpp, at line 4130 (after the big switch statement), comment out the code so it looks like this

if ( iAttachment != -1 && m_Attachments.Count() > iAttachment )
{
	/*
	GetAttachment( iAttachment+1, attachOrigin, attachAngles );
	int entId = render->GetViewEntity();
	ClientEntityHandle_t hEntity = ClientEntityList().EntIndexToHandle( entId );
	tempents->MuzzleFlash( attachOrigin, attachAngles, atoi( options ), hEntity, bFirstPerson );
	*/
}

and insert the following code below the commented out code.

if ( input->CAM_IsThirdPerson() )
{
	C_BaseCombatWeapon *pWeapon = GetActiveWeapon();
	pWeapon->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
}
else
{
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	CBaseViewModel *vm = pPlayer->GetViewModel();
	vm->GetAttachment( iAttachment+1, attachOrigin, attachAngles );
	engine->GetViewAngles( attachAngles );
}
g_pEffects->MuzzleFlash( attachOrigin, attachAngles, 1.0, MUZZLEFLASH_TYPE_DEFAULT );

Go to src/game/client/fx.cpp, under the statement pParticle->m_vecVelocity.Init(); in void FX_MuzzleEffect( ... ), place the following code.

C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
Vector velocity = pPlayer->GetLocalVelocity();
pParticle->m_vecVelocity += velocity;

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 )
	return;

Insert the following code:

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


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 )
		return;

	//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;

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

		icon->DrawSelfCropped( 
			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 )
   return;

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 );

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:

case EVENT_WEAPON_AR2_ALTFIRE:
{
	CAI_BaseNPC *npc = pOperator->MyNPCPointer();

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

	//Checks if it can fire the grenade
	WeaponRangeAttack2Condition();

	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)){
		break;
	}

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

	pGrenade->SetThrower(GetOwner());

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

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

	m_iClip2--;
}
break;

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" ); 
	}
	else
	{
		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 add these two lines to the bottom of the if ( m_hContainer ) statement:

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:

return ( ( iDmgType & ( DMG_PARALYZE | DMG_NERVEGAS | DMG_POISON | DMG_RADIATION | DMG_DROWNRECOVER | DMG_ACID | DMG_SLOWBURN ) ) != 0 );

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

Schrodinger's/Quantum crouch fix

See: https://wiki.sourceruns.org/wiki/Schrodinger's_Crouch


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 )
	return;

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

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: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..."

Fixing the NPC not blinking bug

In Source SDK 2013 NPC's not being able to blink has been a bug for a while.


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

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

And remove the following line:

m_iBlink = AddGlobalFlexController( "UH" );

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;

Self casting player shadows

Go to src/game/client/hl2/c_basehlplayer.h scroll down to bool IsWeaponLowered( void ) { ... }

And right below it add this:

virtual ShadowType_t ShadowCastType() { return SHADOWS_RENDER_TO_TEXTURE_DYNAMIC; } // Should this object cast shadows?

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 )