bool CASWTraceFilterShot::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
	Assert( pHandleEntity );
	if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt2 ) )
		return false;
	
	CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );

	// don't collide with other projectiles
	if ( dynamic_cast<CASW_Flamer_Projectile*>( pEntity ) != NULL )
		return false;

	if ( dynamic_cast<CASW_Extinguisher_Projectile*>( pEntity ) != NULL )
		return false;

	if ( pEntity && pEntity->Classify() == CLASS_ASW_MARINE )
	{
		if ( m_bSkipMarines )
			return false;

		CASW_Marine *pMarine = assert_cast<CASW_Marine*>( pEntity );
		if ( m_bSkipRollingMarines && pMarine->GetCurrentMeleeAttack() && pMarine->GetCurrentMeleeAttack()->m_nAttackID == CASW_Melee_System::s_nRollAttackID )
			return false;

		if ( m_bSkipMarinesReflectingProjectiles && pMarine->IsReflectingProjectiles() )
			return false;
	}

	if ( m_bSkipAliens && pEntity && IsAlienClass( pEntity->Classify() ) )
		return false;

	return BaseClass::ShouldHitEntity( pHandleEntity, contentsMask );
}
//------------------------------------------------------------------------------
// Purpose: Implement impact function
//------------------------------------------------------------------------------
void CWeaponCrowbar::Hit( void )
{
	CBasePlayer *pPlayer = ToBasePlayer( GetOwner() );
	
	//Make sound for the AI
	CSoundEnt::InsertSound( SOUND_BULLET_IMPACT, m_traceHit.endpos, 400, 0.2f, pPlayer );

	CBaseEntity	*pHitEntity = m_traceHit.m_pEnt;

	//Apply damage to a hit target
	if ( pHitEntity != NULL )
	{
		Vector hitDirection;
		pPlayer->EyeVectors( &hitDirection, NULL, NULL );
		VectorNormalize( hitDirection );

		ClearMultiDamage();
		CTakeDamageInfo info( GetOwner(), GetOwner(), sk_plr_dmg_crowbar.GetFloat(), DMG_CLUB );
		CalculateMeleeDamageForce( &info, hitDirection, m_traceHit.endpos );
		pHitEntity->DispatchTraceAttack( info, hitDirection, &m_traceHit ); 
		ApplyMultiDamage();

		// Now hit all triggers along the ray that... 
		TraceAttackToTriggers( CTakeDamageInfo( GetOwner(), GetOwner(), sk_plr_dmg_crowbar.GetFloat(), DMG_CLUB ), m_traceHit.startpos, m_traceHit.endpos, hitDirection );

		//Play an impact sound	
		ImpactSound( pHitEntity->Classify() == CLASS_NONE || pHitEntity->Classify() == CLASS_MACHINE );
	}

	//Apply an impact effect
	ImpactEffect();
}
示例#3
0
//=========================================================
// PlayerKilled - someone/something killed this player
//=========================================================
void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{
	DeathNotice( pVictim, pKiller, pInflictor );

	pVictim->m_iDeaths += 1;


	FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 );
	CBasePlayer *peKiller = NULL;
	CBaseEntity *ktmp = CBaseEntity::Instance( pKiller );
	if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) )
		peKiller = (CBasePlayer*)ktmp;

	if ( pVictim->pev == pKiller )  
    {
        // Already increment deaths, don't need to lose frags also
        // killed self
		//pKiller->frags -= 1;
	}
	else if ( ktmp && ktmp->IsPlayer() )
	{
		// if a player dies in a deathmatch game and the killer is a client, award the killer some points
		pKiller->frags += IPointsForKill( peKiller, pVictim );
		
		FireTargets( "game_playerkill", ktmp, ktmp, USE_TOGGLE, 0 );
	}
	else
	{  // killed by the world
		pKiller->frags -= 1;
	}

	// update the scores
	// killed scores
	pVictim->EffectivePlayerClassChanged();

	// killers score, if it's a player
	CBaseEntity *ep = CBaseEntity::Instance( pKiller );
	if ( ep && ep->Classify() == CLASS_PLAYER )
	{
		CBasePlayer *PK = (CBasePlayer*)ep;

		PK->EffectivePlayerClassChanged();

		// let the killer paint another decal as soon as he'd like.
		PK->m_flNextDecalTime = gpGlobals->time;
	}

// Game rules shouldn't know about specific weapons!  Removed this because AvH doesn't have satchel charges.
//#ifndef HLDEMO_BUILD
//	if ( pVictim->HasNamedPlayerItem("weapon_satchel") )
//	{
//		DeactivateSatchels( pVictim );
//	}
//#endif
}
示例#4
0
//=========================================================
// PlayerKilled - someone/something killed this player
//=========================================================
void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{
	DeathNotice( pVictim, pKiller, pInflictor );

	pVictim->m_iDeaths += 1;


	FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 );
	CBasePlayer *peKiller = NULL;
	CBaseEntity *ktmp = CBaseEntity::Instance( pKiller );
	if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) )
		peKiller = (CBasePlayer*)ktmp;

	if ( pVictim->pev == pKiller )  
	{  // killed self
		pKiller->frags -= 1;
	}
	else if ( ktmp && ktmp->IsPlayer() )
	{
		// if a player dies in a deathmatch game and the killer is a client, award the killer some points
		pKiller->frags += IPointsForKill( peKiller, pVictim );
		
		FireTargets( "game_playerkill", ktmp, ktmp, USE_TOGGLE, 0 );
	}
	else
	{  // killed by the world
		pVictim->pev->frags -= 1;
	}

	// update the scores
	// killed scores
	MESSAGE_BEGIN( MSG_ALL, gmsgScoreInfo );
		WRITE_BYTE( ENTINDEX(pVictim->edict()) );
		WRITE_SHORT( pVictim->pev->frags );
		WRITE_SHORT( pVictim->m_iDeaths );
		WRITE_SHORT( pVictim->pev->team );
	MESSAGE_END();

	// killers score, if it's a player
	CBaseEntity *ep = CBaseEntity::Instance( pKiller );
	if ( ep && ep->Classify() == CLASS_PLAYER )
	{
		CBasePlayer *PK = (CBasePlayer*)ep;

		MESSAGE_BEGIN( MSG_ALL, gmsgScoreInfo );
			WRITE_BYTE( ENTINDEX(PK->edict()) );
			WRITE_SHORT( PK->pev->frags );
			WRITE_SHORT( PK->m_iDeaths );
			WRITE_SHORT( PK->pev->team );
		MESSAGE_END();

		// let the killer paint another decal as soon as he'd like.
		PK->m_flNextDecalTime = gpGlobals->time;
	}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input  : *pHandleEntity -
