void hhProjectileStickyCrawlerGrenade::BindToCollisionObject( const trace_t* collision ) {
	if( !collision || collision->fraction > 1.0f ) {
		return;
	}

	//HUMANHEAD PCF rww 05/18/06 - wait until we receive bind info from the server
	if (gameLocal.isClient) {
		return;
	}
	//HUMANHEAD END

	idEntity*	pEntity = gameLocal.entities[collision->c.entityNum];
	HH_ASSERT( pEntity );	

	// HUMANHEAD PCF pdm 05-20-06: Check for some degenerate cases to combat the server hangs happening
	if (pEntity == this || this->IsBound()) {
		assert(0);	// Report any of these
		return;
	}
	// HUMANHEAD END

	jointHandle_t jointHandle = CLIPMODEL_ID_TO_JOINT_HANDLE( collision->c.id );
	if ( jointHandle != INVALID_JOINT ) {
		SetOrigin( collision->endpos );
		SetAxis( DetermineCollisionAxis( (-collision->c.normal).ToMat3()) );
		BindToJoint( pEntity, jointHandle, true );
	} else {
		SetOrigin( collision->endpos );
		SetAxis( DetermineCollisionAxis( (-collision->c.normal).ToMat3()) );
		Bind( pEntity, true );
	}
}
Пример #2
0
/*
================
idThread::Event_GetTraceJoint
================
*/
void idThread::Event_GetTraceJoint( void ) {
	if ( trace.fraction < 1.0f && trace.c.id < 0 ) {
		idAFEntity_Base *af = static_cast<idAFEntity_Base *>( gameLocal.entities[ trace.c.entityNum ] );
		if ( af && af->IsType( idAFEntity_Base::Type ) && af->IsActiveAF() ) {
			ReturnString( af->GetAnimator()->GetJointName( CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id ) ) );
			return;
		}
	}
	ReturnString( "" );
}
Пример #3
0
/*
================
idAF::BodyForClipModelId
================
*/
int idAF::BodyForClipModelId( int id ) const {
	if ( id >= 0 ) {
		return id;
	} else {
		id = CLIPMODEL_ID_TO_JOINT_HANDLE( id );
		if ( id < jointBody.Num() ) {
			return jointBody[id];
		} else {
			return 0;
		}
	}
}
Пример #4
0
/*
============
idPush::ClipRotationalPush

  Try to push other entities by moving the given entity.
============
*/
float idPush::ClipRotationalPush( trace_t &results, idEntity *pusher, const int flags,
									const idMat3 &newAxis, const idRotation &rotation ) {
	int			i, listedEntities, res;
	idEntity	*check, *entityList[ MAX_GENTITIES ];
	idBounds	bounds, pushBounds;
	idRotation	clipRotation;
	idMat3		clipAxis, oldAxis;
	trace_t		pushResults;
	bool		wasEnabled;
	float		totalMass;
	idClipModel *clipModel;

	clipModel = pusher->GetPhysics()->GetClipModel();

	totalMass = 0.0f;

	results.fraction = 1.0f;
	results.endpos = clipModel->GetOrigin();
	results.endAxis = newAxis;
	memset( &results.c, 0, sizeof( results.c ) );

	if ( !rotation.GetAngle() ) {
		return totalMass;
	}

	// get bounds for the whole movement
	bounds = clipModel->GetBounds();
	if ( bounds[0].x >= bounds[1].x ) {
		return totalMass;
	}
	pushBounds.FromBoundsRotation( bounds, clipModel->GetOrigin(), clipModel->GetAxis(), rotation );

	wasEnabled = clipModel->IsEnabled();

	// make sure we don't get the pushing clip model in the list
	clipModel->Disable();

	listedEntities = gameLocal.clip.EntitiesTouchingBounds( pushBounds, -1, entityList, MAX_GENTITIES );

	// discard entities we cannot or should not push
	listedEntities = DiscardEntities( entityList, listedEntities, flags, pusher );

	if ( flags & PUSHFL_CLIP ) {

		// can only clip movement of a trace model
		assert( clipModel->IsTraceModel() );

		// disable to be pushed entities for collision detection
		for ( i = 0; i < listedEntities; i++ ) {
			entityList[i]->GetPhysics()->DisableClip();
		}

		gameLocal.clip.Rotation( results, clipModel->GetOrigin(), rotation, clipModel, clipModel->GetAxis(), pusher->GetPhysics()->GetClipMask(), NULL );

		// enable to be pushed entities for collision detection
		for ( i = 0; i < listedEntities; i++ ) {
			entityList[i]->GetPhysics()->EnableClip();
		}

		if ( results.fraction == 0.0f ) {
			if ( wasEnabled ) {
				clipModel->Enable();
			}
			return totalMass;
		}

		clipRotation = rotation * results.fraction;
		clipAxis = results.endAxis;
	}
	else {

		clipRotation = rotation;
		clipAxis = newAxis;
	}

	// we have to enable the clip model because we use it during pushing
	clipModel->Enable();

	// save pusher old position
	oldAxis = clipModel->GetAxis();

	// try to push all the entities
	for ( i = 0; i < listedEntities; i++ ) {

		check = entityList[ i ];

		idPhysics *physics = check->GetPhysics();

		// disable the entity for collision detection
		physics->DisableClip();

		res = TryRotatePushEntity( pushResults, check, clipModel, flags, clipAxis, clipRotation );

		// enable the entity for collision detection
		physics->EnableClip();

		// if the entity is pushed
		if ( res == PUSH_OK ) {
			// set the pusher in the rotated position
			clipModel->Link( gameLocal.clip, clipModel->GetEntity(), clipModel->GetId(), clipModel->GetOrigin(), newAxis );
			// the entity might be pushed off the ground
			physics->EvaluateContacts();
			// put pusher back in old position
			clipModel->Link( gameLocal.clip, clipModel->GetEntity(), clipModel->GetId(), clipModel->GetOrigin(), oldAxis );

			// wake up this object
			check->ApplyImpulse( clipModel->GetEntity(), clipModel->GetId(), clipModel->GetOrigin(), vec3_origin );

			// add mass of pushed entity
			totalMass += physics->GetMass();
		}

		// if the entity is not blocking
		if ( res != PUSH_BLOCKED ) {
			continue;
		}

		// if the blocking entity is a projectile
		if ( check->IsType( idProjectile::Type ) ) {
			check->ProcessEvent( &EV_Explode );
			continue;
		}

		// if blocking entities should be crushed
		if ( flags & PUSHFL_CRUSH ) {
			check->Damage( clipModel->GetEntity(), clipModel->GetEntity(), vec3_origin, "damage_crush", 1.0f, CLIPMODEL_ID_TO_JOINT_HANDLE( pushResults.c.id ) );
			continue;
		}

		// if the entity is an active articulated figure and gibs
		if ( check->IsType( idAFEntity_Base::Type ) && check->spawnArgs.GetBool( "gib" ) ) {
			if ( static_cast<idAFEntity_Base *>(check)->IsActiveAF() ) {
				check->ProcessEvent( &EV_Gib, "damage_Gib" );
			}
		}

		// blocked
		results = pushResults;
		results.fraction = 0.0f;
		results.endAxis = clipModel->GetAxis();
		results.endpos = clipModel->GetOrigin();
		results.c.entityNum = check->entityNumber;
		results.c.id = 0;

		if ( !wasEnabled ) {
			clipModel->Disable();
		}

		return totalMass;
	}

	if ( !wasEnabled ) {
		clipModel->Disable();
	}

	return totalMass;
}
Пример #5
0
/*
============
idPush::ClipTranslationalPush

  Try to push other entities by moving the given entity.
============
*/
float idPush::ClipTranslationalPush( trace_t &results, idEntity *pusher, const int flags,
										const idVec3 &newOrigin, const idVec3 &translation ) {
	int			i, listedEntities, res;
	idEntity	*check, *entityList[ MAX_GENTITIES ];
	idBounds	bounds, pushBounds;
	idVec3		clipMove, clipOrigin, oldOrigin, dir, impulse;
	trace_t		pushResults;
	bool		wasEnabled;
	float		totalMass;
	idClipModel *clipModel;

	clipModel = pusher->GetPhysics()->GetClipModel();

	totalMass = 0.0f;

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

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

	dir = translation;
	dir.Normalize();
	dir.z += 1.0f;
	dir *= 10.0f;

	// get bounds for the whole movement
	bounds = clipModel->GetBounds();
	if ( bounds[0].x >= bounds[1].x ) {
		return totalMass;
	}
	pushBounds.FromBoundsTranslation( bounds, clipModel->GetOrigin(), clipModel->GetAxis(), translation );

	wasEnabled = clipModel->IsEnabled();

	// make sure we don't get the pushing clip model in the list
	clipModel->Disable();

// RAVEN BEGIN
// ddynerman: multiple clip worlds
	listedEntities = gameLocal.EntitiesTouchingBounds( pusher, pushBounds, -1, entityList, MAX_GENTITIES );
// RAVEN END

	// discard entities we cannot or should not push
	listedEntities = DiscardEntities( entityList, listedEntities, flags, pusher );

	if ( flags & PUSHFL_CLIP ) {

		// can only clip movement of a trace model
		assert( clipModel->IsTraceModel() );

		// disable to be pushed entities for collision detection
		for ( i = 0; i < listedEntities; i++ ) {
			entityList[i]->GetPhysics()->DisableClip();
		}
// RAVEN BEGIN
// ddynerman: multiple clip worlds
		gameLocal.Translation( pusher, results, clipModel->GetOrigin(), clipModel->GetOrigin() + translation, clipModel, clipModel->GetAxis(), pusher->GetPhysics()->GetClipMask(), NULL );
// RAVEN END
		// enable to be pushed entities for collision detection
		for ( i = 0; i < listedEntities; i++ ) {
			entityList[i]->GetPhysics()->EnableClip();
		}

		if ( results.fraction == 0.0f ) {
			if ( wasEnabled ) {
				clipModel->Enable();
			}
			return totalMass;
		}

		clipMove = results.endpos - clipModel->GetOrigin();
		clipOrigin = results.endpos;

	}
	else {

		clipMove = translation;
		clipOrigin = newOrigin;
	}

	// we have to enable the clip model because we use it during pushing
	clipModel->Enable();

	// save pusher old position
	oldOrigin = clipModel->GetOrigin();

	// try to push the entities
	for ( i = 0; i < listedEntities; i++ ) {

		check = entityList[ i ];

		idPhysics *physics = check->GetPhysics();

		// disable the entity for collision detection
		physics->DisableClip();

		res = TryTranslatePushEntity( pushResults, check, clipModel, flags, clipOrigin, clipMove );

		// enable the entity for collision detection
		physics->EnableClip();

		// if the entity is pushed
		if ( res == PUSH_OK ) {
			// set the pusher in the translated position
// RAVEN BEGIN
// ddynerman: multiple clip worlds
			clipModel->Link( clipModel->GetEntity(), clipModel->GetId(), newOrigin, clipModel->GetAxis() );
// RAVEN END
			// the entity might be pushed off the ground
			physics->EvaluateContacts();
			// put pusher back in old position
// RAVEN BEGIN
// ddynerman: multiple clip worlds
			clipModel->Link( clipModel->GetEntity(), clipModel->GetId(), oldOrigin, clipModel->GetAxis() );
// RAVEN END

			// wake up this object
			if ( flags & PUSHFL_APPLYIMPULSE ) {
				impulse = physics->GetMass() * dir;
			} else {
				impulse.Zero();
			}
			check->ApplyImpulse( clipModel->GetEntity(), clipModel->GetId(), clipModel->GetOrigin(), impulse );

			// add mass of pushed entity
			totalMass += physics->GetMass();
		}

		// if the entity is not blocking
		if ( res != PUSH_BLOCKED ) {
			continue;
		}

		// if the blocking entity is a projectile
// RAVEN BEGIN
// jnewquist: Use accessor for static class type 
		if ( check->IsType( idProjectile::GetClassType() ) ) {
// RAVEN END
			check->ProcessEvent( &EV_Explode );
			continue;
		}

		// if blocking entities should be crushed
		if ( flags & PUSHFL_CRUSH ) {
			check->Damage( clipModel->GetEntity(), clipModel->GetEntity(), vec3_origin, "damage_crush", 1.0f, CLIPMODEL_ID_TO_JOINT_HANDLE( pushResults.c.id ) );
			continue;
		}

		// if the entity is an active articulated figure and gibs
// RAVEN BEGIN
// jnewquist: Use accessor for static class type 
		if ( check->IsType( idAFEntity_Base::GetClassType() ) && check->spawnArgs.GetBool( "gib" ) ) {
// RAVEN END
			if ( static_cast<idAFEntity_Base *>(check)->IsActiveAF() ) {
				check->ProcessEvent( &EV_Gib, "damage_Gib" );
			}
		}

		// if the entity is a moveable item and gibs
// RAVEN BEGIN
// jnewquist: Use accessor for static class type 
		if ( check->IsType( idMoveableItem::GetClassType() ) && check->spawnArgs.GetBool( "gib" ) ) {
// RAVEN END
			check->ProcessEvent( &EV_Gib, "damage_Gib" );
		}

		// blocked
		results = pushResults;
		results.fraction = 0.0f;
		results.endAxis = clipModel->GetAxis();
		results.endpos = clipModel->GetOrigin();
		results.c.entityNum = check->entityNumber;
		results.c.id = 0;

		if ( !wasEnabled ) {
			clipModel->Disable();
		}

		return totalMass;
	}

	if ( !wasEnabled ) {
		clipModel->Disable();
	}

	return totalMass;
}
Пример #6
0
/*
==============
idDragEntity::Update
==============
*/
void idDragEntity::Update( idPlayer *player ) {
	idVec3 viewPoint, origin;
	idMat3 viewAxis, axis;
	trace_t trace;
	idEntity *newEnt;
	idAngles angles;
	jointHandle_t newJoint;
	idStr newBodyName;

	player->GetViewPos( viewPoint, viewAxis );

	// if no entity selected for dragging
	if ( !dragEnt.GetEntity() ) {

		if ( player->usercmd.buttons & BUTTON_ATTACK ) {

			gameLocal.clip.TracePoint( trace, viewPoint, viewPoint + viewAxis[0] * MAX_DRAG_TRACE_DISTANCE, (CONTENTS_SOLID|CONTENTS_RENDERMODEL|CONTENTS_BODY), player );
			if ( trace.fraction < 1.0f ) {

				newEnt = gameLocal.entities[ trace.c.entityNum ];
				if ( newEnt ) {

					if ( newEnt->GetBindMaster() ) {
						if ( newEnt->GetBindJoint() ) {
							trace.c.id = JOINT_HANDLE_TO_CLIPMODEL_ID( newEnt->GetBindJoint() );
						} else {
							trace.c.id = newEnt->GetBindBody();
						}
						newEnt = newEnt->GetBindMaster();
					}

					if ( newEnt->IsType( idAFEntity_Base::Type ) && static_cast<idAFEntity_Base *>(newEnt)->IsActiveAF() ) {
						idAFEntity_Base *af = static_cast<idAFEntity_Base *>(newEnt);

						// joint being dragged
						newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id );
						// get the body id from the trace model id which might be a joint handle
						trace.c.id = af->BodyForClipModelId( trace.c.id );
						// get the name of the body being dragged
						newBodyName = af->GetAFPhysics()->GetBody( trace.c.id )->GetName();

					} else if ( !newEnt->IsType( idWorldspawn::Type ) ) {

						if ( trace.c.id < 0 ) {
							newJoint = CLIPMODEL_ID_TO_JOINT_HANDLE( trace.c.id );
						} else {
							newJoint = INVALID_JOINT;
						}
						newBodyName = "";

					} else {

						newJoint = INVALID_JOINT;
						newEnt = NULL;
					}
				}
				if ( newEnt ) {
					dragEnt = newEnt;
					selected = newEnt;
					joint = newJoint;
					id = trace.c.id;
					bodyName = newBodyName;

					if ( !cursor ) {
						cursor = ( idCursor3D * )gameLocal.SpawnEntityType( idCursor3D::Type );
					}

					idPhysics *phys = dragEnt.GetEntity()->GetPhysics();
					localPlayerPoint = ( trace.c.point - viewPoint ) * viewAxis.Transpose();
					origin = phys->GetOrigin( id );
					axis = phys->GetAxis( id );
					localEntityPoint = ( trace.c.point - origin ) * axis.Transpose();

					cursor->drag.Init( g_dragDamping.GetFloat() );
					cursor->drag.SetPhysics( phys, id, localEntityPoint );
					cursor->Show();

					if ( phys->IsType( idPhysics_AF::Type ) ||
							phys->IsType( idPhysics_RigidBody::Type ) ||
								phys->IsType( idPhysics_Monster::Type ) ) {
						cursor->BecomeActive( TH_THINK );
					}
				}
			}
		}
	}

	// if there is an entity selected for dragging
	idEntity *drag = dragEnt.GetEntity();
	if ( drag ) {

		if ( !( player->usercmd.buttons & BUTTON_ATTACK ) ) {
			StopDrag();
			return;
		}

		cursor->SetOrigin( viewPoint + localPlayerPoint * viewAxis );
		cursor->SetAxis( viewAxis );

		cursor->drag.SetDragPosition( cursor->GetPhysics()->GetOrigin() );

		renderEntity_t *renderEntity = drag->GetRenderEntity();
		idAnimator *dragAnimator = drag->GetAnimator();

		if ( joint != INVALID_JOINT && renderEntity && dragAnimator ) {
			dragAnimator->GetJointTransform( joint, gameLocal.time, cursor->draggedPosition, axis );
			cursor->draggedPosition = renderEntity->origin + cursor->draggedPosition * renderEntity->axis;
			gameRenderWorld->DrawText( va( "%s\n%s\n%s, %s", drag->GetName(), drag->GetType()->classname, dragAnimator->GetJointName( joint ), bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 );
		} else {
			cursor->draggedPosition = cursor->GetPhysics()->GetOrigin();
			gameRenderWorld->DrawText( va( "%s\n%s\n%s", drag->GetName(), drag->GetType()->classname, bodyName.c_str() ), cursor->GetPhysics()->GetOrigin(), 0.1f, colorWhite, viewAxis, 1 );
		}
	}

	// if there is a selected entity
	if ( selected.GetEntity() && g_dragShowSelection.GetBool() ) {
		// draw the bbox of the selected entity
		renderEntity_t *renderEntity = selected.GetEntity()->GetRenderEntity();
		if ( renderEntity ) {
			gameRenderWorld->DebugBox( colorYellow, idBox( renderEntity->bounds, renderEntity->origin, renderEntity->axis ) );
		}
	}
}