HL2 snippets

From Valve Developer Community
Jump to: navigation, search


Replace zombie's blood with human's blood

Human blood for zombie.

in hl2_dll\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 Head Crab

How to Remove HeadCrab from zombie

in hl2_dll\npc_zombie.cpp look for void CZombie::Spawn( void ) then find this line.

m_fIsHeadless = false;

and simply change it to read this

m_fIsHeadless = true;

Now open hl2_dll\npc_BaseZombie.cpp and change this 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 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 after the comment.

 				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 fx.cpp, under the statement pParticle->m_vecVelocity.Init(); in 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 weapon_crossbow.cpp

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

Don't forget to #include "func_break.h". You may also wish to also your bolts to go through "matWeb" or through a "func_breakable_surf".

Ignite Your 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 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 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 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 Spawn:

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

And if you wish to have a differant 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 CViewRender::SetUpView (view.cpp) search the line

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

and replace it with

m_View.fovViewmodel = abs(g_pClientMode->GetViewModelFOV() - flFOVOffset);

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

On server/hl2/weapon_smg1.cpp, go to the line 48 and replace WeaponRangeAttack2Condition( float flDot, float flDist ) for this:

int		WeaponRangeAttack2Condition();

Now from the lines 231 to 256 (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;

On next go to line 397 (or where is declared the WeaponRangeAttack2Condition() function) and replace it with this:

int CWeaponSMG1::WeaponRangeAttack2Condition()
{
	CAI_BaseNPC *npcOwner = GetOwner()->MyNPCPointer();
 
	//return COND_NONE;
 
/*
	// --------------------------------------------------------
	// Assume things haven't changed too much since last time
	// --------------------------------------------------------
	if (gpGlobals->curtime < m_flNextGrenadeCheck )
		return m_lastGrenadeCondition;
*/
 
	// -----------------------
	// If moving, don't check.
	// -----------------------
	if ( npcOwner->IsMoving())
		return COND_NONE;
 
	CBaseEntity *pEnemy = npcOwner->GetEnemy();
 
	if (!pEnemy)
		return (COND_NONE);
 
	Vector vecEnemyLKP = npcOwner->GetEnemyLKP();
	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 
		// be grenaded.
		// don't throw grenades at anything that isn't on the ground!
		return (COND_NONE);
	}
 
	// --------------------------------------
	//  Get target vector
	// --------------------------------------
	Vector vecTarget;
	if (random->RandomInt(0,1))
	{
		// magically know where they are
		vecTarget = pEnemy->WorldSpaceCenter();
	}
	else
	{
		// toss it to where you last saw them
		vecTarget = vecEnemyLKP;
	}
	// vecTarget = m_vecEnemyLKP + (pEnemy->BodyTarget( GetLocalOrigin() ) - pEnemy->GetLocalOrigin());
	// estimate position
	// vecTarget = vecTarget + pEnemy->m_vecVelocity * 2;
 
 
	if ( ( vecTarget - npcOwner->GetLocalOrigin() ).Length2D() <= COMBINE_MIN_GRENADE_CLEAR_DIST )
	{
		// crap, I don't want to blow myself up
		m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second.
		return (COND_NONE);
	}
 
	// ---------------------------------------------------------------------
	// Are any friendlies near the intended grenade impact area?
	// ---------------------------------------------------------------------
	CBaseEntity *pTarget = NULL;
 
	while ( ( pTarget = gEntList.FindEntityInSphere( pTarget, vecTarget, COMBINE_MIN_GRENADE_CLEAR_DIST ) ) != NULL )
	{
		//Check to see if the default relationship is hatred, and if so intensify that
		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.
			m_flNextGrenadeCheck = gpGlobals->curtime + 1; // one full second.
			return (COND_WEAPON_BLOCKED_BY_FRIEND);
		}
	}
 
	// ---------------------------------------------------------------------
	// 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 );
 
	if (vecToss != vec3_origin)
	{
		m_vecTossVelocity = vecToss;
 
		// don't check again for a while.
		// JAY: HL1 keeps checking - test?
		//m_flNextGrenadeCheck = gpGlobals->curtime;
		m_flNextGrenadeCheck = gpGlobals->curtime + 0.3; // 1/3 second.
		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);
	}
}

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

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 not longer hear the AR2 effect when using the SMG1:

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

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:

if ( m_hContainer )
		{
 
			m_hContainer->SetName( AllocPooledString("dropship_container") );
			m_hContainer->SetAbsOrigin( GetAbsOrigin() );
			m_hContainer->SetAbsAngles( GetAbsAngles() );
			m_hContainer->SetParent(this, 0);
			m_hContainer->SetOwnerEntity(this);
			m_hContainer->Spawn();
 
			IPhysicsObject *pPhysicsObject = m_hContainer->VPhysicsGetObject();
			if ( pPhysicsObject )
			{
				pPhysicsObject->SetShadow( 1e4, 1e4, false, false );
				pPhysicsObject->UpdateShadow( m_hContainer->GetAbsOrigin(), m_hContainer->GetAbsAngles(), false, 0 );
			}
 
			m_hContainer->SetMoveType( MOVETYPE_PUSH );
			m_hContainer->SetGroundEntity( NULL );
 
			// Cache off container's attachment points
			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
			m_poseWeapon_Yaw = m_hContainer->LookupPoseParameter("weapon_yaw");
 
		}

Now your gun should rotate and shoot again!

Fixing the acid damge white flash sticking around bug

This is a very easy fix, I'm surprised no one has patched this. go to shared/hl2/hl2_gamerules.cpp and go to line 209

bool CHalfLife2::Damage_IsTimeBased( int iDmgType )
{
	// 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
}

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