Ejemplo n.º 1
0
/*
============
idPush::GetPushableEntitiesForRotation
============
*/
int idPush::GetPushableEntitiesForRotation( idEntity *pusher, idEntity *initialPusher, const int flags,
											const idRotation &rotation, idEntity *entityList[], int maxEntities ) {
	int i, n, l;
	idBounds bounds, pushBounds;
	idPhysics *physics;

	// get bounds for the whole movement
	physics = pusher->GetPhysics();
	bounds = physics->GetBounds();
	pushBounds.FromBoundsRotation( bounds, physics->GetOrigin(), physics->GetAxis(), rotation );
	pushBounds.ExpandSelf( 2.0f );

	// get all entities within the push bounds
	n = gameLocal.clip.EntitiesTouchingBounds( pushBounds, -1, entityList, MAX_GENTITIES );

	for ( l = i = 0; i < n; i++ ) {
		if ( entityList[i] == pusher || entityList[i] == initialPusher ) {
			continue;
		}
		if ( CanPushEntity( entityList[i], pusher, initialPusher, flags ) ) {
			entityList[l++] = entityList[i];
		}
	}

	return l;
}
Ejemplo n.º 2
0
/*
============
idPush::GetPushableEntitiesForTranslation
============
*/
int idPush::GetPushableEntitiesForTranslation( idEntity *pusher, idEntity *initialPusher, const int flags,
											const idVec3 &translation, idEntity *entityList[], int maxEntities ) {
	int i, n, l;
	idBounds bounds, pushBounds;
	idPhysics *physics;

	// get bounds for the whole movement
	physics = pusher->GetPhysics();
	bounds = physics->GetBounds();
	pushBounds.FromBoundsTranslation( bounds, physics->GetOrigin(), physics->GetAxis(), translation );
	pushBounds.ExpandSelf( 2.0f );

	// get all entities within the push bounds
// RAVEN BEGIN
// ddynerman: multiple clip worlds
	n = gameLocal.EntitiesTouchingBounds( this, pushBounds, -1, entityList, MAX_GENTITIES );
// RAVEN END

	for ( l = i = 0; i < n; i++ ) {
		if ( entityList[i] == pusher || entityList[i] == initialPusher ) {
			continue;
		}
		if ( CanPushEntity( entityList[i], pusher, initialPusher, flags ) ) {
			entityList[l++] = entityList[i];
		}
	}

	return l;
}
Ejemplo n.º 3
0
/*
============
idPush::ClipTranslationalPush

  Try to push other entities by translating the given entity.
============
*/
float idPush::ClipTranslationalPush( trace_t &results, idEntity *pusher, const int flags,
										const idVec3 &newOrigin, const idVec3 &translation ) {
	int i, j, numListedEntities;
	idEntity *curPusher, *ent, *entityList[ MAX_GENTITIES ];
	float fraction;
	bool groundContact, blocked = false;
	float totalMass;
	trace_t trace;
	idVec3 realTranslation, partialTranslation;

	totalMass = 0.0f;

	results.fraction = 1.0f;
	results.endpos = newOrigin;
	results.endAxis = pusher->GetPhysics()->GetAxis();
	memset( results.c, 0, sizeof( results.c ) );

	if ( translation == vec3_origin ) {
		return totalMass;
	}

	// clip against all non-pushable physics objects
	if ( flags & PUSHFL_CLIP ) {

		numListedEntities = GetPushableEntitiesForTranslation( pusher, pusher, flags, translation, entityList, MAX_GENTITIES );
		// disable pushable entities for collision detection
		for ( i = 0; i < numListedEntities; i++ ) {
			entityList[i]->GetPhysics()->DisableClip();
		}
		// clip translation
		pusher->GetPhysics()->ClipTranslation( results, translation, NULL );
		// enable pushable entities
		for ( i = 0; i < numListedEntities; i++ ) {
			entityList[i]->GetPhysics()->EnableClip();
		}
		if ( results.fraction == 0.0f ) {
			return totalMass;
		}
		realTranslation = results.fraction * translation;
	}
	else {
		realTranslation = translation;
	}

	// put the pusher in the group of pushed physics objects
	pushedGroup[0].ent = pusher;
	pushedGroup[0].fraction = 1.0f;
	pushedGroup[0].groundContact = true;
	pushedGroup[0].test = true;
	pushedGroupSize = 1;

	// get all physics objects that need to be pushed
	for ( i = 0; i < pushedGroupSize; ) {
		if ( !pushedGroup[i].test ) {
			i++;
			continue;
		}
		pushedGroup[i].test = false;
		curPusher = pushedGroup[i].ent;
		fraction = pushedGroup[i].fraction;
		groundContact = pushedGroup[i].groundContact;
		i = 0;

		numListedEntities = GetPushableEntitiesForTranslation( curPusher, pusher, flags, realTranslation, entityList, MAX_GENTITIES );

		for ( j = 0; j < numListedEntities; j++ ) {
			ent = entityList[ j ];

			if ( IsFullyPushed( ent ) ) {
				continue;
			}

			if ( !CanPushEntity( ent, curPusher, pusher, flags ) ) {
				continue;
			}

			if ( ent->GetPhysics()->IsGroundEntity( curPusher->entityNumber ) ) {
				AddEntityToPushedGroup( ent, 1.0f * fraction, false );
			}
			else if ( ClipTranslationAgainstPusher( trace, ent, curPusher, -fraction * realTranslation ) ) {
				AddEntityToPushedGroup( ent, ( 1.0f - trace.fraction ) * fraction, groundContact );
			}
		}
	}

	// save physics states and disable physics objects for collision detection
	for ( i = 0; i < pushedGroupSize; i++ ) {
		SaveEntityPosition( pushedGroup[i].ent );
		pushedGroup[i].ent->GetPhysics()->DisableClip();
	}

	// clip all pushed physics objects
	for ( i = 1; i < pushedGroupSize; i++ ) {
		partialTranslation = realTranslation * pushedGroup[i].fraction;

		pushedGroup[i].ent->GetPhysics()->ClipTranslation( trace, partialTranslation, NULL );

		if ( trace.fraction < 1.0f ) {
			blocked = true;
			break;
		}
	}

	// enable all physics objects for collision detection
	for ( i = 1; i < pushedGroupSize; i++ ) {
		pushedGroup[i].ent->GetPhysics()->EnableClip();
	}

	// push all or nothing
	if ( blocked ) {
		if ( flags & PUSHFL_CLIP ) {
			pusher->GetPhysics()->ClipTranslation( results, realTranslation, NULL );
		}
		else {
			results.fraction = 0.0f;
			results.endpos = pusher->GetPhysics()->GetOrigin();
			results.endAxis = pusher->GetPhysics()->GetAxis();
		}
	}
	else {
		// translate all pushed physics objects
		for ( i = 1; i < pushedGroupSize; i++ ) {
			partialTranslation = realTranslation * pushedGroup[i].fraction;
			pushedGroup[i].ent->GetPhysics()->Translate( partialTranslation );
			totalMass += pushedGroup[i].ent->GetPhysics()->GetMass();
		}
		// translate the clip models of the pusher
		for ( i = 0; i < pusher->GetPhysics()->GetNumClipModels(); i++ ) {
			pusher->GetPhysics()->GetClipModel(i)->Translate( results.fraction * realTranslation );
			pusher->GetPhysics()->GetClipModel(i)->Link( gameLocal.clip );
		}
	}

	return totalMass;
}