Example #1
0
/*
================
idBrittleFracture::Shatter
================
*/
void idBrittleFracture::Shatter( const idVec3 &point, const idVec3 &impulse, const int time ) {
	int i;
	idVec3 dir;
	shard_t *shard;
	float m;

	if ( gameLocal.isServer ) {
		idBitMsg	msg;
		byte		msgBuf[MAX_EVENT_PARAM_SIZE];

		msg.Init( msgBuf, sizeof( msgBuf ) );
		msg.BeginWriting();
		msg.WriteFloat( point[0] );
		msg.WriteFloat( point[1] );
		msg.WriteFloat( point[2] );
		msg.WriteFloat( impulse[0] );
		msg.WriteFloat( impulse[1] );
		msg.WriteFloat( impulse[2] );
		ServerSendEvent( EVENT_SHATTER, &msg, true, -1 );
	}

	if ( time > ( gameLocal.time - SHARD_ALIVE_TIME ) ) {
		StartSound( "snd_shatter", SND_CHANNEL_ANY, 0, false, NULL );
	}

	if ( !IsBroken() ) {
		Break();
	}

	if ( fxFracture.Length() ) {
		idEntityFx::StartFx( fxFracture, &point, &GetPhysics()->GetAxis(), this, true );
	}

	dir = impulse;
	m = dir.Normalize();

	for ( i = 0; i < shards.Num(); i++ ) {
		shard = shards[i];

		if ( shard->droppedTime != -1 ) {
			continue;
		}

		if ( ( shard->clipModel->GetOrigin() - point ).LengthSqr() > Square( maxShatterRadius ) ) {
			continue;
		}

		DropShard( shard, point, dir, m, time );
	}

	DropFloatingIslands( point, impulse, time );

	//trigger it.
	if (!firedTargets)
	{
		firedTargets = true;
		ActivateTargets(this);
	}
}
Example #2
0
/*
================
c4tnt: now fractures can be broken at start
idBrittleFracture::StartBroken
================
*/
void idBrittleFracture::StartBroken( const float part, float disperse) {
	int i, counter;
	shard_t *shard;
	shard_t *shardorg;
	idVec3 point;

	if ( disperse > 0.9) disperse = 0.9f;

	if ( !IsBroken() ) {
		Break();
	}
	
	counter = shards.Num() * part;
	if ( counter > shards.Num()) counter = shards.Num();

	while (counter > 0) {
		for ( i = 0; i < shards.Num(); i++ ) {
			shardorg = shards[i];

			if ( shardorg->droppedTime != -1 ) {
				continue;
			}
			if (gameLocal.random.RandomFloat() > disperse) {
				counter--;
				point = shardorg->clipModel->GetOrigin();

				for ( i = 0; i < shards.Num(); i++ ) {
					shard = shards[i];

					if ( shard->droppedTime != -1 || shard == shardorg) {
						continue;
					}

					if ( ( shard->clipModel->GetOrigin() - point ).LengthSqr() > Square( maxShatterRadius ) ) {
						continue;
					}

					counter--;
					DropShard( shard );
				}
				DropShard( shardorg );
				DropFloatingIslands( &counter );
			}
		}
	}
}
/*
================
idBrittleFracture::DropFloatingIslands
================
*/
void idBrittleFracture::DropFloatingIslands( const idVec3 &point, const idVec3 &impulse, const int time ) {
	int i, j, numIslands;
	int queueStart, queueEnd;
	shard_t *curShard, *nextShard, **queue;
	bool touchesEdge;
	idVec3 dir;
	dir = impulse;
	dir.Normalize();
	numIslands = 0;
	queue = ( shard_t ** ) _alloca16( shards.Num() * sizeof( shard_t ** ) );
	for( i = 0; i < shards.Num(); i++ ) {
		shards[i]->islandNum = 0;
	}
	for( i = 0; i < shards.Num(); i++ ) {
		if( shards[i]->droppedTime != -1 ) {
			continue;
		}
		if( shards[i]->islandNum ) {
			continue;
		}
		queueStart = 0;
		queueEnd = 1;
		queue[0] = shards[i];
		shards[i]->islandNum = numIslands + 1;
		touchesEdge = false;
		if( shards[i]->atEdge ) {
			touchesEdge = true;
		}
		for( curShard = queue[queueStart]; queueStart < queueEnd; curShard = queue[++queueStart] ) {
			for( j = 0; j < curShard->neighbours.Num(); j++ ) {
				nextShard = curShard->neighbours[j];
				if( nextShard->droppedTime != -1 ) {
					continue;
				}
				if( nextShard->islandNum ) {
					continue;
				}
				queue[queueEnd++] = nextShard;
				nextShard->islandNum = numIslands + 1;
				if( nextShard->atEdge ) {
					touchesEdge = true;
				}
			}
		}
		numIslands++;
		// if the island is not connected to the world at any edges
		if( !touchesEdge ) {
			for( j = 0; j < queueEnd; j++ ) {
				DropShard( queue[j], point, dir, 0.0f, time );
			}
		}
	}
}
/*
================
idBrittleFracture::Shatter
================
*/
void idBrittleFracture::Shatter( const idVec3& point, const idVec3& impulse, const int time )
{
	int i;
	idVec3 dir;
	shard_t* shard;
	float m;
	
	if( common->IsServer() )
	{
		idBitMsg	msg;
		byte		msgBuf[MAX_EVENT_PARAM_SIZE];
		
		msg.InitWrite( msgBuf, sizeof( msgBuf ) );
		msg.BeginWriting();
		msg.WriteFloat( point[0] );
		msg.WriteFloat( point[1] );
		msg.WriteFloat( point[2] );
		msg.WriteFloat( impulse[0] );
		msg.WriteFloat( impulse[1] );
		msg.WriteFloat( impulse[2] );
		ServerSendEvent( EVENT_SHATTER, &msg, true );
	}
	
	// Store off the event so we can rebuilt the object if we reload a savegame
	fractureEvent_s fractureEvent;
	fractureEvent.eventType = EVENT_SHATTER;
	fractureEvent.point = point;
	fractureEvent.vector = impulse;
	storedEvents.Append( fractureEvent );
	
	if( time > ( gameLocal.time - SHARD_ALIVE_TIME ) )
	{
		StartSound( "snd_shatter", SND_CHANNEL_ANY, 0, false, NULL );
	}
	
	if( !IsBroken() )
	{
		Break();
	}
	
	if( fxFracture.Length() )
	{
		idEntityFx::StartFx( fxFracture, &point, &GetPhysics()->GetAxis(), this, true );
	}
	
	dir = impulse;
	m = dir.Normalize();
	
	for( i = 0; i < shards.Num(); i++ )
	{
		shard = shards[i];
		
		if( shard->droppedTime != -1 )
		{
			continue;
		}
		
		if( ( shard->clipModel->GetOrigin() - point ).LengthSqr() > Square( maxShatterRadius ) )
		{
			continue;
		}
		
		DropShard( shard, point, dir, m, time );
	}
	
	DropFloatingIslands( point, impulse, time );
}