Esempio n. 1
0
/*
================
idMoveable::Spawn
================
*/
void idMoveable::Spawn( void ) {
	idTraceModel trm;
	float density, friction, bouncyness, mass;
	int clipShrink;
	idStr clipModelName;

	// check if a clip model is set
	spawnArgs.GetString( "clipmodel", "", clipModelName );
	if ( !clipModelName[0] ) {
		clipModelName = spawnArgs.GetString( "model" );		// use the visual model
	}

	if ( !collisionModelManager->TrmFromModel( clipModelName, trm ) ) {
		gameLocal.Error( "idMoveable '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
		return;
	}

	// if the model should be shrinked
	clipShrink = spawnArgs.GetInt( "clipshrink" );
	if ( clipShrink != 0 ) {
		trm.Shrink( clipShrink * CM_CLIP_EPSILON );
	}

	// get rigid body properties
	spawnArgs.GetFloat( "density", "0.5", density );
	density = idMath::ClampFloat( 0.001f, 1000.0f, density );
	spawnArgs.GetFloat( "friction", "0.05", friction );
	friction = idMath::ClampFloat( 0.0f, 1.0f, friction );
	spawnArgs.GetFloat( "bouncyness", "0.6", bouncyness );
	bouncyness = idMath::ClampFloat( 0.0f, 1.0f, bouncyness );
	explode = spawnArgs.GetBool( "explode" );
	unbindOnDeath = spawnArgs.GetBool( "unbindondeath" );

	fxCollide = spawnArgs.GetString( "fx_collide" );
	nextCollideFxTime = 0;

	fl.takedamage = true;
	damage = spawnArgs.GetString( "def_damage", "" );
	canDamage = spawnArgs.GetBool( "damageWhenActive" ) ? false : true;
	minDamageVelocity = spawnArgs.GetFloat( "minDamageVelocity", "100" );
	maxDamageVelocity = spawnArgs.GetFloat( "maxDamageVelocity", "200" );
	nextDamageTime = 0;
	nextSoundTime = 0;

	health = spawnArgs.GetInt( "health", "0" );
	spawnArgs.GetString( "broken", "", brokenModel );

	if ( health ) {
		if ( brokenModel != "" && !renderModelManager->CheckModel( brokenModel ) ) {
			gameLocal.Error( "idMoveable '%s' at (%s): cannot load broken model '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), brokenModel.c_str() );
		}
	}

	// setup the physics
	physicsObj.SetSelf( this );
	physicsObj.SetClipModel( new idClipModel( trm ), density );
	physicsObj.GetClipModel()->SetMaterial( GetRenderModelMaterial() );
	physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
	physicsObj.SetAxis( GetPhysics()->GetAxis() );
	physicsObj.SetBouncyness( bouncyness );
	physicsObj.SetFriction( 0.6f, 0.6f, friction );
	physicsObj.SetGravity( gameLocal.GetGravity() );
	physicsObj.SetContents( CONTENTS_SOLID );
	physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
	SetPhysics( &physicsObj );

	if ( spawnArgs.GetFloat( "mass", "10", mass ) ) {
		physicsObj.SetMass( mass );
	}

	if ( spawnArgs.GetBool( "nodrop" ) ) {
		physicsObj.PutToRest();
	} else {
		physicsObj.DropToFloor();
	}

	if ( spawnArgs.GetBool( "noimpact" ) || spawnArgs.GetBool( "notPushable" ) ) {
		physicsObj.DisableImpact();
	}

	if ( spawnArgs.GetBool( "nonsolid" ) ) {
		BecomeNonSolid();
	}

	allowStep = spawnArgs.GetBool( "allowStep", "1" );

	PostEventMS( &EV_SetOwnerFromSpawnArgs, 0 );
}
Esempio n. 2
0
/*
================
idMoveable::Event_BecomeNonSolid
================
*/
void idMoveable::Event_BecomeNonSolid( void ) {
	BecomeNonSolid();
}
/*
================
idMoveable::Spawn
================
*/
void idMoveable::Spawn( void ) {
	idTraceModel trm;
	float density, friction, bouncyness, mass, air_friction_linear, air_friction_angular;
	int clipShrink;
	idStr clipModelName;
	idVec3 maxForce, maxTorque;
	// check if a clip model is set
	spawnArgs.GetString( "clipmodel", "", clipModelName );
	if( !clipModelName[0] ) {
		clipModelName = spawnArgs.GetString( "model" );		// use the visual model
	}
	// tels: support "model" "" with "noclipmodel" "0" - do not attempt to load
	// the clipmodel from the non-existing model name in this case:
	if( clipModelName.Length() ) {
		if( !collisionModelManager->TrmFromModel( clipModelName, trm ) ) {
			gameLocal.Error( "idMoveable '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
			return;
		}
		// angua: check if the cm is valid
		if( idMath::Fabs( trm.bounds[0].x ) == idMath::INFINITY ) {
			gameLocal.Error( "idMoveable '%s': invalid collision model %s", name.c_str(), clipModelName.c_str() );
		}
		// if the model should be shrunk
		clipShrink = spawnArgs.GetInt( "clipshrink" );
		if( clipShrink != 0 ) {
			trm.Shrink( clipShrink * CM_CLIP_EPSILON );
		}
	}
	// get rigid body properties
	spawnArgs.GetFloat( "density", "0.5", density );
	density = idMath::ClampFloat( 0.001f, 1000.0f, density );
	spawnArgs.GetFloat( "bouncyness", "0.6", bouncyness );
	bouncyness = idMath::ClampFloat( 0.0f, 1.0f, bouncyness );
	explode = spawnArgs.GetBool( "explode" );
	unbindOnDeath = spawnArgs.GetBool( "unbindondeath" );
	spawnArgs.GetFloat( "friction", "0.05", friction );
	// reverse compatibility, new contact_friction key replaces friction only if present
	if( spawnArgs.FindKey( "contact_friction" ) ) {
		spawnArgs.GetFloat( "contact_friction", "0.05", friction );
	}
	spawnArgs.GetFloat( "linear_friction", "0.6", air_friction_linear );
	spawnArgs.GetFloat( "angular_friction", "0.6", air_friction_angular );
	fxCollide = spawnArgs.GetString( "fx_collide" );
	nextCollideFxTime = 0;
	// tels:
	m_scriptCollide = spawnArgs.GetString( "script_collide" );
	m_nextCollideScriptTime = 0;
	m_collideScriptCounter = spawnArgs.GetInt( "collide_script_counter", "1" );
	// override the default of 1 with 0 if no script is defined
	if( m_scriptCollide == "" ) {
		m_collideScriptCounter = 0;
	}
	m_minScriptVelocity = spawnArgs.GetFloat( "min_script_velocity", "5.0" );
	damage = spawnArgs.GetString( "def_damage", "" );
	canDamage = spawnArgs.GetBool( "damageWhenActive" ) ? false : true;
	minDamageVelocity = spawnArgs.GetFloat( "minDamageVelocity", "-1" );
	if( minDamageVelocity == -1 ) { // grayman #2816
		minDamageVelocity = MIN_DAMAGE_VELOCITY;
	}
	maxDamageVelocity = spawnArgs.GetFloat( "maxDamageVelocity", "-1" );
	if( maxDamageVelocity == -1 ) { // grayman #2816
		maxDamageVelocity = MAX_DAMAGE_VELOCITY;
	}
	nextDamageTime = 0;
	nextSoundTime = 0;
	health = spawnArgs.GetInt( "health", "0" );
	// tels: load a visual model, as well as an optional brokenModel
	LoadModels();
	// setup the physics
	physicsObj.SetSelf( this );
	physicsObj.SetClipModel( new idClipModel( trm ), density );
	physicsObj.GetClipModel()->SetMaterial( GetRenderModelMaterial() );
	physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
	physicsObj.SetAxis( GetPhysics()->GetAxis() );
	physicsObj.SetBouncyness( bouncyness );
	physicsObj.SetFriction( air_friction_linear, air_friction_angular, friction );
	physicsObj.SetGravity( gameLocal.GetGravity() );
	int contents = CONTENTS_SOLID | CONTENTS_OPAQUE;
	// ishtvan: overwrite with custom contents, if present
	if( m_CustomContents != -1 ) {
		contents = m_CustomContents;
	}
	// greebo: Set the frobable contents flag if the spawnarg says so
	if( spawnArgs.GetBool( "frobable", "0" ) ) {
		contents |= CONTENTS_FROBABLE;
	}
	physicsObj.SetContents( contents );
	physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP );
	SetPhysics( &physicsObj );
	if( spawnArgs.GetFloat( "mass", "10", mass ) ) {
		physicsObj.SetMass( mass );
	}
	// tels
	if( spawnArgs.GetVector( "max_force", "", maxForce ) ) {
		physicsObj.SetMaxForce( maxForce );
	}
	if( spawnArgs.GetVector( "max_torque", "", maxTorque ) ) {
		physicsObj.SetMaxTorque( maxTorque );
	}
	if( spawnArgs.GetBool( "nodrop" ) ) {
		physicsObj.PutToRest();
	} else {
		physicsObj.DropToFloor();
	}
	if( spawnArgs.GetBool( "noimpact" ) || spawnArgs.GetBool( "notpushable" ) ) {
		physicsObj.DisableImpact();
	}
	if( !spawnArgs.GetBool( "solid" ) ) {
		BecomeNonSolid();
	}
	// SR CONTENTS_RESPONSE FIX
	if( m_StimResponseColl->HasResponse() ) {
		physicsObj.SetContents( physicsObj.GetContents() | CONTENTS_RESPONSE );
	}
	m_preHideContents = physicsObj.GetContents();
	m_preHideClipMask = physicsObj.GetClipMask();
	allowStep = spawnArgs.GetBool( "allowStep", "1" );
	// parse LOD spawnargs
	if( ParseLODSpawnargs( &spawnArgs, gameLocal.random.RandomFloat() ) ) {
		// Have to start thinking if we're distance dependent
		BecomeActive( TH_THINK );
	}
	// grayman #2820 - don't queue EV_SetOwnerFromSpawnArgs if it's going to
	// end up doing nothing. Queuing this for every moveable causes a lot
	// of event posting during frame 0. If extra work is added to
	// EV_SetOwnerFromSpawnArgs, then that must be accounted for here, to
	// make sure it has a chance of getting done.
	idStr owner;
	if( spawnArgs.GetString( "owner", "", owner ) ) {
		PostEventMS( &EV_SetOwnerFromSpawnArgs, 0 );
	}
}
bool ResolveMovementBlockTask::PerformBlockingAI(idAI* owner)
{
	if (owner->AI_MOVE_DONE && !owner->movementSubsystem->IsWaiting()) // grayman #2345 - if already waiting, no need to do this section
	{
		idVec3 ownerRight, ownerForward;
		_initialAngles.ToVectors(&ownerForward, &ownerRight);
		owner->StopMove(MOVE_STATUS_WAITING);
		owner->TurnToward(owner->GetPhysics()->GetOrigin() - ownerRight);

		if (owner->FacingIdeal() && _preTaskContents == -1)
		{
			// grayman #2345 - don't become non-solid if your alert index is > ERelaxed. This is because
			// AI tend to bunch together when agitated, and it doesn't look good if one goes non-solid
			// and the others repeatedly walk through it.

			// If there's no room to get around you, become non-solid

			if ((owner->AI_AlertIndex == ERelaxed) && !Room2Pass(owner))
			{
				BecomeNonSolid(owner);
			}
			else
			{
				bool solid = true;
				owner->movementSubsystem->SetWaiting(solid);
			}
		}
	}

	if (owner->movementSubsystem->IsWaiting()) // grayman #2345
	{
		// We are waiting for the other AI to pass by
		idVec3 dist = _blockingEnt->GetPhysics()->GetOrigin() - owner->GetPhysics()->GetOrigin();

		if (dist.LengthSqr() > Square(60))
		{
			// other AI has passed by, end the task
			return true;
		}
		
		if (_blockingEnt->IsType(idAI::Type))
		{
			// grayman #2345 - check to see if the other AI is standing still.
			// If they are, end the task.

			idAI *_blockingEntAI = static_cast<idAI*>(_blockingEnt);
			if (_blockingEntAI && !_blockingEntAI->AI_FORWARD)
			{
				return true; // end the task
			}

			// If we're EWaitingSolid, change to EWaitingNonSolid if the other AI is barely moving.
			// grayman #2422 - but not if the other AI is searching

			if ( !_blockingEntAI->IsSearching() )
			{
				if (owner->movementSubsystem->IsWaitingSolid())
				{
					float traveledPrev = _blockingEntAI->movementSubsystem->GetPrevTraveled();
					if (traveledPrev < 0.1) // grayman #2345
					{
						BecomeNonSolid(owner);
					} 
				}
			}
		}

		if (ai_showObstacleAvoidance.GetBool())
		{
			// waiting AI is watching blocking AI
			gameRenderWorld->DebugLine(colorPink,owner->GetPhysics()->GetOrigin() + idVec3(0,0,72),_blockingEnt->GetPhysics()->GetOrigin() + idVec3(0,0,64),100);
		}
	}

	return false;
}
bool ResolveMovementBlockTask::PerformBlockingAI( idAI *owner ) {
	idVec3 right, forward;
	if( owner->AI_MOVE_DONE && !_turning && !owner->movementSubsystem->IsWaiting() ) { // grayman #2345 - if already waiting, no need to do this section
		// grayman #3725 - turn perpendicular to the direction
		// _blockingEnt is looking
		idAngles angles;
		if( _blockingEnt->IsType( idAI::Type ) ) {
			angles = static_cast<idAI *>( _blockingEnt )->viewAxis.ToAngles();
		} else {
			angles = _initialAngles;
		}
		angles.ToVectors( &forward, &right );
		owner->StopMove( MOVE_STATUS_WAITING );
		owner->TurnToward( owner->GetPhysics()->GetOrigin() + right );
		_turning = true; // grayman #3725
	}
	if( _turning ) { // grayman #3725
		if( !owner->FacingIdeal() ) {
			return false;
		}
		_turning = false;
		if( _preTaskContents == -1 ) {
			// grayman #2345 - don't become non-solid if your alert index is > ERelaxed. This is because
			// AI tend to bunch together when agitated, and it doesn't look good if one goes non-solid
			// and the others repeatedly walk through it.
			// If there's no room to get around you, become non-solid
			if( ( owner->AI_AlertIndex == ERelaxed ) && !Room2Pass( owner ) ) {
				BecomeNonSolid( owner );
			} else {
				bool solid = true;
				owner->movementSubsystem->SetWaiting( solid );
			}
		}
	}
	if( owner->movementSubsystem->IsWaiting() ) { // grayman #2345
		// We are waiting for the other AI to pass by
		idVec3 dist = _blockingEnt->GetPhysics()->GetOrigin() - owner->GetPhysics()->GetOrigin();
		if( dist.LengthSqr() > Square( 60 ) ) {
			// other AI has passed by, end the task
			// Be sure no one else is touching you when you want to return to being solid.
			// If there is, remain non-solid and let them pass by before you return to solid.
			// (This might not matter, but let's be safe.)
			idClipModel *clipModels[ MAX_GENTITIES ];
			idPhysics *phys = owner->GetPhysics();
			int num = gameLocal.clip.ClipModelsTouchingBounds( phys->GetAbsBounds(), phys->GetClipMask(), clipModels, MAX_GENTITIES );
			bool foundNeighbor = false;
			for( int i = 0 ; i < num ; i++ ) {
				idClipModel *cm = clipModels[ i ];
				// don't check render entities
				if( cm->IsRenderModel() ) {
					continue;
				}
				idEntity *hit = cm->GetEntity();
				if( hit == owner ) {
					continue;
				}
				if( !phys->ClipContents( cm ) ) {
					continue;
				}
				// touching
				if( hit->IsType( idActor::Type ) ) {
					_blockingEnt = hit;
					foundNeighbor = true;
					break;
				}
			}
			if( !foundNeighbor ) {
				// grayman #3725 - Return to your initial facing angle. This will
				// only matter if you were initially standing. If you were moving,
				// ending this task will return you to that, overriding this turn.
				_initialAngles.ToVectors( &forward, &right );
				owner->TurnToward( owner->GetPhysics()->GetOrigin() + forward );
				return true;
			}
		}
		if( _blockingEnt->IsType( idAI::Type ) ) {
			// grayman #2345 - check to see if the other AI is standing still.
			// If they are, end the task.
			idAI *_blockingEntAI = static_cast<idAI *>( _blockingEnt );
			if( _blockingEntAI && !_blockingEntAI->AI_FORWARD ) {
				// grayman #3725 - turn back to your initial facing angle
				_initialAngles.ToVectors( &forward, &right );
				owner->TurnToward( owner->GetPhysics()->GetOrigin() + forward );
				return true; // end the task
			}
			// If we're EWaitingSolid, change to EWaitingNonSolid if the other AI is barely moving.
			// grayman #2422 - but not if the other AI is searching
			if( !_blockingEntAI->IsSearching() ) {
				if( owner->movementSubsystem->IsWaitingSolid() ) {
					float traveledPrev = _blockingEntAI->movementSubsystem->GetPrevTraveled( false ).LengthFast(); // grayman #3647
					if( traveledPrev < 0.1 ) { // grayman #2345
						BecomeNonSolid( owner );
					}
				}
			}
		}
		if( ai_showObstacleAvoidance.GetBool() ) {
			// waiting AI is watching blocking AI
			gameRenderWorld->DebugLine( colorPink, owner->GetPhysics()->GetOrigin() + idVec3( 0, 0, 72 ), _blockingEnt->GetPhysics()->GetOrigin() + idVec3( 0, 0, 64 ), 100 );
		}
	}
	return false;
}
Esempio n. 6
0
/*
================
idMoveable::Spawn
================
*/
void idMoveable::Spawn( void ) {
	idTraceModel trm;
	float density, friction, bouncyness;
	int clipShrink;
	idStr clipModelName;
	bool setClipModel = false;
	idBounds bounds;
	
	// check if a clip model is set
	spawnArgs.GetString( "clipmodel", "", clipModelName );
	if ( !clipModelName[0] ) {
		idVec3 size;
		if ( spawnArgs.GetVector( "mins", NULL, bounds[0] ) &&
			spawnArgs.GetVector( "maxs", NULL, bounds[1] ) ) {
			setClipModel = true;
			if ( bounds[0][0] > bounds[1][0] || bounds[0][1] > bounds[1][1] || bounds[0][2] > bounds[1][2] ) {
				gameLocal.Error( "Invalid bounds '%s'-'%s' on moveable '%s'", bounds[0].ToString(), bounds[1].ToString(), name.c_str() );
			}
		} else if ( spawnArgs.GetVector( "size", NULL, size ) ) {
			if ( ( size.x < 0.0f ) || ( size.y < 0.0f ) || ( size.z < 0.0f ) ) {
				gameLocal.Error( "Invalid size '%s' on moveable '%s'", size.ToString(), name.c_str() );
			}
			bounds[0].Set( size.x * -0.5f, size.y * -0.5f, 0.0f );
			bounds[1].Set( size.x * 0.5f, size.y * 0.5f, size.z );
			setClipModel = true;
		}
	}

	if ( setClipModel ) {
		trm.SetupBox( bounds );
	} else {
		if ( !clipModelName[0] ) {
			clipModelName = spawnArgs.GetString ( "model" );		// use the visual model
		}
		clipModelName.BackSlashesToSlashes();

		if ( !collisionModelManager->TrmFromModel( gameLocal.GetMapName(), clipModelName, trm ) ) {
			gameLocal.Error( "idMoveable '%s': cannot load collision model %s", name.c_str(), clipModelName.c_str() );
			return;
		}
	}

	// if the model should be shrinked
	clipShrink = spawnArgs.GetInt( "clipshrink" );
	if ( clipShrink != 0 ) {
		trm.Shrink( clipShrink * CM_CLIP_EPSILON );
	}

	// get rigid body properties
	spawnArgs.GetFloat( "density", "0.5", density );
	density = idMath::ClampFloat( 0.001f, 1000.0f, density );
	spawnArgs.GetFloat( "friction", "0.05", friction );
	friction = idMath::ClampFloat( 0.0f, 1.0f, friction );
	spawnArgs.GetFloat( "bouncyness", "0.6", bouncyness );
	bouncyness = idMath::ClampFloat( 0.0f, 1.0f, bouncyness );
	unbindOnDeath = spawnArgs.GetBool( "unbindondeath" );

	nextCollideFxTime = 0;

	damage = spawnArgs.GetString( "def_damage", "" );
	canDamage = spawnArgs.GetBool( "damageWhenActive" ) ? false : true;
	health = spawnArgs.GetInt( "health", "0" );
	spawnArgs.GetString( "broken", "", brokenModel );

	if ( health ) {
		if ( brokenModel != "" && !renderModelManager->CheckModel( brokenModel ) ) {
			gameLocal.Error( "idMoveable '%s' at (%s): cannot load broken model '%s'", name.c_str(), GetPhysics()->GetOrigin().ToString(0), brokenModel.c_str() );
		}
	}

	fl.takedamage = (health > 0 );

	// setup the physics
	physicsObj.SetSelf( this );
// RAVEN BEGIN
// mwhitlock: Dynamic memory consolidation
	RV_PUSH_HEAP_MEM( this );
// RAVEN END
	physicsObj.SetClipModel( new idClipModel( trm, GetRenderModelMaterial() ), density );
// RAVEN BEGIN
// mwhitlock: Dynamic memory consolidation
	RV_POP_HEAP();
// RAVEN END
	physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
	physicsObj.SetAxis( GetPhysics()->GetAxis() );
	physicsObj.SetBouncyness( bouncyness );
	physicsObj.SetFriction( 0.6f, 0.6f, friction );
	physicsObj.SetGravity( gameLocal.GetGravity() );
	physicsObj.SetContents( CONTENTS_SOLID );
	physicsObj.SetClipMask( MASK_SOLID | CONTENTS_BODY | CONTENTS_CORPSE | CONTENTS_MOVEABLECLIP | CONTENTS_WATER );
	SetPhysics( &physicsObj );

	if ( spawnArgs.GetBool( "nodrop" ) ) {
		physicsObj.PutToRest();
	} else {
		physicsObj.DropToFloor();
	}

	if ( spawnArgs.GetBool( "noimpact" ) || spawnArgs.GetBool( "notPushable" ) ) {
		physicsObj.DisableImpact();
	}

	if ( spawnArgs.GetBool( "nonsolid" ) ) {
		BecomeNonSolid();
	}

	allowStep = spawnArgs.GetBool( "allowStep", "1" );

// RAVEN BEGIN
// cdr: Obstacle Avoidance
	fl.isAIObstacle = !physicsObj.IsPushable();
// RAVEN END

	PostEventMS( &EV_SetOwnerFromSpawnArgs, 0 );
}