//			contentsMask -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CASW_Trace_Filter_Doors::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
    if ( !StandardFilterRules( pHandleEntity, contentsMask ) )
        return false;

    // Don't test if the game code tells us we should ignore this collision...
    CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
    const CBaseEntity *pEntPass = EntityFromEntityHandle( m_pPassEnt );

    // don't hurt ourself
    if ( pEntPass == pEntity )
        return false;

    if ( !pEntity || pEntity->Classify() != CLASS_ASW_DOOR )
        return false;

    CASW_Door *pDoor = assert_cast<CASW_Door*>( pEntity );
    if ( !pDoor )
        return false;

    if ( m_bRequireLockedOrSealed )
    {
        if ( pDoor->GetSealAmount() > 0 || !pDoor->IsAutoOpen() )
        {
            return true;
        }
        else
        {
            return false;
        }
    }

    return true;
}
示例#6
0
void CFlame::Fly( void )
{
	if ( pev->frags <= 0 || UTIL_PointContents(pev->origin) == CONTENT_WATER )
	{
		FX_Trail( pev->origin, entindex(), PROJ_REMOVE );
		UTIL_Remove( this );
		return;
	}
	pev->frags--;

	entvars_t *pevOwner = VARS(pev->owner);
	CBaseEntity *pOther = NULL;

	while ((pOther = UTIL_FindEntityInSphere( pOther, pev->origin, 50 )) != NULL)
	{
		if (pOther->edict() != pev->owner && pOther->pev->takedamage && pOther->Classify() != CLASS_MACHINE )
		{
			TraceResult tr;
			UTIL_TraceLine( pev->origin, pOther->pev->origin, dont_ignore_monsters, ENT(pev), &tr );
			CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);

			ClearMultiDamage( );
			pEntity->TraceAttack( pevOwner, pev->dmg/3, pev->velocity, &tr, DMG_IGNITE | DMG_NEVERGIB);
			ApplyMultiDamage( pev, pevOwner );
		}
	}
	pev->nextthink = gpGlobals->time + 0.1;
}
示例#7
0
void CWeaponImmolator::ImmolationDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore )
{
	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	Vector		vecSpot;

	Vector vecSrc = vecSrcIn;

	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( vecSrc, flRadius ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() )
	{
		CBaseCombatCharacter *pBCC;

		pBCC = pEntity->MyCombatCharacterPointer();

		if ( pBCC && !pBCC->IsOnFire() )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{
				continue;
			}

			if( pEntity == GetOwner() )
			{
				continue;
			}

			pBCC->Ignite( random->RandomFloat( 15, 20 ) );
		}
	}
}
示例#8
0
void CBlackHole::RadiusDamage( )
{
	CBaseEntity *pEntity = NULL;
	TraceResult	tr;
	float		flAdjustedDamage;
	Vector		vecSpot;

	entvars_t *pevOwner = VARS( pev->owner );
	Vector vecSrc = pev->origin + Vector(0,0,1);

	if ( !pevOwner )
		pevOwner = pev;

	CBaseEntity *pPlayer = CBaseEntity::Instance (pevOwner);

	// iterate on all entities in the vicinity.
	while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, (dmg_chrono_radius.value * (mp_wpn_power.value/100)) )) != NULL)
	{
		if ( pEntity->pev->movetype != MOVETYPE_PUSH && pEntity->pev->movetype != MOVETYPE_NONE && pEntity->pev->movetype != MOVETYPE_FOLLOW && pEntity->pev->movetype != MOVETYPE_NOCLIP )
		{
			if (pEntity == this) continue;

			if (CVAR_GET_FLOAT("mp_noselfdamage")==1 && pEntity->pev == pevOwner )
			continue;

			if (CVAR_GET_FLOAT("mp_noteamdamage")==1 && g_pGameRules->PlayerRelationship(pPlayer, pEntity) == GR_TEAMMATE && pEntity->pev != pevOwner)
			continue;

			vecSpot = pEntity->BodyTarget( vecSrc );
			
			UTIL_TraceLine ( vecSrc, vecSpot, ignore_monsters, ENT(pev), &tr );

			if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() )
			{
				flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length();
			
				if ( flAdjustedDamage <	1 )
					flAdjustedDamage = 1;
			
				Vector m_vel = ( vecSrc - tr.vecEndPos ).Normalize() * ((500 * (dmg_chrono_radius.value * (mp_wpn_power.value/100)) / flAdjustedDamage) + 150);

				if (m_vel.Length() > 1000) m_vel = m_vel.Normalize() * 1000;

				pEntity->pev->velocity = m_vel;

				if (flAdjustedDamage < 200)
				{
					if (!(pEntity->Classify() == CLASS_MACHINE || pEntity->IsBot() || pEntity->IsPlayer() || FClassnameIs(pEntity->pev, "laser_dot") || FClassnameIs(pEntity->pev, "laser_spot")))
					{
						pEntity->Killed ( pevOwner, 0 );
						return;
					}
				}
				
			}
		}
	}
}
示例#9
0
void CASW_Arena::UpdateArena()
{
	// has arena mode just been turned on?
	if ( !m_bStartedArenaMode )
	{
		for ( int i=0; i< m_ArenaAliens.Count(); i++ )
		{
			UTIL_PrecacheOther( m_ArenaAliens[i]->m_szAlienClass );
		}
		m_bStartedArenaMode = true;
		m_ArenaRestTimer.Start( 3.0f );
	}

	if ( m_ArenaShuffleWallsTimer.HasStarted() && m_ArenaShuffleWallsTimer.IsElapsed() )
	{
		TeleportPlayersToSpawn();
		ShuffleArenaWalls();
		m_ArenaShuffleWallsTimer.Invalidate();
		m_ArenaRestTimer.Start( 2.5f );
	}

	if ( m_ArenaRestTimer.HasStarted() && m_ArenaRestTimer.IsElapsed() )
	{
		SpawnArenaWave();
		m_ArenaRestTimer.Invalidate();
	}

	if ( m_ArenaCheckTimer.HasStarted() && m_ArenaCheckTimer.IsElapsed() )
	{
		// count live aliens
		CBaseEntity* pEntity = NULL;
		int iAliens = 0;
		while ((pEntity = gEntList.NextEnt( pEntity )) != NULL)
		{
			if ( pEntity && pEntity->IsNPC() && pEntity->Classify() != CLASS_ASW_MARINE && pEntity->GetHealth() > 0 )
				iAliens++;
		}

		if ( iAliens <= 0 && !m_ArenaRestTimer.HasStarted() && !m_ArenaShuffleWallsTimer.HasStarted() )
		{						
			RefillMarineAmmo();	

			if ( asw_arena_shuffle_walls.GetInt() > 0 && ( m_iArenaWave % asw_arena_shuffle_walls.GetInt() ) == 0 && ( m_iArenaWave != 0 ) )
			{
				UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!\nThe arena is changing...", m_iArenaWave ) );
				m_ArenaShuffleWallsTimer.Start( 5.0f );
			}
			else
			{
				UTIL_CenterPrintAll( UTIL_VarArgs("Wave %d clear!", m_iArenaWave ) );
				m_ArenaRestTimer.Start( RandomFloat( 8, 12 ) );
			}

			m_ArenaCheckTimer.Invalidate();
		}	
	}
}
示例#10
0
// searches for all our named spawners and adds them to the list
void CASW_Spawn_Group::FindSpawners()
{
	for ( int i = 0; i < MAX_SPAWNER_NAMES_PER_GROUP; i++ )
	{
		if ( m_iszSpawnerNames[ i ] == NULL_STRING )
			continue;

		CBaseEntity *pEnt = NULL;
		while ( ( pEnt = gEntList.FindEntityByName( pEnt, m_iszSpawnerNames[ i ], NULL ) ) != NULL )
		{
			if ( pEnt->Classify() != CLASS_ASW_SPAWNER && pEnt->Classify() != CLASS_ASW_HOLDOUT_SPAWNER )
				continue;

			CASW_Base_Spawner *pSpawner = assert_cast<CASW_Base_Spawner*>( pEnt );
			m_hSpawners.AddToTail( pSpawner );
		}
	}
}
//=========================================================
// PlayerKilled - someone/something killed this player
//=========================================================
void CHalfLifeMultiplay :: PlayerKilled( CBasePlayer *pVictim, entvars_t *pKiller, entvars_t *pInflictor )
{
	DeathNotice( pVictim, pKiller, pInflictor );

	FireTargets( "game_playerdie", pVictim, pVictim, USE_TOGGLE, 0 );
	CBasePlayer *peKiller = NULL;
	CBaseEntity *ktmp = CBaseEntity::Instance( pKiller );
	if ( ktmp && (ktmp->Classify() == CLASS_PLAYER) )
		peKiller = (CBasePlayer*)ktmp;

	CBaseEntity *ep = CBaseEntity::Instance( pKiller );
	if ( ep && ep->Classify() == CLASS_PLAYER )
	{
		CBasePlayer *PK = (CBasePlayer*)ep;

		// let the killer paint another decal as soon as he'd like.
		PK->m_flNextDecalTime = gpGlobals->time;
	}
}
示例#12
0
char UTIL_TextureHit(TraceResult *ptr, Vector vecSrc, Vector vecEnd)
{
	char chTextureType;
	float rgfl1[3], rgfl2[3];
	const char *pTextureName;
	char szbuffer[64];
	CBaseEntity *pEntity;

	if( ptr->pHit == NULL )
		return CHAR_TEX_FLESH;

	pEntity = CBaseEntity::Instance(ptr->pHit);

	if (pEntity && pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE)
		return CHAR_TEX_FLESH;

	vecSrc.CopyToArray(rgfl1);
	vecEnd.CopyToArray(rgfl2);

	if (pEntity)
		pTextureName = TRACE_TEXTURE(ENT(pEntity->pev), rgfl1, rgfl2);
	else
		pTextureName = TRACE_TEXTURE(ENT(0), rgfl1, rgfl2);

	if (pTextureName)
	{
		if (*pTextureName == '-' || *pTextureName == '+')
			pTextureName += 2;

		if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ')
			pTextureName++;

		strncpy(szbuffer, pTextureName, sizeof(szbuffer));
		szbuffer[CBTEXTURENAMEMAX - 1] = 0;
		chTextureType = PM_FindTextureType(szbuffer);
	}
	else
		chTextureType = 0;

	return chTextureType;
}
示例#13
0
void CBasePlayer::UpdateStatusBar()
{
	int newSBarState[ SBAR_END ];
	memset( newSBarState, 0, sizeof(newSBarState) );

	// Find an ID Target
	TraceResult tr;
	UTIL_MakeVectors( pev->v_angle + pev->punchangle );
	Vector vecSrc = EyePosition();
	Vector vecEnd = vecSrc + (gpGlobals->v_forward * MAX_ID_RANGE);
	UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, edict(), &tr);

	if (tr.flFraction != 1.0)
	{
		if ( !FNullEnt( tr.pHit ) )
		{
			CBaseEntity *pEntity = CBaseEntity::Instance( tr.pHit );

			if ( pEntity->Classify() == CLASS_PLAYER )
			{
				newSBarState[ SBAR_ID_TARGETNAME ] = ENTINDEX( pEntity->edict() );
				newSBarState[ SBAR_ID_TARGETTEAM ] = FALSE;
					
				m_flStatusBarDisappearDelay = gpGlobals->time + 1.0;
			}
		}
		else if ( m_flStatusBarDisappearDelay > gpGlobals->time )
		{
			// hold the values for a short amount of time after viewing the object
			newSBarState[ SBAR_ID_TARGETNAME ] = m_izSBarState[ SBAR_ID_TARGETNAME ];
			newSBarState[ SBAR_ID_TARGETHEALTH ] = m_izSBarState[ SBAR_ID_TARGETHEALTH ];
			newSBarState[ SBAR_ID_TARGETARMOR ] = m_izSBarState[ SBAR_ID_TARGETARMOR ];
			newSBarState[ SBAR_ID_TARGETTEAM ] = m_izSBarState[ SBAR_ID_TARGETTEAM ];
		}
	}

	// Check values and send if they don't match
	for (int i = 1; i < SBAR_END; i++)
	{
		if ( newSBarState[i] != m_izSBarState[i] )
		{
			MESSAGE_BEGIN( MSG_ONE, gmsgStatusValue, NULL, pev );
				WRITE_BYTE( i );
				WRITE_SHORT( newSBarState[i] );
			MESSAGE_END();

			m_izSBarState[i] = newSBarState[i];
		}
	}
}
示例#14
0
//-----------------------------------------------------------------------------
// Purpose: Trace filter that only hits anything but NPCs and the player
//-----------------------------------------------------------------------------
bool CTraceFilterNoNPCsOrPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
	if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) )
	{
		CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
		if ( !pEntity )
			return NULL;
#ifndef CLIENT_DLL
		if ( pEntity->Classify() == CLASS_PLAYER_ALLY )
			return false; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC()
#endif
		return (!pEntity->IsNPC() && !pEntity->IsPlayer());
	}
	return false;
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : *pHandleEntity - 
//			contentsMask - 
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CASW_Trace_Filter_Door_Crush::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
	if ( !StandardFilterRules( pHandleEntity, contentsMask ) )
		return false;

	if ( !PassServerEntityFilter( pHandleEntity, m_pPassEnt ) )
		return false;

	// Don't test if the game code tells us we should ignore this collision...
	CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
	
	if ( pEntity )
	{
		//Msg("%f CASW_Trace_Filter_Door_Crush::ShouldHitEntity %s\n", gpGlobals->curtime, pEntity->GetClassname());
		if ( !pEntity->ShouldCollide( m_collisionGroup, contentsMask ) )
			return false;
		
		if ( !g_pGameRules->ShouldCollide( m_collisionGroup, pEntity->GetCollisionGroup() ) )
			return false;

		if ( pEntity->Classify() == CLASS_ASW_DOOR )
			return false;

		if ( pEntity->m_takedamage == DAMAGE_NO )
			return false;

		// Translate the vehicle into its driver for damage
		if ( pEntity->GetServerVehicle() != NULL )
		{
			CBaseEntity *pDriver = pEntity->GetServerVehicle()->GetPassenger();

			if ( pDriver != NULL )
			{
				pEntity = pDriver;
			}
		}

		Vector	attackDir = pEntity->WorldSpaceCenter() - m_dmgInfo->GetAttacker()->WorldSpaceCenter();
		VectorNormalize( attackDir );
	
		pEntity->TakeDamage( *m_dmgInfo );

		//CalculateMeleeDamageForce( &info, attackDir, info.GetAttacker()->WorldSpaceCenter(), m_flForceScale );
		return true;
	}

	return false;
}
CASW_Spawn_Group* CASW_Holdout_Wave_Entry::GetSpawnGroup()
{
	if ( m_hSpawnGroup.Get() )
	{
		return m_hSpawnGroup.Get();
	}

	CBaseEntity *pEnt = gEntList.FindEntityByName( NULL, m_iszSpawnGroupName );
	if ( pEnt && pEnt->Classify() == CLASS_ASW_SPAWN_GROUP )
	{
		m_hSpawnGroup = assert_cast<CASW_Spawn_Group*>( pEnt );
		return m_hSpawnGroup.Get();
	}
	Warning( "Holdout wave entry can't find spawngroup %s\n", STRING( m_iszSpawnGroupName ) );
	return NULL;
}
示例#17
0
//-----------------------------------------------------------------------------
// Purpose: Trace filter that only hits NPCs and the player
//-----------------------------------------------------------------------------
bool CTraceFilterOnlyNPCsAndPlayer::ShouldHitEntity( IHandleEntity *pHandleEntity, int contentsMask )
{
	if ( CTraceFilterSimple::ShouldHitEntity( pHandleEntity, contentsMask ) )
	{
		CBaseEntity *pEntity = EntityFromEntityHandle( pHandleEntity );
		if ( !pEntity )
			return false;

#ifdef CSTRIKE_DLL
#ifndef CLIENT_DLL
		if ( pEntity->Classify() == CLASS_PLAYER_ALLY )
			return true; // CS hostages are CLASS_PLAYER_ALLY but not IsNPC()
#endif // !CLIENT_DLL
#endif // CSTRIKE_DLL
		return (pEntity->IsNPC() || pEntity->IsPlayer());
	}
	return false;
}
//------------------------------------------------------------------------------
// Purpose: 
// Input  : 
// Output : 
//------------------------------------------------------------------------------
void CAI_ASW_MeleeBehavior::HullAttack( float flDistance, float flDamage, float flForce, CUtlSymbol &AttackHitSound, CUtlSymbol &AttackMissSound )
{
	Vector vecForceDir;

	CBaseEntity *pHurt = GetOuter()->CheckTraceHullAttack( flDistance, -Vector( 16.0f, 16.0f, 32.0f ), Vector( 16.0f, 16.0f, 32.0f ), flDamage, DMG_SLASH, flForce );
	if ( pHurt )
	{
		SetBehaviorParam( m_StatusParm, 1 );
		// Play a random attack hit sound
		if ( AttackHitSound != UTL_INVAL_SYMBOL )
		{
			GetOuter()->EmitSound( GetSymbolText( AttackHitSound ) );
		}

		// change our sequence to one with the hit in it
		if ( !m_bSecondaryMelee && ( GetActivity() == ACT_MELEE_ATTACK1 ) )
		{
			if ( GetOuter()->HaveSequenceForActivity( (Activity) ACT_MELEE_ATTACK1_HIT ) )
			{
				SetActivity( (Activity) ACT_MELEE_ATTACK1_HIT );
			}
		}
		else if ( m_bSecondaryMelee && ( GetActivity() == ACT_MELEE_ATTACK2 ) )
		{
			if ( GetOuter()->HaveSequenceForActivity( (Activity) ACT_MELEE_ATTACK2_HIT ) )
			{
				SetActivity( (Activity) ACT_MELEE_ATTACK2_HIT );
			}
		}
		if ( m_bKnockdown && pHurt->Classify() == CLASS_ASW_MARINE )
		{
			CASW_Marine *pMarine = static_cast<CASW_Marine*>( pHurt );
			Vector vecImpulse = ( GetOuter()->BodyDirection2D() * m_flKnockdownSpeed ) + Vector( 0, 0, m_flKnockdownLift );
			pMarine->Knockdown( GetOuter(), vecImpulse );
		}
	}
	else
	{
		// Play a miss sound.
		GetOuter()->EmitSound( GetSymbolText( AttackMissSound ) );
		SetBehaviorParam( m_StatusParm, 0 );
	}
}
示例#19
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  :
// Output :
//-----------------------------------------------------------------------------
int CNPC_Houndeye::RangeAttack1Conditions ( float flDot, float flDist )
{
	// I'm not allowed to attack if standing in another hound eye 
	// (note houndeyes allowed to interpenetrate)
	trace_t tr;
	AI_TraceHull( GetAbsOrigin(), GetAbsOrigin() + Vector(0,0,0.1), 
					GetHullMins(), GetHullMaxs(),
					MASK_NPCSOLID, this, COLLISION_GROUP_NONE, &tr );
	if (tr.startsolid)
	{
		CBaseEntity *pEntity = tr.m_pEnt;
		if (pEntity->Classify() == CLASS_HOUNDEYE)
		{
			return( COND_NONE );
		}
	}

	// If I'm really close to my enemy allow me to attack if 
	// I'm facing regardless of next attack time
	if (flDist < 100 && flDot >= 0.3)
	{
		return COND_CAN_RANGE_ATTACK1;
	}
	if ( gpGlobals->curtime < m_flNextAttack )
	{
		return( COND_NONE );
	}
	if (flDist > ( HOUNDEYE_MAX_ATTACK_RADIUS * 0.5 ))
	{
		return COND_TOO_FAR_TO_ATTACK;
	}
	if (flDot < 0.3)
	{
		return COND_NOT_FACING_ATTACK;
	}
	return COND_CAN_RANGE_ATTACK1;
}
示例#20
0
void CGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, CBaseEntity *pEntityIgnore )
{
	const int MASK_RADIUS_DAMAGE = MASK_SHOT&(~CONTENTS_HITBOX);
	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;

	Vector vecSrc = vecSrcIn;

	if ( flRadius )
		falloff = info.GetDamage() / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false;

#ifdef HL2_DLL
	if( bInWater )
	{
		// Only muffle the explosion if deeper than 2 feet in water.
		if( !(UTIL_PointContents(vecSrc + Vector(0, 0, 24)) & MASK_WATER) )
		{
			bInWater = false;
		}
	}
#endif // HL2_DLL
	
	vecSrc.z += 1;// in case grenade is lying on the ground

	float flHalfRadiusSqr = Square( flRadius / 2.0f );

	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( vecSrc, flRadius ); (pEntity = sphere.GetCurrentEntity()) != NULL; sphere.NextEntity() )
	{
		// This value is used to scale damage when the explosion is blocked by some other object.
		float flBlockedDamagePercent = 0.0f;

		if ( pEntity == pEntityIgnore )
			continue;

		if ( pEntity->m_takedamage == DAMAGE_NO )
			continue;

		// UNDONE: this should check a damage mask, not an ignore
		if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
		{// houndeyes don't hurt other houndeyes with their attack
			continue;
		}

		// blast's don't tavel into or out of water
		if (bInWater && pEntity->GetWaterLevel() == 0)
			continue;

		if (!bInWater && pEntity->GetWaterLevel() == 3)
			continue;

		// Check that the explosion can 'see' this entity.
		vecSpot = pEntity->BodyTarget( vecSrc, false );
		UTIL_TraceLine( vecSrc, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

		if( old_radius_damage.GetBool() )
		{
			if ( tr.fraction != 1.0 && tr.m_pEnt != pEntity )
			continue;
		}
		else
		{
			if ( tr.fraction != 1.0 )
			{
				if ( IsExplosionTraceBlocked(&tr) )
				{
					if( ShouldUseRobustRadiusDamage( pEntity ) )
					{
						if( vecSpot.DistToSqr( vecSrc ) > flHalfRadiusSqr )
						{
							// Only use robust model on a target within one-half of the explosion's radius.
							continue;
						}

						Vector vecToTarget = vecSpot - tr.endpos;
						VectorNormalize( vecToTarget );

						// We're going to deflect the blast along the surface that 
						// interrupted a trace from explosion to this target.
						Vector vecUp, vecDeflect;
						CrossProduct( vecToTarget, tr.plane.normal, vecUp );
						CrossProduct( tr.plane.normal, vecUp, vecDeflect );
						VectorNormalize( vecDeflect );

						// Trace along the surface that intercepted the blast...
						UTIL_TraceLine( tr.endpos, tr.endpos + vecDeflect * ROBUST_RADIUS_PROBE_DIST, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );
						//NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 255, 0, false, 10 );

						// ...to see if there's a nearby edge that the explosion would 'spill over' if the blast were fully simulated.
						UTIL_TraceLine( tr.endpos, vecSpot, MASK_RADIUS_DAMAGE, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );
						//NDebugOverlay::Line( tr.startpos, tr.endpos, 255, 0, 0, false, 10 );

						if( tr.fraction != 1.0 && tr.DidHitWorld() )
						{
							// Still can't reach the target.
							continue;
						}
						// else fall through
					}
					else
					{
						continue;
					}
				}

				// UNDONE: Probably shouldn't let children block parents either?  Or maybe those guys should set their owner if they want this behavior?
				// HL2 - Dissolve damage is not reduced by interposing non-world objects
				if( tr.m_pEnt && tr.m_pEnt != pEntity && tr.m_pEnt->GetOwnerEntity() != pEntity )
				{
					// Some entity was hit by the trace, meaning the explosion does not have clear
					// line of sight to the entity that it's trying to hurt. If the world is also
					// blocking, we do no damage.
					CBaseEntity *pBlockingEntity = tr.m_pEnt;
					//Msg( "%s may be blocked by %s...", pEntity->GetClassname(), pBlockingEntity->GetClassname() );

					UTIL_TraceLine( vecSrc, vecSpot, CONTENTS_SOLID, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

					if( tr.fraction != 1.0 )
					{
						continue;
					}
					
					// Now, if the interposing object is physics, block some explosion force based on its mass.
					if( pBlockingEntity->VPhysicsGetObject() )
					{
						const float MASS_ABSORB_ALL_DAMAGE = 350.0f;
						float flMass = pBlockingEntity->VPhysicsGetObject()->GetMass();
						float scale = flMass / MASS_ABSORB_ALL_DAMAGE;

						// Absorbed all the damage.
						if( scale >= 1.0f )
						{
							continue;
						}

						ASSERT( scale > 0.0f );
						flBlockedDamagePercent = scale;
						//Msg("  Object (%s) weighing %fkg blocked %f percent of explosion damage\n", pBlockingEntity->GetClassname(), flMass, scale * 100.0f);
					}
					else
					{
						// Some object that's not the world and not physics. Generically block 25% damage
						flBlockedDamagePercent = 0.25f;
					}
				}
			}
		}
		// decrease damage for an ent that's farther from the bomb.
		flAdjustedDamage = ( vecSrc - tr.endpos ).Length() * falloff;
		flAdjustedDamage = info.GetDamage() - flAdjustedDamage;

		if ( flAdjustedDamage <= 0 )
		{
			continue;
		}

		// the explosion can 'see' this entity, so hurt them!
		if (tr.startsolid)
		{
			// if we're stuck inside them, fixup the position and distance
			tr.endpos = vecSrc;
			tr.fraction = 0.0;
		}
		
		CTakeDamageInfo adjustedInfo = info;
		//Msg("%s: Blocked damage: %f percent (in:%f  out:%f)\n", pEntity->GetClassname(), flBlockedDamagePercent * 100, flAdjustedDamage, flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) );
		adjustedInfo.SetDamage( flAdjustedDamage - (flAdjustedDamage * flBlockedDamagePercent) );

		// Now make a consideration for skill level!
		if( info.GetAttacker() && info.GetAttacker()->IsPlayer() && pEntity->IsNPC() )
		{
			// An explosion set off by the player is harming an NPC. Adjust damage accordingly.
			adjustedInfo.AdjustPlayerDamageInflictedForSkillLevel();
		}

		Vector dir = vecSpot - vecSrc;
		VectorNormalize( dir );

		// If we don't have a damage force, manufacture one
		if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
		{
			if ( !( adjustedInfo.GetDamageType() & DMG_PREVENT_PHYSICS_FORCE ) )
			{
				CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc );
			}
		}
		else
		{
			// Assume the force passed in is the maximum force. Decay it based on falloff.
			float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
			adjustedInfo.SetDamageForce( dir * flForce );
			adjustedInfo.SetDamagePosition( vecSrc );
		}

		if ( tr.fraction != 1.0 && pEntity == tr.m_pEnt )
		{
			ClearMultiDamage( );
			pEntity->DispatchTraceAttack( adjustedInfo, dir, &tr );
			ApplyMultiDamage();
		}
		else
		{
			pEntity->TakeDamage( adjustedInfo );
		}

		// Now hit all triggers along the way that respond to damage... 
		pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, tr.endpos, dir );

#if defined( GAME_DLL )
		if ( info.GetAttacker() && info.GetAttacker()->IsPlayer() && ToBaseCombatCharacter( tr.m_pEnt ) )
		{

			// This is a total hack!!!
			bool bIsPrimary = true;
			CBasePlayer *player = ToBasePlayer( info.GetAttacker() );
			CBaseCombatWeapon *pWeapon = player->GetActiveWeapon();
			if ( pWeapon && FClassnameIs( pWeapon, "weapon_smg1" ) )
			{
				bIsPrimary = false;
			}

			//gamestats->Event_WeaponHit( player, bIsPrimary, (pWeapon != NULL) ? player->GetActiveWeapon()->GetClassname() : "NULL", info );
		}
#endif
	}
}
//------------------------------------------------------------------------------
// Purpose: general purpose routine to collect conditions used both during active
//			and non-active states of the behavior.
//------------------------------------------------------------------------------
void CAI_ASW_HealOtherBehavior::GatherCommonConditions( )
{
	BaseClass::GatherCommonConditions();

//	ClearCondition( COND_HEAL_OTHER_HAS_TARGET );
	SetCondition( COND_HEAL_OTHER_NOT_HAS_TARGET );
	ClearCondition( COND_HEAL_OTHER_TARGET_CHANGED );
	ClearCondition( COND_HEAL_OTHER_TARGET_IN_RANGE );
	ClearCondition( COND_HEAL_OTHER_NOT_TARGET_IN_RANGE );

	CBaseEntity					*pBestObject = NULL;
	int							nPotentialHealthBenefit = 0;

	for( int i = 0; i < GetOuter()->GetNumFactions(); i++ )
	{
		if ( GetOuter()->GetFactionRelationshipDisposition( i ) == D_LIKE )
		{
			CUtlVector< EHANDLE >	*pEntityList = GetOuter()->GetEntitiesInFaction( i );
			for( int j = 0; j < pEntityList->Count(); j++ )
			{
				CBaseEntity	*pEntity = pEntityList->Element( j );
				if ( pEntity->GetHealth() <= 0 )
					continue;
				
				Class_T entClass = pEntity->Classify();
 				if ( entClass == CLASS_ASW_SHAMAN || entClass == CLASS_ASW_BOOMER || entClass == CLASS_ASW_BOOMERMINI
						|| entClass == CLASS_ASW_PARASITE || entClass == CLASS_ASW_BLOB || entClass == CLASS_ASW_BUZZER
						|| entClass == CLASS_ASW_RUNNER )
 				{
 					continue;
 				}

				if ( GetOuter() != pEntity )
				{
					Vector	vDiff = pEntity->GetAbsOrigin() - GetAbsOrigin();
					float	flLengthSquared = vDiff.LengthSqr();

					if ( flLengthSquared <= m_flHealConsiderationDistanceSquared )
						//&& ( !asw_shaman_only_heal_hurt_pEntity->m_iHealth < pEntity->m_iMaxHealth )
					{
						if ( nPotentialHealthBenefit == 0 || ( pEntity->m_iMaxHealth - pEntity->m_iHealth ) > nPotentialHealthBenefit )
						{
							nPotentialHealthBenefit = ( pEntity->m_iMaxHealth - pEntity->m_iHealth );
							pBestObject = pEntity;
						}	
					}
				}
			}
		}
	}

	if ( pBestObject )
	{
		if ( m_hHealTargetEnt != NULL && m_hHealTargetEnt != pBestObject )
		{
			SetCondition( COND_HEAL_OTHER_TARGET_CHANGED );
		}
//		SetCondition( COND_HEAL_OTHER_HAS_TARGET );
		ClearCondition( COND_HEAL_OTHER_NOT_HAS_TARGET );

		m_hHealTargetEnt = pBestObject;
		
		if ( m_hHealTargetEnt.Get() )
		{
			Vector vPredictedPos = m_hHealTargetEnt->GetAbsOrigin() + m_hHealTargetEnt->GetAbsVelocity() * asw_shaman_aim_ahead_time.GetFloat();
			Vector	vDiff = vPredictedPos - GetAbsOrigin();
			if ( vDiff.Length() < m_flHealDistance )
			{
				SetCondition( COND_HEAL_OTHER_TARGET_IN_RANGE );
			}
			else
			{
				SetCondition( COND_HEAL_OTHER_NOT_TARGET_IN_RANGE );
			}
		}
	}
	else
	{
		if ( m_hHealTargetEnt != NULL && m_hHealTargetEnt != pBestObject )
		{
			SetCondition( COND_HEAL_OTHER_TARGET_CHANGED );
		}

		m_hHealTargetEnt = NULL;
	}
}
示例#22
0
CBaseEntity	* CASW_Rocket::FindPotentialTarget( void ) const
{
	float		bestdist = 0;		
	CBaseEntity	*bestent = NULL;

	Vector v_forward, v_right, v_up;
	AngleVectors( GetAbsAngles(), &v_forward, &v_right, &v_up );

	// find the aimtarget nearest us
	int count = AimTarget_ListCount();		
	if ( count )
	{
		CBaseEntity **pList = (CBaseEntity **)stackalloc( sizeof(CBaseEntity *) * count );
		AimTarget_ListCopy( pList, count );

		CTraceFilterSkipTwoEntities filter(this, GetOwnerEntity(), COLLISION_GROUP_NONE);

		for ( int i = 0; i < count; i++ )
		{
			CBaseEntity *pEntity = pList[i];

			if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() )
			{
				//Msg("not alive or not an edict, skipping\n");
				continue;
			}

			if (!pEntity || !pEntity->IsAlive() || !pEntity->edict() || !pEntity->IsNPC() )
			{
				//Msg("not alive or not an edict, skipping\n");
				continue;
			}
	
			// don't autoaim onto marines
			if (pEntity->Classify() == CLASS_ASW_MARINE || pEntity->Classify() == CLASS_ASW_COLONIST)
				continue;

			if ( pEntity->Classify() == CLASS_ASW_PARASITE )
			{
				CASW_Parasite *pParasite = static_cast< CASW_Parasite* >( pEntity );
				if ( pParasite->m_bInfesting )
				{
					continue;
				}
			}

			Vector center = pEntity->BodyTarget( GetAbsOrigin() );
			Vector center_flat = center;
			center_flat.z = GetAbsOrigin().z;

			Vector dir = (center - GetAbsOrigin());
			VectorNormalize( dir );

			Vector dir_flat = (center_flat - GetAbsOrigin());
			VectorNormalize( dir_flat );

			// make sure it's in front of the rocket
			float dot = DotProduct (dir, v_forward );
			//if (dot < 0)
			//{					
			//continue;
			//}

			float dist = (pEntity->GetAbsOrigin() - GetAbsOrigin()).LengthSqr();
			if (dist > ASW_ROCKET_MAX_HOMING_RANGE)
				continue;

			// check another marine isn't between us and the target to reduce FF
			trace_t tr;
			UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr);
			if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE)
				continue;

			// does this critter already have enough rockets to kill it?
			{ 
				CASW_DamageAllocationMgr::IndexType_t assignmentIndex = m_RocketAssigner.Find( pEntity );
				if ( m_RocketAssigner.IsValid(assignmentIndex) )
				{
					if ( m_RocketAssigner[assignmentIndex].m_flAccumulatedDamage > pEntity->GetHealth() )
					{
						continue;
					}
				}
			}


			// check another marine isn't between us and the target to reduce FF
			UTIL_TraceLine(GetAbsOrigin(), pEntity->WorldSpaceCenter(), MASK_SHOT, &filter, &tr);
			if (tr.fraction < 1.0f && tr.m_pEnt != pEntity && tr.m_pEnt && tr.m_pEnt->Classify() == CLASS_ASW_MARINE)
				continue;

			// increase distance if dot isn't towards us
			dist += (1.0f - dot) * 150;	// bias of x units when object is 90 degrees to the side
			if (bestdist == 0 || dist < bestdist)
			{
				bestdist = dist;
				bestent = pEntity;
			}
		}

		if ( bestent && asw_rocket_debug.GetBool() )
		{
			Vector center = bestent->BodyTarget( GetAbsOrigin() );
			Vector center_flat = center;
			center_flat.z = GetAbsOrigin().z;

			Vector dir = (center - GetAbsOrigin());
			VectorNormalize( dir );
			Msg( "Rocket[%d] starting homing in on %s(%d) dir = %f %f %f\n", entindex(), bestent->GetClassname(), bestent->entindex(), VectorExpand( dir ) );
		}
	}

	return bestent;
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CNPC_Monk::GatherConditions()
{
	BaseClass::GatherConditions();

	// Build my zombie danger index!
	m_iNumZombies = 0;
	m_iDangerousZombies = 0;

	AISightIter_t iter;
	CBaseEntity *pSightEnt;
	pSightEnt = GetSenses()->GetFirstSeenEntity( &iter );
	while( pSightEnt )
	{
		if( pSightEnt->Classify() == CLASS_ZOMBIE && pSightEnt->IsAlive() )
		{
			// Is this zombie coming for me?
			CAI_BaseNPC *pZombie = dynamic_cast<CAI_BaseNPC*>(pSightEnt);
			
			if( pZombie && pZombie->GetEnemy() == this )
			{
				m_iNumZombies++;

				// if this zombie is close enough to attack, add him to the zombie danger!
				float flDist;

				flDist = (pZombie->GetAbsOrigin() - GetAbsOrigin()).Length2DSqr();

				if( flDist <= 128.0f * 128.0f )
				{
					m_iDangerousZombies++;
				}
			}
		}

		pSightEnt = GetSenses()->GetNextSeenEntity( &iter );
	}

	if( m_iDangerousZombies >= 3 || (GetEnemy() && GetHealth() < 25) )
	{
		// I see many zombies, or I'm quite injured.
		SpeakIfAllowed( TLK_HELP_ME );
	}

	// NOTE!!!!!! This code assumes grigori is using annabelle!
	ClearCondition(COND_LOW_PRIMARY_AMMO);
	if ( GetActiveWeapon() )
	{
		if ( GetActiveWeapon()->UsesPrimaryAmmo() )
		{
			if (!GetActiveWeapon()->HasPrimaryAmmo() )
			{
				SetCondition(COND_NO_PRIMARY_AMMO);
			}
			else if ( m_NPCState != NPC_STATE_COMBAT && GetActiveWeapon()->UsesClipsForAmmo1() && GetActiveWeapon()->Clip1() < 2 )
			{
				// Don't send a low ammo message unless we're not in combat.
				SetCondition(COND_LOW_PRIMARY_AMMO);
			}
		}
	}
}
示例#24
0
// Add the ability to ignore the world trace
void CSDKGameRules::RadiusDamage( const CTakeDamageInfo &info, const Vector &vecSrcIn, float flRadius, int iClassIgnore, bool bIgnoreWorld )
{
	CBaseEntity *pEntity = NULL;
	trace_t		tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;
	Vector		vecToTarget;
	Vector		vecEndPos;

	Vector vecSrc = vecSrcIn;

	if ( flRadius )
		falloff = info.GetDamage() / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false;

	vecSrc.z += 1;// in case grenade is lying on the ground

	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() )
	{
		if ( pEntity->m_takedamage != DAMAGE_NO )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{// houndeyes don't hurt other houndeyes with their attack
				continue;
			}

			// blast's don't tavel into or out of water
			if (bInWater && pEntity->GetWaterLevel() == 0)
				continue;
			if (!bInWater && pEntity->GetWaterLevel() == 3)
				continue;

			// radius damage can only be blocked by the world
			vecSpot = pEntity->BodyTarget( vecSrc );



			bool bHit = false;

			if( bIgnoreWorld )
			{
				vecEndPos = vecSpot;
				bHit = true;
			}
			else
			{
				UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr );

				if (tr.startsolid)
				{
					// if we're stuck inside them, fixup the position and distance
					tr.endpos = vecSrc;
					tr.fraction = 0.0;
				}

				vecEndPos = tr.endpos;

				if( tr.fraction == 1.0 || tr.m_pEnt == pEntity )
				{
					bHit = true;
				}
			}

			if ( bHit )
			{
				// the explosion can 'see' this entity, so hurt them!
				//vecToTarget = ( vecSrc - vecEndPos );
				vecToTarget = ( vecEndPos - vecSrc );

				// decrease damage for an ent that's farther from the bomb.
				flAdjustedDamage = vecToTarget.Length() * falloff;
				flAdjustedDamage = info.GetDamage() - flAdjustedDamage;

				if ( flAdjustedDamage > 0 )
				{
					CTakeDamageInfo adjustedInfo = info;
					adjustedInfo.SetDamage( flAdjustedDamage );

					Vector dir = vecToTarget;
					VectorNormalize( dir );

					// If we don't have a damage force, manufacture one
					if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin )
					{
						CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5	/* explosion scale! */ );
					}
					else
					{
						// Assume the force passed in is the maximum force. Decay it based on falloff.
						float flForce = adjustedInfo.GetDamageForce().Length() * falloff;
						adjustedInfo.SetDamageForce( dir * flForce );
						adjustedInfo.SetDamagePosition( vecSrc );
					}

					pEntity->TakeDamage( adjustedInfo );

					// Now hit all triggers along the way that respond to damage... 
					pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir );
				}
			}
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponHarpoon::SecondaryAttack( void )
{
	CBasePlayer *pPlayer = dynamic_cast<CBasePlayer*>( GetOwner() );
	if ( !pPlayer )
		return;

	// Slap things in front of me
	Vector vecForward;
	Vector vecBox = Vector( FIST_RANGE,FIST_RANGE,FIST_RANGE * 1.5 ) * 0.5;
	pPlayer->EyeVectors( &vecForward );
	Vector vecSrc = pPlayer->Weapon_ShootPosition( );
	Vector vecCenter = vecSrc + (FIST_RANGE * 0.5 * vecForward);

#if !defined( CLIENT_DLL )
	//NDebugOverlay::Box( vecCenter, -Vector(2,2,2), Vector(2,2,2), 255,0,0,20,2.0);
	//NDebugOverlay::Box( vecCenter, -vecBox, vecBox, 255,255,255,20,2.0);

	bool bHitMetal = false;
	bool bHitPlayer = false;

	CBaseEntity	*pList[100];
	int count = UTIL_EntitiesInBox( pList, 100, vecSrc - vecBox, vecSrc + vecBox, FL_CLIENT|FL_NPC|FL_OBJECT );
	for ( int i = 0; i < count; i++ )
	{
		CBaseEntity *pEntity = pList[i];
		if ( !pEntity->m_takedamage )
			continue;
		if ( pEntity->InSameTeam( this ) )
			continue;

		//NDebugOverlay::EntityBounds( pEntity, 0,255,0,20,2.0);
		if ( pEntity->IsPlayer() )
		{
			bHitPlayer = true;
			CTakeDamageInfo info( this, pPlayer, weapon_fist_damage.GetFloat(), DMG_CLUB );
			CalculateMeleeDamageForce( &info, (pEntity->GetAbsOrigin() - vecCenter), pEntity->GetAbsOrigin() );
			pEntity->TakeDamage( info );
		}
		else if ( pEntity->Classify() == CLASS_MILITARY )
		{
			bHitMetal = true;
			CTakeDamageInfo info( this, pPlayer, weapon_fist_damage_objects.GetFloat(), DMG_CLUB );
			CalculateMeleeDamageForce( &info, (pEntity->GetAbsOrigin() - vecCenter), pEntity->GetAbsOrigin() );
			pEntity->TakeDamage( info );
		}
		else
		{
			bHitMetal = true;
			CTakeDamageInfo info( this, pPlayer, weapon_fist_damage.GetFloat(), DMG_CLUB );
			CalculateMeleeDamageForce( &info, (pEntity->GetAbsOrigin() - vecCenter), pEntity->GetAbsOrigin() );
			pEntity->TakeDamage( info );
		}
	}

	// Play the right sound
	if ( bHitPlayer )
	{
		EmitSound( "Harpoon.HitFlesh" );
	}
	else if ( bHitMetal )
	{
		EmitSound( "Harpoon.HitMetal" );
	}
#endif
}
示例#26
0
void RadiusDamage( Vector vecSrc, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, float flRadius, int iClassIgnore, int bitsDamageType )
{
	CBaseEntity *pEntity = NULL;
	TraceResult	tr;
	float		flAdjustedDamage, falloff;
	Vector		vecSpot;

	if ( flRadius )
		falloff = flDamage / flRadius;
	else
		falloff = 1.0;

	int bInWater = (UTIL_PointContents ( vecSrc ) == CONTENTS_WATER);

	vecSrc.z += 1;// in case grenade is lying on the ground

	if ( !pevAttacker )
		pevAttacker = pevInflictor;

	// iterate on all entities in the vicinity.
	while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecSrc, flRadius )) != NULL)
	{
		if ( pEntity->pev->takedamage != DAMAGE_NO )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{// houndeyes don't hurt other houndeyes with their attack
				continue;
			}

			// blast's don't tavel into or out of water
			if (bInWater && pEntity->pev->waterlevel == 0)
				continue;
			if (!bInWater && pEntity->pev->waterlevel == 3)
				continue;

			vecSpot = pEntity->BodyTarget( vecSrc );
			
			UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pevInflictor), &tr );

			if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() )
			{// the explosion can 'see' this entity, so hurt them!
				if (tr.fStartSolid)
				{
					// if we're stuck inside them, fixup the position and distance
					tr.vecEndPos = vecSrc;
					tr.flFraction = 0.0;
				}
				
				// decrease damage for an ent that's farther from the bomb.
				flAdjustedDamage = ( vecSrc - tr.vecEndPos ).Length() * falloff;
				flAdjustedDamage = flDamage - flAdjustedDamage;
			
				if ( flAdjustedDamage < 0 )
				{
					flAdjustedDamage = 0;
				}
			
				// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
				if (tr.flFraction != 1.0)
				{
					ClearMultiDamage( );
					pEntity->TraceAttack( pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType );
					ApplyMultiDamage( pevInflictor, pevAttacker );
				}
				else
				{
					pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
				}
			}
		}
	}
}
示例#27
0
void CGargantua :: FlameDamage( Vector vecStart, Vector vecEnd, entvars_t *pevInflictor, entvars_t *pevAttacker, float flDamage, int iClassIgnore, int bitsDamageType )
{
	CBaseEntity *pEntity = NULL;
	TraceResult	tr;
	float		flAdjustedDamage;
	Vector		vecSpot;

	Vector vecMid = (vecStart + vecEnd) * 0.5;

	float searchRadius = (vecStart - vecMid).Length();

	Vector vecAim = (vecEnd - vecStart).Normalize( );

	// iterate on all entities in the vicinity.
	while ((pEntity = UTIL_FindEntityInSphere( pEntity, vecMid, searchRadius )) != NULL)
	{
		if ( pEntity->pev->takedamage != DAMAGE_NO )
		{
			// UNDONE: this should check a damage mask, not an ignore
			if ( iClassIgnore != CLASS_NONE && pEntity->Classify() == iClassIgnore )
			{// houndeyes don't hurt other houndeyes with their attack
				continue;
			}
			
			vecSpot = pEntity->BodyTarget( vecMid );
		
			float dist = DotProduct( vecAim, vecSpot - vecMid );
			if (dist > searchRadius)
				dist = searchRadius;
			else if (dist < -searchRadius)
				dist = searchRadius;
			
			Vector vecSrc = vecMid + dist * vecAim;

			UTIL_TraceLine ( vecSrc, vecSpot, dont_ignore_monsters, ENT(pev), &tr );

			if ( tr.flFraction == 1.0 || tr.pHit == pEntity->edict() )
			{// the explosion can 'see' this entity, so hurt them!
				// decrease damage for an ent that's farther from the flame.
				dist = ( vecSrc - tr.vecEndPos ).Length();

				if (dist > 64)
				{
					flAdjustedDamage = flDamage - (dist - 64) * 0.4;
					if (flAdjustedDamage <= 0)
						continue;
				}
				else
				{
					flAdjustedDamage = flDamage;
				}

				// ALERT( at_console, "hit %s\n", STRING( pEntity->pev->classname ) );
				if (tr.flFraction != 1.0)
				{
					ClearMultiDamage( );
					pEntity->TraceAttack( pevInflictor, flAdjustedDamage, (tr.vecEndPos - vecSrc).Normalize( ), &tr, bitsDamageType );
					ApplyMultiDamage( pevInflictor, pevAttacker );
				}
				else
				{
					pEntity->TakeDamage ( pevInflictor, pevAttacker, flAdjustedDamage, bitsDamageType );
				}
			}
		}
	}
}
示例#28
0
int CCrowbar::Swing( int fFirst )
{
	int fDidHit = FALSE;

	TraceResult tr;

	UTIL_MakeVectors (m_pPlayer->pev->v_angle);
	Vector vecSrc	= m_pPlayer->GetGunPosition( );
	Vector vecEnd	= vecSrc + gpGlobals->v_forward * 32;

	UTIL_TraceLine( vecSrc, vecEnd, dont_ignore_monsters, ENT( m_pPlayer->pev ), &tr );

#ifndef CLIENT_DLL
	if ( tr.flFraction >= 1.0 )
	{
		UTIL_TraceHull( vecSrc, vecEnd, dont_ignore_monsters, head_hull, ENT( m_pPlayer->pev ), &tr );
		if ( tr.flFraction < 1.0 )
		{
			// Calculate the point of intersection of the line (or hull) and the object we hit
			// This is and approximation of the "best" intersection
			CBaseEntity *pHit = CBaseEntity::Instance( tr.pHit );
			if ( !pHit || pHit->IsBSPModel() )
				FindHullIntersection( vecSrc, tr, VEC_DUCK_HULL_MIN, VEC_DUCK_HULL_MAX, m_pPlayer->edict() );
			vecEnd = tr.vecEndPos;	// This is the point on the actual surface (the hull could have hit space)
		}
	}
#endif

	PLAYBACK_EVENT_FULL( FEV_NOTHOST, m_pPlayer->edict(), m_usCrowbar, 
	0.0, (float *)&g_vecZero, (float *)&g_vecZero, 0, 0, 0,
	0.0, 0, 0.0 );


	if ( tr.flFraction >= 1.0 )
	{
		if (fFirst)
		{
			// miss
			m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.5;
			
			// player "shoot" animation
			m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
		}
	}
	else
	{
		switch( ((m_iSwing++) % 2) + 1 )
		{
		case 0:
			SendWeaponAnim( CROWBAR_ATTACK1HIT ); break;
		case 1:
			SendWeaponAnim( CROWBAR_ATTACK2HIT ); break;
		case 2:
			SendWeaponAnim( CROWBAR_ATTACK3HIT ); break;
		}

		// player "shoot" animation
		m_pPlayer->SetAnimation( PLAYER_ATTACK1 );
		
#ifndef CLIENT_DLL

		// hit
		fDidHit = TRUE;
		CBaseEntity *pEntity = CBaseEntity::Instance(tr.pHit);

		ClearMultiDamage( );

		if ( (m_flNextPrimaryAttack + 1 < UTIL_WeaponTimeBase() ) || g_pGameRules->IsMultiplayer() )
		{
			// first swing does full damage
			pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar, gpGlobals->v_forward, &tr, DMG_CLUB ); 
		}
		else
		{
			// subsequent swings do half
			pEntity->TraceAttack(m_pPlayer->pev, gSkillData.plrDmgCrowbar / 2, gpGlobals->v_forward, &tr, DMG_CLUB ); 
		}	
		ApplyMultiDamage( m_pPlayer->pev, m_pPlayer->pev );

		// play thwack, smack, or dong sound
		float flVol = 1.0;
		int fHitWorld = TRUE;

		if (pEntity)
		{
			if ( pEntity->Classify() != CLASS_NONE && pEntity->Classify() != CLASS_MACHINE )
			{
				// play thwack or smack sound
				switch( RANDOM_LONG(0,2) )
				{
				case 0:
					EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod1.wav", 1, ATTN_NORM); break;
				case 1:
					EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod2.wav", 1, ATTN_NORM); break;
				case 2:
					EMIT_SOUND(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hitbod3.wav", 1, ATTN_NORM); break;
				}
				m_pPlayer->m_iWeaponVolume = CROWBAR_BODYHIT_VOLUME;
				if ( !pEntity->IsAlive() )
					  return TRUE;
				else
					  flVol = 0.1;

				fHitWorld = FALSE;
			}
		}

		// play texture hit sound
		// UNDONE: Calculate the correct point of intersection when we hit with the hull instead of the line

		if (fHitWorld)
		{
			float fvolbar = TEXTURETYPE_PlaySound(&tr, vecSrc, vecSrc + (vecEnd-vecSrc)*2, BULLET_PLAYER_CROWBAR);

			if ( g_pGameRules->IsMultiplayer() )
			{
				// override the volume here, cause we don't play texture sounds in multiplayer, 
				// and fvolbar is going to be 0 from the above call.

				fvolbar = 1;
			}

			// also play crowbar strike
			switch( RANDOM_LONG(0,1) )
			{
			case 0:
				EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit1.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); 
				break;
			case 1:
				EMIT_SOUND_DYN(ENT(m_pPlayer->pev), CHAN_ITEM, "weapons/cbar_hit2.wav", fvolbar, ATTN_NORM, 0, 98 + RANDOM_LONG(0,3)); 
				break;
			}

			// delay the decal a bit
			m_trHit = tr;
		}

		m_pPlayer->m_iWeaponVolume = flVol * CROWBAR_WALLHIT_VOLUME;
#endif
		m_flNextPrimaryAttack = UTIL_WeaponTimeBase() + 0.25;
		
		SetThink( &CCrowbar::Smack );
		pev->nextthink = UTIL_WeaponTimeBase() + 0.2;

		
	}
	return fDidHit;
}
示例#29
0
//=========================================================
// SonicAttack
//=========================================================
void CNPC_Houndeye::SonicAttack ( void )
{
	EmitSound( "NPC_Houndeye.SonicAttack" );

	if (m_pEnergyWave)
	{
		UTIL_Remove(m_pEnergyWave);
	}
	Vector vFacingDir = EyeDirection3D( );
	m_pEnergyWave = (CEnergyWave*)Create( "energy_wave", EyePosition(), GetLocalAngles() );
	m_flEndEnergyWaveTime = gpGlobals->curtime + 1; //<<TEMP>> magic
	m_pEnergyWave->SetAbsVelocity( 100*vFacingDir );

	CBaseEntity *pEntity = NULL;
	// iterate on all entities in the vicinity.
	for ( CEntitySphereQuery sphere( GetAbsOrigin(), HOUNDEYE_MAX_ATTACK_RADIUS ); pEntity = sphere.GetCurrentEntity(); sphere.NextEntity() )
	{
		if (pEntity->Classify()	== CLASS_HOUNDEYE)
		{
			continue;
		}

		if (pEntity->GetFlags() & FL_NOTARGET)
		{
			continue;
		}

		IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();

		if ( pEntity->m_takedamage != DAMAGE_NO || pPhysicsObject)
		{
			// --------------------------
			// Adjust damage by distance
			// --------------------------
			float flDist = (pEntity->WorldSpaceCenter() - GetAbsOrigin()).Length();
			float flDamageAdjuster = 1-( flDist / HOUNDEYE_MAX_ATTACK_RADIUS );

			// --------------------------
			// Adjust damage by direction
			// --------------------------
			Vector forward;
			AngleVectors( GetAbsAngles(), &forward );
			Vector vEntDir		= (pEntity->GetAbsOrigin() - GetAbsOrigin());
			VectorNormalize(vEntDir);
			float flDotPr		= DotProduct(forward,vEntDir);
			flDamageAdjuster   *= flDotPr;

			if (flDamageAdjuster < 0)
			{
				continue;
			}

			// --------------------------
			// Adjust damage by visibility
			// --------------------------
			if ( !FVisible( pEntity ) )
			{
				if ( pEntity->IsPlayer() )
				{
					// if this entity is a client, and is not in full view, inflict half damage. We do this so that players still 
					// take the residual damage if they don't totally leave the houndeye's effective radius. We restrict it to clients
					// so that monsters in other parts of the level don't take the damage and get pissed.
					flDamageAdjuster *= 0.5;
				}
				else if ( !FClassnameIs( pEntity, "func_breakable" ) && !FClassnameIs( pEntity, "func_pushable" ) ) 
				{
					// do not hurt nonclients through walls, but allow damage to be done to breakables
					continue;
				}
			}

			// ------------------------------
			//  Apply the damage
			// ------------------------------
			if (pEntity->m_takedamage != DAMAGE_NO)
			{
				CTakeDamageInfo info( this, this, flDamageAdjuster * sk_Houndeye_dmg_blast.GetFloat(), DMG_SONIC | DMG_ALWAYSGIB );
				CalculateExplosiveDamageForce( &info, (pEntity->GetAbsOrigin() - GetAbsOrigin()), pEntity->GetAbsOrigin() );

				pEntity->TakeDamage( info );

				// Throw the player
				if ( pEntity->IsPlayer() )
				{
					Vector forward;
					AngleVectors( GetLocalAngles(), &forward );

					Vector vecVelocity = pEntity->GetAbsVelocity();
					vecVelocity	+= forward * 250 * flDamageAdjuster;
					vecVelocity.z = 300 * flDamageAdjuster;
					pEntity->SetAbsVelocity( vecVelocity );
					pEntity->ViewPunch( QAngle(random->RandomInt(-20,20), 0, random->RandomInt(-20,20)) );
				}
			}
			// ------------------------------
			//  Apply physics foces
			// ------------------------------
			IPhysicsObject *pPhysicsObject = pEntity->VPhysicsGetObject();
			if (pPhysicsObject)
			{
				float flForce	= flDamageAdjuster * 8000;
				pPhysicsObject->ApplyForceCenter( (vEntDir+Vector(0,0,0.2)) * flForce );
				pPhysicsObject->ApplyTorqueCenter( vEntDir * flForce );
			}
		}
	}
}
示例#30
0
//-----------------------------------------------------------------------------
// Purpose: Intercept damage and decide whether or not we want to trigger
// Input  : &info - 
//-----------------------------------------------------------------------------
int CWeaponStriderBuster::OnTakeDamage( const CTakeDamageInfo &info )
{
	// If we're attached, any damage from the player makes us trigger
	CBaseEntity *pInflictor = info.GetInflictor();
	CBaseEntity *pAttacker = info.GetAttacker();
	bool bInflictorIsPlayer = ( pInflictor != NULL && pInflictor->IsPlayer() );
	bool bAttackerIsPlayer = ( pAttacker != NULL && pAttacker->IsPlayer() );

	if ( GetParent() && GetParent()->ClassMatches( g_iszVehicle ) )
	{
		return 0;
	}

	// Only take damage from a player, for the moment
	if ( striderbuster_allow_all_damage.GetBool() || ( IsAttachedToStrider() && ( bAttackerIsPlayer || bInflictorIsPlayer ) ) )
	{
		Detonate();
		return 0;
	}

	if ( pAttacker && ( pAttacker->Classify() == CLASS_COMBINE || pAttacker->Classify() == CLASS_COMBINE_HUNTER ) )
	{
		if ( VPhysicsGetObject() && !VPhysicsGetObject()->IsMoveable() )
		{
			return 0;
		}
	}

	// Hunters are able to destroy strider busters
	if ( hunter_hate_held_striderbusters.GetBool() || hunter_hate_thrown_striderbusters.GetBool() || hunter_hate_attached_striderbusters.GetBool() )
	{
		if ( ( GetHealth() > 0 ) && ( pInflictor != NULL ) && FClassnameIs( pInflictor, "hunter_flechette" ) )
		{
			//
			// Flechette impacts don't hurt the striderbuster unless it's attached to a strider,
			// but the explosions always do. This is so that held or thrown striderbusters fly
			// awry because of the flechette, but attached striderbusters break instantly to make
			// the hunters more effective at defending the strider.
			//
			if ( IsAttachedToStrider() || !( info.GetDamageType() & DMG_NEVERGIB ) )
			{
				if( striderbuster_die_detach.GetBool() && IsAttachedToStrider() )
				{
					// Make the buster fall off and break.
					m_takedamage = DAMAGE_NO;

					CNPC_Strider *pStrider = dynamic_cast<CNPC_Strider *>(GetOwnerEntity());
					Assert( pStrider != NULL );
					pStrider->StriderBusterDetached( this );
					DestroyConstraint();

					// Amplify some lateral force.
					Vector vecForce = info.GetDamageForce();
					vecForce.z = 0.0f;
					VPhysicsGetObject()->ApplyForceCenter( vecForce * 5.0f );

					SetContextThink( NULL, gpGlobals->curtime, s_pBusterPingThinkContext );

					SetThink( &CWeaponStriderBuster::BusterDetachThink );
					SetNextThink( gpGlobals->curtime );
					m_iBusterFlags |= STRIDERBUSTER_FLAG_KNOCKED_OFF_STRIDER;

					return 0;
				}
				else
				{
					// Destroy the buster in place
					// Make sure they know it blew up prematurely.
					EmitSound( "Weapon_StriderBuster.Dud_Detonate" );
					DispatchParticleEffect( "striderbuster_break_flechette", GetAbsOrigin(), GetAbsAngles() );
					SetHealth( 0 );

					Shatter( info.GetAttacker() );
					return 0;
				}
			}

			if ( info.GetDamage() < 5 )
			{
				bool bFirst = ( m_CarryAngles.x == 45 && m_CarryAngles.y == 0 && m_CarryAngles.z == 0);
				float sinTime = sin( gpGlobals->curtime );
				bool bSubtractX = ( bFirst ) ? ( sinTime < 0 ) : ( m_CarryAngles.x < 45 );

				m_CarryAngles.x += ( 10.0 + 10.0 * fabsf( sinTime ) + random->RandomFloat( -2.5, 2.5 ) + random->RandomFloat( -2.5, 2.5 ) ) * ( ( bSubtractX ) ? -1.0 : 1.0 );
				m_CarryAngles.y = 15 * ( sin( gpGlobals->curtime ) + cos( gpGlobals->curtime * 0.5 ) ) * .5  + random->RandomFloat( -15, 15 );
				m_CarryAngles.z = 7.5 * ( sin( gpGlobals->curtime ) + sin( gpGlobals->curtime * 2.0 ) ) * .5 + random->RandomFloat( -7.5, 7.5 );
			}

			return 1;
		}
	}
	
	// Allow crushing damage
	if ( info.GetDamageType() & DMG_CRUSH )
		return BaseClass::OnTakeDamage( info );

	return 0;
}