void CPlayerPickupController::Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
{
	if ( ToBasePlayer(pActivator) == m_pPlayer )
	{
		CBaseEntity *pAttached = m_grabController.GetAttached();

		// UNDONE: Use vphysics stress to decide to drop objects
		// UNDONE: Must fix case of forcing objects into the ground you're standing on (causes stress) before that will work
		if ( !pAttached || useType == USE_OFF || (m_pPlayer->m_nButtons & IN_ATTACK2) || m_grabController.ComputeError() > 12 )
		{
			Shutdown();
			return;
		}
		
		//Adrian: Oops, our object became motion disabled, let go!
		IPhysicsObject *pPhys = pAttached->VPhysicsGetObject();
		if ( pPhys && pPhys->IsMoveable() == false )
		{
			Shutdown();
			return;
		}

#if STRESS_TEST
		vphysics_objectstress_t stress;
		CalculateObjectStress( pPhys, pAttached, &stress );
		if ( stress.exertedStress > 250 )
		{
			Shutdown();
			return;
		}
#endif

#ifndef PLAYER_DISABLE_THROWING
		// +ATTACK will throw phys objects
		if ( m_pPlayer->m_nButtons & IN_ATTACK )
		{
			Shutdown( true );
			Vector vecLaunch;
			m_pPlayer->EyeVectors( &vecLaunch );
			// JAY: Scale this with mass because some small objects really go flying
			float massFactor = clamp( pPhys->GetMass(), 0.5, 15 );
			massFactor = RemapVal( massFactor, 0.5, 15, 0.5, 4 );
			vecLaunch *= player_throwforce.GetFloat() * massFactor;

			pPhys->ApplyForceCenter( vecLaunch );
			AngularImpulse aVel = RandomAngularImpulse( -10, 10 ) * massFactor;
			pPhys->ApplyTorqueCenter( aVel );
			return;
		}
#endif
		if ( useType == USE_SET )
		{
			// update position
			m_grabController.UpdateObject( m_pPlayer, 12 );
		}
	}
}
Пример #2
0
//---------------------------------------------------------
// A different bounce behavior for the citizen-modified mine. Detonates at the top of its apex, 
// and does not attempt to track enemies.
//---------------------------------------------------------
void CBounceBomb::CavernBounceThink()
{
	SetNextThink( gpGlobals->curtime + 0.1 );
	StudioFrameAdvance();

	IPhysicsObject *pPhysicsObject = VPhysicsGetObject();

	if ( pPhysicsObject != NULL )
	{
		const float MINE_MAX_JUMP_HEIGHT = 78;

		// Figure out how much headroom the mine has, and hop to within a few inches of that.
		trace_t tr;
		UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() + Vector( 0, 0, MINE_MAX_JUMP_HEIGHT ), MASK_SHOT, this, COLLISION_GROUP_INTERACTIVE, &tr );

		float height;

		if( tr.m_pEnt && tr.m_pEnt->VPhysicsGetObject() )
		{
			// Physics object resting on me. Jump as hard as allowed to try to knock it away.
			height = MINE_MAX_JUMP_HEIGHT;
		}
		else
		{
			height = tr.endpos.z - GetAbsOrigin().z;
			height -= BOUNCEBOMB_RADIUS;
			if ( height < 0.1 )
				height = 0.1;
		}

		float time = sqrt( height / (0.5 * sv_gravity.GetFloat()) );
		float velocity = sv_gravity.GetFloat() * time;

		// or you can just AddVelocity to the object instead of ApplyForce
		float force = velocity * pPhysicsObject->GetMass();

		Vector up;

		GetVectors( NULL, NULL, &up );
		
		pPhysicsObject->Wake();
		pPhysicsObject->ApplyForceCenter( up * force );
		if( m_hNearestNPC )
		{
			Vector vecPredict = m_hNearestNPC->GetSmoothedVelocity();

			pPhysicsObject->ApplyForceCenter( vecPredict * (pPhysicsObject->GetMass() * 0.65f) );
		}

		pPhysicsObject->ApplyTorqueCenter( AngularImpulse( random->RandomFloat( 15, 40 ), random->RandomFloat( 15, 40 ), random->RandomFloat( 30, 60 ) ) );
		
		EmitSound( "NPC_CombineMine.Hop" );

		SetThink( &CBounceBomb::ExplodeThink );
		SetNextThink( gpGlobals->curtime + 0.33f );
	}
}
Пример #3
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 );
			}
		}
	}
}