Exemplo n.º 1
0
//-----------------------------------------------------------------------------
// Purpose: Handle a collision using our special behavior
//-----------------------------------------------------------------------------
void CWeaponStriderBuster::VPhysicsCollision( int index, gamevcollisionevent_t *pEvent )
{
	// Find out what we hit.
	// Don't do anything special if we're already attached to a strider.
	CBaseEntity *pVictim = pEvent->pEntities[!index];
	if ( pVictim == NULL || m_pConstraint != NULL )
	{
		BaseClass::VPhysicsCollision( index, pEvent );
		return;
	}

	// Don't attach if we're being held by the player
	if ( VPhysicsGetObject()->GetGameFlags() & FVPHYSICS_PLAYER_HELD )
	{
		BaseClass::VPhysicsCollision( index, pEvent );
		return;
	}

	// Save off the speed of the object
	m_flCollisionSpeedSqr = ( pEvent->preVelocity[ index ] ).LengthSqr();

	// Break if we hit the world while going fast enough.
	// Launched duds detonate if they hit the world at any speed.
	if ( pVictim->IsWorld() && ( ( m_bDud && m_bLaunched ) || m_flCollisionSpeedSqr > Square( 500 ) ) )
	{
		m_OnShatter.FireOutput( this, this );
		Shatter( pVictim );
		return;
	}

	// We'll handle this later in our touch call
	if ( ShouldStickToEntity( pVictim ) )
		return;

	// Determine if we should shatter
	CBaseEntity *pOwnerEntity = pVictim->GetOwnerEntity();
	bool bVictimIsStrider = ( ( pOwnerEntity != NULL ) && FClassnameIs( pOwnerEntity, "npc_strider" ) );

	// Break if we hit anything other than a strider while going fast enough.
	// Launched duds detonate if they hit anything other than a strider any speed.
	if ( ( bVictimIsStrider == false ) && ( ( m_bDud && m_bLaunched ) || m_flCollisionSpeedSqr > Square( 500 ) ) )
	{
		m_OnShatter.FireOutput( this, this );
		Shatter( pVictim );
		return;
	}

	// Just bounce
	BaseClass::VPhysicsCollision( index, pEvent );
}
Exemplo n.º 2
0
/*
================
idBrittleFracture::ClientReceiveEvent
================
*/
bool idBrittleFracture::ClientReceiveEvent( int event, int time, const idBitMsg &msg ) {
	idVec3 point, dir;

	switch( event ) {
		case EVENT_PROJECT_DECAL: {
			point[0] = msg.ReadFloat();
			point[1] = msg.ReadFloat();
			point[2] = msg.ReadFloat();
			dir[0] = msg.ReadFloat();
			dir[1] = msg.ReadFloat();
			dir[2] = msg.ReadFloat();
			ProjectDecal( point, dir, time, NULL );
			return true;
		}
		case EVENT_SHATTER: {
			point[0] = msg.ReadFloat();
			point[1] = msg.ReadFloat();
			point[2] = msg.ReadFloat();
			dir[0] = msg.ReadFloat();
			dir[1] = msg.ReadFloat();
			dir[2] = msg.ReadFloat();
			Shatter( point, dir, time );
			return true;
		}
		default: {
			return idEntity::ClientReceiveEvent( event, time, msg );
		}
	}
	return false;
}
Exemplo n.º 3
0
//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CWeaponStriderBuster::Detonate( void )
{
	CBaseEntity *pVictim = GetOwnerEntity();
	if ( !m_bDud && pVictim )
	{
		// Kill the strider (with magic effect)
		CBasePlayer *pPlayer = AI_GetSinglePlayer();
		CTakeDamageInfo info( pPlayer, this, RandomVector( -100.0f, 100.0f ), GetAbsOrigin(), pVictim->GetHealth(), DMG_GENERIC );
		pVictim->TakeDamage( info );

		gamestats->Event_WeaponHit( ToBasePlayer( pPlayer ), true, GetClassname(), info );

		// Tracker 62293:  There's a bug where the inflictor/attacker are reversed when calling TakeDamage above so the player never gets
		//  credit for the strider buster kills.  The code has a bunch of assumptions lower level, so it's safer to just fix it here by 
		//  crediting a kill to the player directly.
		gamestats->Event_PlayerKilledOther( pPlayer, pVictim, info );
	}

	m_OnDetonate.FireOutput( this, this );

	// Explode
	if ( !m_bDud )
	{
		CreateDestroyedEffect();
		EmitSound( "Weapon_StriderBuster.Detonate" );
	}
	else
	{
		DispatchParticleEffect( "striderbuster_explode_dummy_core", GetAbsOrigin(), GetAbsAngles() );
		EmitSound( "Weapon_StriderBuster.Dud_Detonate" );
	}

	// Go to bits!
	Shatter( pVictim );
}
Exemplo n.º 4
0
/*
================
idBrittleFracture::AddForce
================
*/
void idBrittleFracture::AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force ) {


	
	//if ( id < 0 || id >= shards.Num() )
	if ( id < 0)
	{
		return;
	}

	if (id >= shards.Num())
		id = shards.Num() - 1;

	if ( shards[id]->droppedTime != -1 )
	{
		shards[id]->physicsObj.AddForce( 0, point, force );
	}
	//else if ( health <= 0 && !disableFracture )
	else if ( !disableFracture )
	{
		Shatter( point, force, gameLocal.time );

		//StartSound( "snd_shatter", SND_CHANNEL_ANY, 0, false, NULL );

		//BC Trigger any alarm things.
		ActivateTargets( gameLocal.GetLocalPlayer() );
	}
}
Exemplo n.º 5
0
/*
================
idBrittleFracture::Event_Touch
================
*/
void idBrittleFracture::Event_Touch( idEntity* other, trace_t* trace )
{
	idVec3 point, impulse;
	
	// Let the server handle this, clients dont' predict it
	if( common->IsClient() )
	{
		return;
	}
	
	if( !IsBroken() )
	{
		return;
	}
	
	if( trace->c.id < 0 || trace->c.id >= shards.Num() )
	{
		return;
	}
	
	point = shards[trace->c.id]->clipModel->GetOrigin();
	impulse = other->GetPhysics()->GetLinearVelocity() * other->GetPhysics()->GetMass();
	
	Shatter( point, impulse, gameLocal.time );
}
Exemplo n.º 6
0
//Flags as defined by the cob standard
void CUnitScript::Explode(int piece, int flags)
{
	if (!PieceExists(piece)) {
		ShowUnitScriptError("Invalid piecenumber for explode");
		return;
	}

#ifndef _CONSOLE
	const float3 relPos = GetPiecePos(piece);
	const float3 absPos = unit->GetObjectSpacePos(relPos);

#ifdef TRACE_SYNC
	tracefile << "Cob explosion: ";
	tracefile << absPos.x << " " << absPos.y << " " << absPos.z << " " << piece << " " << flags << "\n";
#endif

	if (!(flags & PF_NoHeatCloud)) {
		// Do an explosion at the location first
		new CHeatCloudProjectile(nullptr, absPos, ZeroVector, 30, 30);
	}

	// If this is true, no stuff should fly off
	if (flags & PF_NONE)
		return;

	if (pieces[piece]->original == nullptr)
		return;

	if (flags & PF_Shatter) {
		Shatter(piece, absPos, unit->speed);
		return;
	}

	// This means that we are going to do a full fledged piece explosion!
	float3 baseSpeed = unit->speed;
	float3 explSpeed((0.5f - gs->randFloat()) * 6.0f, 1.2f + gs->randFloat() * 5.0f, (0.5f - gs->randFloat()) * 6.0f);

	if (unit->pos.y - CGround::GetApproximateHeight(unit->pos.x, unit->pos.z) > 15)
		explSpeed.y = (0.5f - gs->randFloat()) * 6.0f;

	if (baseSpeed.SqLength() > 9.0f) {
		const float l  = baseSpeed.Length();
		const float l2 = 3.0f + math::sqrt(l - 3.0f);
		baseSpeed *= (l2 / l);
	}

	explSpeed += baseSpeed;

	const float partSat = projectileHandler->GetParticleSaturation();

	int newFlags = 0;
	newFlags |= (PF_Explode    * ((flags & PF_Explode   ) != 0));
	newFlags |= (PF_Smoke      * ((flags & PF_Smoke     ) != 0) && partSat < 0.95f);
	newFlags |= (PF_Fire       * ((flags & PF_Fire      ) != 0) && partSat < 0.95f);
	newFlags |= (PF_NoCEGTrail * ((flags & PF_NoCEGTrail) != 0));
	newFlags |= (PF_Recursive  * ((flags & PF_Recursive ) != 0));

	new CPieceProjectile(unit, pieces[piece], absPos, explSpeed, newFlags, 0.5f);
#endif
}
Exemplo n.º 7
0
void CNgcSector::plat_set_shatter(bool on)	
{
	if( on && mp_geom )
	{
		Shatter( mp_geom );
	}
}
/*
================
idBrittleFracture::AddForce
================
*/
void idBrittleFracture::AddForce( idEntity *ent, int id, const idVec3 &point, const idVec3 &force ) {
	if( id < 0 || id >= shards.Num() ) {
		return;
	}
	if( shards[id]->droppedTime != -1 ) {
		shards[id]->physicsObj.AddForce( 0, point, force );
	} else if( health <= 0 && !disableFracture ) {
		Shatter( point, force, gameLocal.time );
	}
}
/*
================
idBrittleFracture::Event_Touch
================
*/
void idBrittleFracture::Event_Touch( idEntity *other, trace_t *trace ) {
	idVec3 point, impulse;
	if( !IsBroken() ) {
		return;
	}
	if( trace->c.id < 0 || trace->c.id >= shards.Num() ) {
		return;
	}
	point = shards[trace->c.id]->clipModel->GetOrigin();
	impulse = other->GetPhysics()->GetLinearVelocity() * other->GetPhysics()->GetMass();
	Shatter( point, impulse, gameLocal.time );
}
Exemplo n.º 10
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CWeaponStriderBuster::BusterDetachThink()
{
	SetNextThink( gpGlobals->curtime + 0.1f );

	trace_t tr;
	UTIL_TraceLine( GetAbsOrigin(), GetAbsOrigin() - Vector( 0, 0, 1200), MASK_SOLID_BRUSHONLY, this, COLLISION_GROUP_NONE, &tr );

	if( fabs(tr.startpos.z - tr.endpos.z) < 240.0f )
	{
		SetThink(NULL);
		EmitSound( "Weapon_StriderBuster.Dud_Detonate" );
		DispatchParticleEffect( "striderbuster_break_flechette", GetAbsOrigin(), GetAbsAngles() );
		SetHealth( 0 );
		CTakeDamageInfo info;
		info.SetDamage( 1.0f );
		info.SetAttacker( this );
		info.SetInflictor( this );
		Shatter(this);
	}
}
Exemplo n.º 11
0
//Flags as defined by the cob standard
void CUnitScript::Explode(int piece, int flags)
{
	if (!PieceExists(piece)) {
		ShowScriptError("Invalid piecenumber for explode");
		return;
	}

#ifndef _CONSOLE
	const float3 relPos = GetPiecePos(piece);
	const float3 absPos =
		unit->pos +
		unit->frontdir * relPos.z +
		unit->updir    * relPos.y +
		unit->rightdir * relPos.x;

#ifdef TRACE_SYNC
	tracefile << "Cob explosion: ";
	tracefile << absPos.x << " " << absPos.y << " " << absPos.z << " " << piece << " " << flags << "\n";
#endif

	if (!(flags & PF_NoHeatCloud)) {
		// Do an explosion at the location first
		new CHeatCloudProjectile(absPos, float3(0, 0, 0), 30, 30, NULL);
	}

	// If this is true, no stuff should fly off
	if (flags & PF_NONE) return;

	// This means that we are going to do a full fledged piece explosion!
	float3 baseSpeed = unit->speed + unit->residualImpulse * 0.5f;
	float sql = baseSpeed.SqLength();

	if (sql > 9) {
		const float l  = math::sqrt(sql);
		const float l2 = 3 + math::sqrt(l - 3);
		baseSpeed *= (l2 / l);
	}
	float3 speed((0.5f-gs->randFloat()) * 6.0f, 1.2f + gs->randFloat() * 5.0f, (0.5f - gs->randFloat()) * 6.0f);
	if (unit->pos.y - ground->GetApproximateHeight(unit->pos.x, unit->pos.z) > 15) {
		speed.y = (0.5f - gs->randFloat()) * 6.0f;
	}
	speed += baseSpeed;
	if (speed.SqLength() > 12*12) {
		speed.Normalize();
		speed *= 12;
	}

	/* TODO Push this back. Don't forget to pass the team (color).  */

	if (flags & PF_Shatter) {
		Shatter(piece, absPos, speed);
	}
	else {
		LocalModelPiece* pieceData = pieces[piece];

		if (pieceData->original != NULL) {
			int newflags = PF_Fall; // if they don't fall they could live forever
			if (flags & PF_Explode) { newflags |= PF_Explode; }
			//if (flags & PF_Fall) { newflags |=  PF_Fall; }
			if ((flags & PF_Smoke) && ph->particleSaturation < 1) { newflags |= PF_Smoke; }
			if ((flags & PF_Fire) && ph->particleSaturation < 0.95f) { newflags |= PF_Fire; }
			if (flags & PF_NoCEGTrail) { newflags |= PF_NoCEGTrail; }

			//LOG_L(L_DEBUG, "Exploding %s as %d", script.pieceNames[piece].c_str(), dl);
			new CPieceProjectile(absPos, speed, pieceData, newflags,unit,0.5f);
		}
	}
#endif
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
0
//-----------------------------------------------------------------------------
// Purpose: Physics system has just told us our constraint has been broken
//-----------------------------------------------------------------------------
void CWeaponStriderBuster::InputConstraintBroken( inputdata_t &inputdata )
{
	// Shatter with no real explosion effect
	Shatter( NULL );
}
Exemplo n.º 14
0
/*
================
idBrittleFracture::Restore
================
*/
void idBrittleFracture::Restore( idRestoreGame* savefile )
{

	savefile->ReadInt( health );
	savefile->Read( &fl, sizeof( fl ) );
	LittleBitField( &fl, sizeof( fl ) );
	
	// setttings
	savefile->ReadMaterial( material );
	savefile->ReadMaterial( decalMaterial );
	savefile->ReadFloat( decalSize );
	savefile->ReadFloat( maxShardArea );
	savefile->ReadFloat( maxShatterRadius );
	savefile->ReadFloat( minShatterRadius );
	savefile->ReadFloat( linearVelocityScale );
	savefile->ReadFloat( angularVelocityScale );
	savefile->ReadFloat( shardMass );
	savefile->ReadFloat( density );
	savefile->ReadFloat( friction );
	savefile->ReadFloat( bouncyness );
	savefile->ReadString( fxFracture );
	
	// state
	savefile->ReadBounds( bounds );
	savefile->ReadBool( disableFracture );
	
	savefile->ReadInt( lastRenderEntityUpdate );
	savefile->ReadBool( changed );
	
	savefile->ReadModel( defaultRenderModel );
	
	// Reset all brittle Fractures so we can re-break them if necessary
	fl.takedamage = true;
	CreateFractures( defaultRenderModel );
	FindNeighbours();
	
	int numEvents = 0;
	bool resolveBreaks = false;
	savefile->ReadInt( numEvents );
	for( int i = 0; i < numEvents; i++ )
	{
		fractureEvent_s restoredEvent;
		
		savefile->ReadInt( restoredEvent.eventType );
		savefile->ReadVec3( restoredEvent.point );
		savefile->ReadVec3( restoredEvent.vector );
		
		if( restoredEvent.eventType == EVENT_PROJECT_DECAL )
		{
			ProjectDecal( restoredEvent.point, restoredEvent.vector, gameLocal.time, NULL );
		}
		else
		{
			Shatter( restoredEvent.point, restoredEvent.vector, gameLocal.time );
		}
		resolveBreaks = true;
	}
	
	// remove any dropped shards
	for( int i = 0; resolveBreaks && i < shards.Num(); i++ )
	{
		if( shards[i]->droppedTime != -1 )
		{
			RemoveShard( i );
			i--;
		}
	}
	
	renderEntity.hModel = renderModelManager->AllocModel();
	renderEntity.hModel->InitEmpty( brittleFracture_SnapshotName );
	renderEntity.callback = idBrittleFracture::ModelCallback;
	renderEntity.noShadow = true;
	renderEntity.noSelfShadow = true;
	renderEntity.noDynamicInteractions = false;
	
	savefile->ReadBool( isXraySurface );
}
Exemplo n.º 15
0
//Flags as defined by the cob standard
void CUnitScript::Explode(int piece, int flags)
{
	if (!PieceExists(piece)) {
		ShowUnitScriptError("Invalid piecenumber for explode");
		return;
	}

#ifndef _CONSOLE
	const float3 relPos = GetPiecePos(piece);
	const float3 absPos = unit->GetObjectSpacePos(relPos);

#ifdef TRACE_SYNC
	tracefile << "Cob explosion: ";
	tracefile << absPos.x << " " << absPos.y << " " << absPos.z << " " << piece << " " << flags << "\n";
#endif

	if (!(flags & PF_NoHeatCloud)) {
		// Do an explosion at the location first
		new CHeatCloudProjectile(NULL, absPos, ZeroVector, 30, 30);
	}

	// If this is true, no stuff should fly off
	if (flags & PF_NONE)
		return;

	// This means that we are going to do a full fledged piece explosion!
	float3 baseSpeed = unit->speed;
	float3 explSpeed((0.5f - gs->randFloat()) * 6.0f, 1.2f + gs->randFloat() * 5.0f, (0.5f - gs->randFloat()) * 6.0f);

	if (baseSpeed.SqLength() > 9) {
		const float l  = baseSpeed.Length();
		const float l2 = 3 + math::sqrt(l - 3);
		baseSpeed *= (l2 / l);
	}
	if (unit->pos.y - CGround::GetApproximateHeight(unit->pos.x, unit->pos.z) > 15) {
		explSpeed.y = (0.5f - gs->randFloat()) * 6.0f;
	}

	explSpeed += baseSpeed;

	// limit projectile speed to 12 elmos/frame (why?)
	if (false && explSpeed.SqLength() > (12.0f*12.0f)) {
		explSpeed = (explSpeed.Normalize() * 12.0f);
	}

	if (flags & PF_Shatter) {
		Shatter(piece, absPos, explSpeed);
		return;
	}

	if (pieces[piece]->original == NULL)
		return;

	// projectiles that don't fall could live forever
	int newflags = PF_Fall;

	const float partSat = projectileHandler->GetParticleSaturation();

	if (flags & PF_Explode) { newflags |= PF_Explode; }
	// if (flags & PF_Fall) { newflags |=  PF_Fall; }
	if ((flags & PF_Smoke) && partSat < 1.0f) { newflags |= PF_Smoke; }
	if ((flags & PF_Fire) && partSat < 0.95f) { newflags |= PF_Fire; }
	if (flags & PF_NoCEGTrail) { newflags |= PF_NoCEGTrail; }
	if (flags & PF_Recursive) { newflags |= PF_Recursive; }

	new CPieceProjectile(unit, pieces[piece], absPos, explSpeed, newflags, 0.5f);
#endif
}