Ejemplo n.º 1
0
void CBaseGrabHandler::IgnoreCollision(EntityId eID,unsigned int flags,bool ignore)
{
	IEntity *pGrab = gEnv->pEntitySystem->GetEntity(eID);
	IPhysicalEntity *ppGrab = pGrab ? pGrab->GetPhysics() : NULL;

	if(!ppGrab) return;

	if(ignore)
	{
		// NOTE Dez 14, 2006: <pvl> this whole block just fills in
		// a request structure and passes it to physics
		IEntity *pEnt = m_pActor->GetEntity();

		pe_action_add_constraint ac;
		ac.flags = constraint_inactive|constraint_ignore_buddy;
		ac.pBuddy = pEnt->GetPhysics();
		ac.pt[0].Set(0,0,0);

		ICharacterInstance *pCharacter = pEnt->GetCharacter(0);
		IPhysicalEntity *pPhysEnt = pCharacter?pCharacter->GetISkeletonPose()->GetCharacterPhysics(-1):NULL;

		if(pPhysEnt)
		{
			pe_simulation_params sp;
			pPhysEnt->GetParams(&sp);

			if(sp.iSimClass <= 2)
				ac.pBuddy = pPhysEnt;
		}

		ppGrab->Action(&ac);
	}
	else
	{
		// NOTE Dez 14, 2006: <pvl> the same as the other branch - just
		// fill in a request and pass it to the physics engine
		pe_action_update_constraint uc;
		uc.bRemove = 1;

		ppGrab->Action(&uc);
	}

	// NOTE Dez 14, 2006: <pvl> flag manipulation is basically a legacy
	// code - probably not used anymore, scheduled for removal.
	if(flags)
	{
		pe_params_part pp;
		pp.flagsAND = pp.flagsColliderAND = ~flags;
		pp.flagsOR = pp.flagsColliderOR = flags * (ignore?0:1);

		pe_status_nparts status_nparts;

		for(pp.ipart = ppGrab->GetStatus(&status_nparts)-1; pp.ipart>=0; pp.ipart--)
			ppGrab->SetParams(&pp);
	}
}
void CIntersectionAssistanceUnit::OnDetectObjectEmbedded()
{
    m_embedState = eES_Embedded;

    // How do we react to the bad news?
    if(m_resolutionPolicy == eRP_DeleteObject)
        {
            CGameRules *pGameRules=g_pGame->GetGameRules();
            assert(pGameRules);
            if (pGameRules)
                {
                    pGameRules->ScheduleEntityRemoval(m_subjectEntityId, 0.0f, true);
                }
        }
    else
        {
            IEntity* pEntity = gEnv->pEntitySystem->GetEntity(m_subjectEntityId);
            if(pEntity)
                {
                    IPhysicalEntity* pPhysical = pEntity->GetPhysics();
                    if(pPhysical)
                        {
                            // Force entity to sleep (for now)
                            pe_action_awake pa;
                            pa.bAwake = 0;
                            pPhysical->Action( &pa );
                        }
                }
        }
}
Ejemplo n.º 3
0
bool CBaseGrabHandler::StartDrop()
{
	IEntity *pGrab = gEnv->pEntitySystem->GetEntity(m_grabStats.grabId);
	IPhysicalEntity *pGrabPhys = pGrab ? pGrab->GetPhysics() : NULL;

	if (pGrabPhys && m_grabStats.throwVector.len2()>0.01f)
	{	
		pe_action_set_velocity asv;
		asv.v = m_grabStats.throwVector;

		asv.w.x = -1.0f + (cry_rand()/(float)RAND_MAX*(float)(2.0f));
		asv.w.y = -1.0f + (cry_rand()/(float)RAND_MAX*(float)(2.0f));
		asv.w.z = -1.0f + (cry_rand()/(float)RAND_MAX*(float)(2.0f));
		asv.w.NormalizeSafe();
		asv.w *= 2.0f;

		pGrabPhys->Action(&asv);
	}

	if (m_grabStats.grabId>0)
	{
		m_grabStats.dropId = m_grabStats.grabId;
		m_grabStats.resetFlagsDelay = 1.0f;

		m_pActor->CreateScriptEvent("droppedObject",(float)m_grabStats.grabId);

		if (pGrab) DisableGrabbedAnimatedCharacter (false);
	}

	m_grabStats.Reset();

	return true;
}
Ejemplo n.º 4
0
void CBaseGrabHandler::Update(float frameTime)
{

	//we have to restore the grabbed object collision flag at some point after the throw.
	if(m_grabStats.dropId>0)
	{
		m_grabStats.resetFlagsDelay -= frameTime;

		if(m_grabStats.resetFlagsDelay<0.001f)
		{
			IgnoreCollision(m_grabStats.dropId,m_grabStats.collisionFlags,false);
			m_grabStats.dropId = 0;
		}
	}

	if(m_grabStats.grabId<1)
		return;

	if(m_pActor->GetHealth()<=0)
	{
		StartDrop();
		return;
	}

	IEntity *pGrab = gEnv->pEntitySystem->GetEntity(m_grabStats.grabId);

	if(pGrab)
	{
		bool grabbing(m_grabStats.grabDelay>0.001f);

		if(!grabbing || m_grabStats.usingAnimation)
			UpdatePosVelRot(frameTime);
	}
	else
	{
		//in case the grabber lost the grabbed object, reset the ignore collision flags

		// FIXME Dez 14, 2006: <pvl> the following should be done by
		// calling IgnoreCollisions() but that function requires
		// id of the grabbed object => needs refactoring
		IPhysicalEntity *pActorPhys = m_pActor->GetEntity()->GetPhysics();

		if(pActorPhys)
		{
			pe_action_update_constraint uc;
			uc.bRemove = 1;

			pActorPhys->Action(&uc);
		}
	}

	// TODO Sep 13, 2007: <pvl> I strongly suspect releaseIKTime is redundant now.
	// NOTE Sep 13, 2007: <pvl> note that all timeouts are dodgy here since there's
	// no guarantee that the grabbing/throwing animation starts playing immediately
	// after the grabbing command is issued.
	if(m_grabStats.releaseIKTime>0.001f && m_grabStats.grabDelay < 0.001f)
		m_grabStats.releaseIKTime -= frameTime;
}
void CFlowConvoyNode::AwakeCoaches() //awake the physics
{
	pe_action_awake aa; 
	aa.bAwake=1;
	for (size_t i = 0; i < m_coaches.size(); ++i)
	{
		IPhysicalEntity* pPhysics = m_coaches[i].m_pEntity->GetPhysics();
		pPhysics->Action(&aa);
	}
}
void CReplayActor::OnRagdollized()
{
	if(!m_ragdollImpulse.impulse.IsZero())
	{
		IPhysicalEntity* pPhys = GetEntity()->GetPhysics();
		CRY_ASSERT(pPhys && pPhys->GetType()==PE_ARTICULATED);
		pPhys->Action(&m_ragdollImpulse);
	}
	m_ragdollImpulse.impulse.zero();
}
void CReplayActor::ApplyRagdollImpulse( pe_action_impulse& impulse )
{
	IPhysicalEntity* pPhys = GetEntity()->GetPhysics();
	if(!pPhys || pPhys->GetType()!=PE_ARTICULATED)
	{
		m_ragdollImpulse = impulse;
	}
	else
	{
		pPhys->Action(&impulse);
	}
}
//------------------------------------------------------------------------
void CVehicleDamageBehaviorImpulse::OnDamageEvent(EVehicleDamageBehaviorEvent event, const SVehicleDamageBehaviorEventParams& behaviorParams)
{
	if (event == eVDBE_Hit || event == eVDBE_VehicleDestroyed || event == eVDBE_ComponentDestroyed)  
	{
		IEntity* pEntity = m_pVehicle->GetEntity();
		CRY_ASSERT(pEntity);

		IPhysicalEntity* pPhysEntity = pEntity->GetPhysics();
		if (!pPhysEntity)
			return;

		pe_status_dynamics dyn;
		pPhysEntity->GetStatus(&dyn);
		float vehicleMass = dyn.mass;

		float r = cry_random(0.0f, 2.f);
		float impulseForce = cry_random(m_forceMin, m_forceMax) * vehicleMass;		

    Vec3 impulseDir(m_impulseDir);
    if (!m_worldSpace)
      impulseDir = m_pVehicle->GetEntity()->GetWorldTM().TransformVector(impulseDir);

		pe_action_impulse actionImpulse;
		Vec3& impulse = actionImpulse.impulse;
		Vec3& angImpulse = actionImpulse.angImpulse;

		impulse = impulseDir * impulseForce;
		angImpulse = m_pVehicle->GetEntity()->GetWorldTM().TransformVector(m_angImpulse);

		if (r <= 0.75f)
		{
			float r1 = cry_random(-0.35f, 0.35f);

			angImpulse += dyn.v * r1 * max(1.0f, dyn.w.GetLength());
			angImpulse *= vehicleMass;
		}
		else
		{
			float r1 = cry_random(-0.25f, 0.25f);
			float r2 = cry_random(-0.5f, 0.5f);

			impulse.z += abs(dyn.v.y) * r1 * vehicleMass;
			angImpulse.x += dyn.v.y * r2 * vehicleMass * max(1.0f, dyn.w.GetLength() * 1.5f);
		}

		if (m_pImpulseLocation)
			actionImpulse.point = m_pImpulseLocation->GetWorldSpaceTranslation();

		pPhysEntity->Action(&actionImpulse);
	}
}
Ejemplo n.º 9
0
void CNetPlayerInput::UpdateInterpolation()
{
	Vec3 desiredPosition = m_curInput.position;
	Vec3 desiredVelocity = m_curInput.deltaMovement * g_pGameCVars->pl_netSerialiseMaxSpeed;

	// Use the physics pos as the entity position is a frame behind at this point
	IPhysicalEntity * pent = m_pPlayer->GetEntity()->GetPhysics();
	pe_status_pos psp;
	pent->GetStatus(&psp);
	Vec3 entPos = psp.pos;

	pe_status_living psl;
	psl.velGround.zero();
	pent->GetStatus(&psl);
	
	float dt = gEnv->pTimer->GetFrameTime();

	// New data?
	if (m_newInterpolation)
		m_lerper.AddNewPoint(m_curInput.position, desiredVelocity, entPos, m_curInput.standingOn);

	bool bInAirOrJumping = m_pPlayer->GetActorStats()->inAir > 0.01f || m_pPlayer->GetActorStats()->onGround < 0.01f;

	// Predict
	CNetLerper::SPrediction prediction;
	m_lerper.Update(gEnv->pTimer->GetFrameTime(), entPos, prediction, psl.velGround, bInAirOrJumping);

	// Update lerp velocity
	m_lerpVel = prediction.lerpVel;

	// Should Snap
	if (prediction.shouldSnap)
	{
		m_pPlayer->GetEntity()->SetPos(prediction.predictedPos);

		pe_action_set_velocity actionVel;
		actionVel.v = prediction.lerpVel;
		pent->Action(&actionVel);
	}

#if !defined(_RELEASE)
	// Debug Draw
	if (g_pGameCVars->pl_debugInterpolation)
		m_lerper.DebugDraw(prediction, entPos, m_newInterpolation);
	else
		SAFE_DELETE(m_lerper.m_debug);
#endif

	m_newInterpolation = false;
}
Ejemplo n.º 10
0
//-----------------------------------------------------------------------
void CSpectacularKill::DeathBlow(CActor& targetActor)
{
	CRY_ASSERT_MESSAGE(m_isBusy, "spectacular kill should be in progress when triggering the death blow");
	if (!m_isBusy)
		return;

	if (targetActor.IsDead())
		return;

	Vec3 targetDir = targetActor.GetEntity()->GetForwardDir();

	{
		HitInfo hitInfo;
		hitInfo.shooterId = m_pOwner->GetEntityId();
		hitInfo.targetId = targetActor.GetEntityId();
		hitInfo.damage = 99999.0f; // CERTAIN_DEATH
		hitInfo.dir = targetDir;
		hitInfo.normal = -hitInfo.dir; // this has to be in an opposite direction from the hitInfo.dir or the hit is ignored as a 'backface' hit
		hitInfo.type = CGameRules::EHitType::StealthKill;

		g_pGame->GetGameRules()->ClientHit(hitInfo);
	}

	// WARNING: RagDollize resets the entity's rotation!
	//  [7/30/2010 davidr] FixMe: If the entity isn't dead here (because is immortal or any other reason) ragdollizing it will
	// leave it on an inconsistent state (usually only reproducible on debug scenarios)
	targetActor.GetGameObject()->SetAspectProfile(eEA_Physics, eAP_Ragdoll);

	// Give a small nudge in the hit direction to make the target fall over
	const SSpectacularKillParams* pSpectacularKillParams = GetParamsForClass(targetActor.GetEntity()->GetClass());
	CRY_ASSERT(pSpectacularKillParams);
	if (pSpectacularKillParams && (pSpectacularKillParams->impulseScale > 0.0f) && (pSpectacularKillParams->impulseBone != -1))
	{
		const float killDeathBlowVelocity = pSpectacularKillParams->impulseScale; // desired velocity after impulse in meters per second

		IPhysicalEntity* pTargetPhysics = targetActor.GetEntity()->GetPhysics();
		if (pTargetPhysics)
		{
			pe_simulation_params simulationParams;
			pTargetPhysics->GetParams(&simulationParams);

			pe_action_impulse impulse;
			impulse.partid = pSpectacularKillParams->impulseBone;
			impulse.impulse = targetDir*killDeathBlowVelocity*simulationParams.mass; // RagDollize reset the entity's rotation so I have to use the value I cached earlier
			pTargetPhysics->Action(&impulse);
		}
	}

	m_deathBlowState = eDBS_Done;
}
Ejemplo n.º 11
0
	void ResetVelocity(SActivationInfo* pActInfo)
	{
		IEntity* pGraphEntity = pActInfo->pEntity;
		if (pGraphEntity)
		{
			IPhysicalEntity* pPhysicalEntity = pGraphEntity->GetPhysics();
			if (pPhysicalEntity && pPhysicalEntity->GetType() != PE_STATIC)
			{
				pe_action_set_velocity setVel;
				setVel.v.zero();
				setVel.w.zero();
				pPhysicalEntity->Action(&setVel);
			}
		}
	}
Ejemplo n.º 12
0
void CFists::RaiseWeapon(bool raise, bool faster /*= false*/)
{
	//Only when colliding something while running
	if(raise && (GetCurrentAnimState()==eFAS_RUNNING || GetCurrentAnimState()==eFAS_JUMPING) && !IsWeaponRaised())
	{
		if((m_fm && m_fm->IsFiring())||(m_melee && m_melee->IsFiring()))
			return;

		PlayAction(g_pItemStrings->raise);

		SetDefaultIdleAnimation( eIGS_FirstPerson,g_pItemStrings->idle_relaxed);
		SetWeaponRaised(true);

		//Also give the player some impulse into the opposite direction
		CActor *pPlayer = GetOwnerActor();
		Vec3		pos;
		if(pPlayer)
		{
			IPhysicalEntity* playerPhysics = pPlayer->GetEntity()->GetPhysics();
			if(playerPhysics)
			{
				IMovementController *pMC = pPlayer->GetMovementController();
				if(pMC)
				{
					SMovementState state;
					pMC->GetMovementState(state);
					
					pe_action_impulse impulse;
					impulse.iApplyTime = 1;
					impulse.impulse = -state.eyeDirection*600.0f;
					playerPhysics->Action(&impulse);

					pos = state.eyePosition + state.eyeDirection*0.5f;
				}
				
			}
		}

		GetScheduler()->TimerAction(GetCurrentAnimationTime(eIGS_FirstPerson), CSchedulerAction<EndRaiseWeaponAction>::Create(EndRaiseWeaponAction(this)), true);

		//Sound and FX feedback
		CollisionFeeback(pos,m_currentAnimState);
	}
	else if(!raise)
		SetWeaponRaised(false);

}
void CRecoil::RecoilImpulse(const Vec3& firingPos, const Vec3& firingDir)
{
	if (m_recoilParams.impulse > 0.f)
	{
		EntityId id = (m_pWeapon->GetHostId()) ? m_pWeapon->GetHostId() : m_pWeapon->GetOwnerId();
		IEntity* pEntity = gEnv->pEntitySystem->GetEntity(id);
		IPhysicalEntity* pPhysicalEntity = pEntity ? pEntity->GetPhysics() : NULL;

		if (pPhysicalEntity)
		{        
			pe_action_impulse impulse;
			impulse.impulse = -firingDir * m_recoilParams.impulse; 
			impulse.point = firingPos;
			pPhysicalEntity->Action(&impulse);
		}
	}
}
void CLocalPlayerComponent::UpdateStumble( const float frameTime )
{
	IEntity * pEntity = m_rPlayer.GetEntity();

	IPhysicalEntity * pPhysEntity = pEntity->GetPhysics();

	if ( pPhysEntity )
	{
		pe_status_dynamics dynamics;
		pPhysEntity->GetStatus( &dynamics );
		if ( m_playerStumble.Update( frameTime, dynamics ) )
		{
			pe_action_impulse ai; 
			ai.impulse = m_playerStumble.GetCurrentActionImpulse();
			pPhysEntity->Action( &ai );
		}
	}
}
//------------------------------------------------------------------------
void CVehicleActionEntityAttachment::Update(const float deltaTime)
{
	if(m_isAttached)
		return;

	IEntitySystem *pEntitySystem = gEnv->pEntitySystem;
	assert(pEntitySystem);

	IEntity *pEntity = pEntitySystem->GetEntity(m_entityId);

	if(!pEntity)
		return;

	IPhysicalEntity *pPhysEntity = pEntity->GetPhysics();

	if(!pPhysEntity)
		return;

	pe_simulation_params paramsSim;
	float gravity;

	if(pPhysEntity->GetParams(&paramsSim))
		gravity = abs(paramsSim.gravity.z);
	else
		gravity = 9.82f;

	pe_status_dynamics dyn;

	if(pPhysEntity->GetStatus(&dyn))
	{
		pe_action_impulse impulse;
		impulse.impulse  = Matrix33(pEntity->GetWorldTM()) * Vec3(0.0f, 0.0f, 1.0f) * g_parachuteForce * gravity;
		impulse.impulse = impulse.impulse - dyn.v;
		impulse.impulse *= dyn.mass * deltaTime;
		impulse.iSource = 3;

		pPhysEntity->Action(&impulse);
	}

	m_timer -= deltaTime;

	if(m_timer <= 0.0f || dyn.v.z >= 0.0f)
		m_pVehicle->SetObjectUpdate(this, IVehicle::eVOU_NoUpdate);
}
Ejemplo n.º 16
0
void CLivingEntitySample::OnPrePhysicsUpdate()
{
	IEntity* pEntity = GetEntity();
	IPhysicalEntity* pPhysEntity = pEntity->GetPhysics();
	if ( pPhysEntity == NULL )
	{
		return;
	}

	// The desired speed is chosen with a value within the motion capabilities 
	// of the walk animation used for this sample.
	const float desiredSpeed = 1.5f;

	const Vec3 desiredLocalDirection = CalculateDesiredLocalDirection();
	const Vec3 desiredLocalVelocity = desiredLocalDirection * desiredSpeed;

	const Quat worldOrientation = pEntity->GetWorldRotation();
	const Vec3 desiredWorldVelocity = worldOrientation * desiredLocalVelocity;

	pe_action_move pam;
	pam.dir = desiredWorldVelocity;
	
	pPhysEntity->Action( &pam );
}
Ejemplo n.º 17
0
void CVehicleWeaponControlled::Update(SEntityUpdateContext& ctx, int update)
{
	IVehicle *pVehicle = m_vehicleId ? gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(m_vehicleId) : NULL; 
  if (!m_vehicleId && GetEntity()->GetParent())
  {
    IEntity *entity = GetEntity();
    
    if (entity)
    {
      IEntity *parent = entity->GetParent();
      if (parent)
      {
				m_vehicleId = parent->GetId();
        pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(parent->GetId());
      }
    }
  }



  if (pVehicle)
  {
		IVehiclePart *pPart = pVehicle->GetWeaponParentPart(GetEntityId());
		if(pPart)
		{
			if(IVehiclePart *pParentPart = pPart->GetParent())
			{
				CRY_ASSERT(pVehicle->GetEntity());

				if(ICharacterInstance *characterInst = pVehicle->GetEntity()->GetCharacter(pParentPart->GetSlot()))
				{
					if(ISkeletonPose* pose = characterInst->GetISkeletonPose())
					{
						IDefaultSkeleton& rIDefaultSkeleton = characterInst->GetIDefaultSkeleton();
						int16 joint = rIDefaultSkeleton.GetJointIDByName(pPart->GetName());
						const QuatT &jQuat = pose->GetAbsJointByID(joint);

						Matrix34 localT(jQuat);
						localT.SetTranslation(jQuat.t/* - Vec3(0.0f, 0.75f, 0.0f)*/);

						Matrix34 vehicleWorldTm = pVehicle->GetEntity()->GetWorldTM();
						Matrix34 mat = vehicleWorldTm * localT;
						Vec3 vehicleSide2 = pPart->GetParent()->GetLocalTM(true, true).GetTranslation();

						CPlayer *pl = this->GetOwnerPlayer();

						Matrix33 mat2;
						if (!m_destination.IsEquivalent(ZERO))
						{
							Vec3 diff = GetDestination() - mat.GetTranslation(); //pPart->GetWorldTM().GetTranslation();
							diff.Normalize();

							Matrix33 loc(mat);
							loc.Invert();

							Vec3 diffLocal = loc.TransformVector(diff);

							Matrix33 desMat;
							desMat.SetRotationVDir(diffLocal, 0.0f);

							Vec3 test = GetEntity()->GetLocalTM().GetColumn0();

							Ang3 testTM(desMat);

							float za = testTM.x - m_Angles.x;
							za = (za < 0.0f) ? -gf_PI : gf_PI;
							za *= 0.05f * ctx.fFrameTime;

							m_Angles.x += za;
							Limit(m_Angles.x, -gf_PI * 0.33f, gf_PI * 0.33f);

							if (testTM.z > m_Angles.z + 0.05f)
							{
								m_Angles.z += gf_PI * factor1 * ctx.fFrameTime;        
							}
							else if (testTM.z < m_Angles.z - 0.05f)
							{
								m_Angles.z -= gf_PI * factor1 * ctx.fFrameTime;        
							}
							else
							{
								m_Angles.z = testTM.z;
							}

							Limit(m_Angles.z, -gf_PI * 0.33f, gf_PI * 0.33f);
							mat2.SetRotationXYZ(m_Angles);
						}
						else
						{
							if (!m_FireBlocked)
							{
								m_Angles.x = m_Angles.x - ctx.fFrameTime * factor2 * m_Angles.x;
								m_Angles.z = m_Angles.z - ctx.fFrameTime * factor2 * m_Angles.z;
							}
							mat2.SetRotationXYZ(m_Angles);
						}

						mat = mat * mat2; 


						GetEntity()->SetWorldTM(mat);


						if (pl)
						{
							Matrix34 worldGunMat = vehicleWorldTm * localT;

							if (!pl->IsDead())
							{

								Vec3 trans = worldGunMat.GetTranslation() - worldGunMat.GetColumn2() * 0.7f;
								worldGunMat.SetTranslation(trans);

								pl->GetEntity()->SetWorldTM(worldGunMat);


								float dot = mat.GetColumn1().dot(worldGunMat.GetColumn0());
								Update3PAnim(pl, 0.5f - dot * 0.5f, ctx.fFrameTime, mat);
							}
							else
							{

								ICharacterInstance* pCharacter = pl->GetEntity()->GetCharacter(0);
								int boneId = pCharacter ? pCharacter->GetIDefaultSkeleton().GetJointIDByName("Spine03") : 7;

								pl->LinkToMountedWeapon(0);
								if (IVehicleSeat* seat = pVehicle->GetSeatForPassenger(pl->GetEntityId()))
								{
									seat->Exit(false, true);
								}

								Matrix33 rot(worldGunMat);
								Vec3 offset(0.0f, 0.0f, 0.70f);
								Vec3 transformedOff = rot.TransformVector(offset);
								Vec3 trans = worldGunMat.GetTranslation();
								trans -= transformedOff;
								worldGunMat.SetTranslation(trans);
								pl->GetEntity()->SetWorldTM(worldGunMat);
								pl->GetEntity()->SetPos(worldGunMat.GetTranslation()); //worldGunMat.GetTranslation());
								pl->RagDollize(true);

								if (boneId > -1)
								{
									IPhysicalEntity *physEnt = pl->GetEntity()->GetPhysics();
									if (physEnt)
									{
										pe_simulation_params simulationParams;
										physEnt->GetParams(&simulationParams);

										pe_params_pos pos;
										pos.pos = GetEntity()->GetPos();
										physEnt->SetParams(&pos);

										pe_action_impulse impulse;
										impulse.ipart = boneId;
										impulse.angImpulse = Vec3(0.0f, 0.0f, 1.0f);
										impulse.impulse = worldGunMat.GetColumn1() * -1.5f * simulationParams.mass;
										physEnt->Action(&impulse);
									}
								}

								StopUse(GetOwnerId());

								SetOwnerId(0);
								StopFire();

								m_FireBlocked = true;
							} // IsDead
						} // pl
					} // pose
				} // characterInst
			} // pParentPart
		} // pPart
	} // pVehicle

  Base::Update(ctx, update);
  RequireUpdate(eIUS_General);
}
Ejemplo n.º 18
0
void CParachute::ProcessMovement(const float deltatime)
{
#define MetersPerSecondToKilometersPerHour(fValue) (fValue*3.6f)
#define SquareFeetToSquareMeters(fValue) (fValue*0.0929f)

    IPhysicalEntity* pPhysics = GetEntity()->GetPhysics();
    if (!pPhysics)
        return;

    float fDeltaTime = min(deltatime,0.1f);

    pe_status_dynamics statusDynamics;
    if (!pPhysics->GetStatus(&statusDynamics))
        return;

    ResetTextPos();

    DumpVector("Velocity",			&statusDynamics.v);
    DumpVector("AVelocity",			&statusDynamics.w);
    DumpVector("Acceleration",	&statusDynamics.a);
    DumpVector("WAcceleration",	&statusDynamics.wa);

    DumpText("DeltaTime=%f",fDeltaTime);
    DumpText("Velocity=%f m/s",statusDynamics.v.len());
    DumpText("Velocity=%f km/h",MetersPerSecondToKilometersPerHour(statusDynamics.v.len()));
    DumpText("Yaw=%f",	m_movementAction.rotateYaw);
    DumpText("Pitch=%f",m_movementAction.rotatePitch);
    DumpText("Roll=%f",	m_movementAction.rotateRoll);

    /*	Vec3 p1 = GetEntity()->GetWorldTM().GetColumn(3);
    Vec3 p2 = p1 + statusDynamics.v * 10.0f;
    gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(p1,ColorF(1,1,0,1),p2,ColorF(1,1,0,1));
    gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(p1,0.6f,ColorF(0,0,1,1));*/

    if(m_movementAction.rotatePitch > 0.0f)
    {
        pe_action_impulse actionImpulse;
        actionImpulse.impulse = Vec3(0,0,5000*fDeltaTime);
        pPhysics->Action(&actionImpulse);
    }
    else if(statusDynamics.v.z < 0.0f)
    {
        for(int iCel=0; iCel<7; iCel++)
        {
            SWing *pCel = &m_aCels[iCel];

            pCel->fCl = 1.0f;
            pCel->fCd = 1.0f;

            float fPosY = 0.25f;

            m_aCels[0].vPos = Vec3(-3.7f,fPosY,5.2f);
            m_aCels[1].vPos = Vec3(-2.7f,fPosY,5.7f);
            m_aCels[2].vPos = Vec3(-1.6f,fPosY,6.0f);
            m_aCels[3].vPos = Vec3(+0.0f,fPosY,6.1f);
            m_aCels[4].vPos = Vec3(+1.6f,fPosY,6.0f);
            m_aCels[5].vPos = Vec3(+2.7f,fPosY,5.7f);
            m_aCels[6].vPos = Vec3(+3.7f,fPosY,5.2f);

            m_aCels[0].fAngleX = 7.0f;
            m_aCels[1].fAngleX = 7.0f;
            m_aCels[2].fAngleX = 7.0f;
            m_aCels[3].fAngleX = 7.0f;
            m_aCels[4].fAngleX = 7.0f;
            m_aCels[5].fAngleX = 7.0f;
            m_aCels[6].fAngleX = 7.0f;

            if(m_movementAction.rotateYaw < 0.0f)
            {
                m_aCels[0].fCl = 1.3f;
                //				m_aCels[1].fCl = 1.3f;
                //				m_aCels[2].fCl = 1.2f;

                m_aCels[0].fCd = 2.9f;
                //				m_aCels[1].fCd = 2.2f;
                //				m_aCels[2].fCd = 2.1f;
            }
            else if(m_movementAction.rotateYaw > 0.0f)
            {
                //				m_aCels[4].fCl = 1.2f;
                //				m_aCels[5].fCl = 1.3f;
                m_aCels[6].fCl = 1.3f;

                //				m_aCels[4].fCd = 2.1f;
                //				m_aCels[5].fCd = 2.2f;
                m_aCels[6].fCd = 2.9f;
            }
            else if(m_movementAction.rotatePitch < 0.0f)
            {
                /*				m_aCels[0].vPos = Vec3(-3.6f,fPosY,4.6f);
                m_aCels[1].vPos = Vec3(-2.6f,fPosY,5.3f);
                m_aCels[2].vPos = Vec3(-1.6f,fPosY,5.9f);

                m_aCels[0].fAngleX = -15.0f;
                m_aCels[1].fAngleX = -8.0f;
                m_aCels[2].fAngleX = 0.0f;

                m_aCels[4].vPos = Vec3(+1.6f,fPosY,5.9f);
                m_aCels[5].vPos = Vec3(+2.6f,fPosY,5.3f);
                m_aCels[6].vPos = Vec3(+3.6f,fPosY,4.6f);

                m_aCels[4].fAngleX = 0.0f;
                m_aCels[5].fAngleX = -8.0f;
                m_aCels[6].fAngleX = -15.0f;*/

                m_aCels[0].fCl = 1.1f;
                m_aCels[1].fCl = 1.2f;
                m_aCels[2].fCl = 1.3f;

                m_aCels[0].fCd = 2.1f;
                m_aCels[1].fCd = 2.2f;
                m_aCels[2].fCd = 2.3f;

                m_aCels[4].fCl = 1.3f;
                m_aCels[5].fCl = 1.2f;
                m_aCels[6].fCl = 1.1f;

                m_aCels[4].fCd = 2.3f;
                m_aCels[5].fCd = 2.2f;
                m_aCels[6].fCd = 2.1f;
            }

            UpdateWing(pCel,0,fDeltaTime);
        }
    }
}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementTank::ProcessMovement(const float deltaTime)
{ 
	FUNCTION_PROFILER( gEnv->pSystem, PROFILE_GAME );

	m_netActionSync.UpdateObject(this);

	CryAutoCriticalSection lk(m_lock);

	CVehicleMovementBase::ProcessMovement(deltaTime);

	if (!(m_actorId && m_isEnginePowered))
	{
		IPhysicalEntity* pPhysics = GetPhysics();

		if (m_latFriction != 1.3f)
			SetLatFriction(1.3f);

		if (m_axleFriction != m_axleFrictionMax)
			UpdateAxleFriction(0.f, false, deltaTime);

		m_action.bHandBrake = 1;
		m_action.pedal = 0;
		m_action.steer = 0;
		pPhysics->Action(&m_action, 1);
		return;
	}

	IPhysicalEntity* pPhysics = GetPhysics();
	MARK_UNUSED m_action.clutch;

	Matrix34 worldTM( m_PhysPos.q );
	worldTM.AddTranslation( m_PhysPos.pos );

	const Matrix34 invWTM = worldTM.GetInvertedFast();

	Vec3 localVel = invWTM.TransformVector(m_PhysDyn.v);
	Vec3 localW = invWTM.TransformVector(m_PhysDyn.w);
	float speed = m_PhysDyn.v.len();
	float speedRatio = min(1.f, speed/m_maxSpeed);

	float actionPedal = abs(m_movementAction.power) > 0.001f ? m_movementAction.power : 0.f;        

	// tank specific:
	// avoid steering input around 0.5 (ask Anton)
	float actionSteer = m_movementAction.rotateYaw;
	float absSteer = abs(actionSteer);
	float steerSpeed = (absSteer < 0.01f && abs(m_currSteer) > 0.01f) ? m_steerSpeedRelax : m_steerSpeed;

	if (steerSpeed == 0.f)
	{
		m_currSteer =	(float)sgn(actionSteer);
	}
	else
	{ 
		if (m_movementAction.isAI)
		{
			m_currSteer = actionSteer;
		}
		else
		{
			m_currSteer += min(abs(actionSteer-m_currSteer), deltaTime*steerSpeed) * sgn(actionSteer-m_currSteer);        
		}
	}
	Limit(m_currSteer, -m_steerLimit, m_steerLimit);  

	if (abs(m_currSteer) > 0.0001f) 
	{
		// if steering, apply full throttle to have enough turn power    
		actionPedal = (float)sgn(actionPedal);

		if (actionPedal == 0.f) 
		{
			// allow steering-on-teh-spot only above maxReverseSpeed (to avoid sudden reverse of controls)
			const float maxReverseSpeed = -1.5f;
			actionPedal = max(0.f, min(1.f, 1.f-(localVel.y/maxReverseSpeed)));

			// todo
			float steerLim = 0.8f;
			Limit(m_currSteer, -steerLim*m_steerLimit, steerLim*m_steerLimit);
		}
	}

	if (!pPhysics->GetStatus(&m_vehicleStatus))
		return;

	int currGear = m_vehicleStatus.iCurGear - 1; // indexing for convenience: -1,0,1,2,..

	UpdateAxleFriction(m_movementAction.power, true, deltaTime);
	UpdateSuspension(deltaTime);   	

	float absPedal = abs(actionPedal);  

	// pedal ramping   
	if (m_pedalSpeed == 0.f)
		m_currPedal = actionPedal;
	else
	{
		m_currPedal += deltaTime * m_pedalSpeed * sgn(actionPedal - m_currPedal);  
		m_currPedal = clamp_tpl(m_currPedal, -absPedal, absPedal);
	}

	// only apply pedal after threshold is exceeded
	if (currGear == 0 && fabs_tpl(m_currPedal) < m_pedalThreshold) 
		m_action.pedal = 0;
	else
		m_action.pedal = m_currPedal;

	// change pedal amount based on damages
	float damageMul = 0.0f;
	{
		if (m_movementAction.isAI)
		{
			damageMul = 1.0f - 0.30f * m_damage; 
			m_action.pedal *= damageMul;
		}
		else
		{
			// request from Sten: damage shouldn't affect reversing so much.
			float effectiveDamage = m_damage;
			if(m_action.pedal < -0.1f)
				effectiveDamage = 0.4f * m_damage;

			m_action.pedal *= GetWheelCondition();
			damageMul = 1.0f - 0.7f*effectiveDamage; 
			m_action.pedal *= damageMul;
		}
	}

	// reverse steering value for backward driving
	float effSteer = m_currSteer * sgn(actionPedal);   

	// update lateral friction  
	float latSlipMinGoal = 0.f;
	float latFricMinGoal = m_latFricMin;

	if (abs(effSteer) > 0.01f && !m_movementAction.brake)
	{
		latSlipMinGoal = m_latSlipMin;

		// use steering friction, but not when countersteering
		if (sgn(effSteer) != sgn(localW.z))
			latFricMinGoal = m_latFricMinSteer;
	}

	Interpolate(m_currentSlipMin, latSlipMinGoal, 3.f, deltaTime);   

	if (latFricMinGoal < m_currentFricMin)
		m_currentFricMin = latFricMinGoal;
	else
		Interpolate(m_currentFricMin, latFricMinGoal, 3.f, deltaTime);

	float fractionSpeed = min(1.f, max(0.f, m_avgLateralSlip-m_currentSlipMin) / (m_latSlipMax-m_currentSlipMin));
	float latFric = fractionSpeed * (m_latFricMax-m_currentFricMin) + m_currentFricMin;

	if ( m_movementAction.brake && m_movementAction.isAI )
	{
		// it is natural for ai, apply differnt friction value while handbreaking
		latFric = m_latFricMax;
	}

	if (latFric != m_latFriction)
	{ 
		SetLatFriction(latFric);    
	}      

	const static float maxSteer = gf_PI/4.f; // fix maxsteer, shouldn't change  
	m_action.steer = m_currSteer * maxSteer;  

	if (m_steeringImpulseMin > 0.f && m_wheelContactsLeft != 0 && m_wheelContactsRight != 0)
	{  
		const float maxW = 0.3f*gf_PI;
		float steer = abs(m_currSteer)>0.001f ? m_currSteer : 0.f;    
		float desired = steer * maxW; 
		float curr = -localW.z;
		float err = desired - curr; // err>0 means correction to right 
		Limit(err, -maxW, maxW);

		if (abs(err) > 0.01f)
		{ 
			float amount = m_steeringImpulseMin + speedRatio*(m_steeringImpulseMax-m_steeringImpulseMin);

			// bigger correction for relaxing
			if (desired == 0.f || (desired*curr>0 && abs(desired)<abs(curr))) 
				amount = m_steeringImpulseRelaxMin + speedRatio*(m_steeringImpulseRelaxMax-m_steeringImpulseRelaxMin);

			float corr = -err * amount * m_PhysDyn.mass * deltaTime;

			pe_action_impulse imp;
			imp.iApplyTime = 0;      
			imp.angImpulse = worldTM.GetColumn2() * corr;
			pPhysics->Action(&imp, THREAD_SAFE);
		}    
	}

	m_action.bHandBrake = (m_movementAction.brake) ? 1 : 0;	

	if (currGear > 0 && m_vehicleStatus.iCurGear < m_currentGear) 
	{
		// when shifted down, disengage clutch immediately to avoid power/speed dropdown
		m_action.clutch = 1.f;
	}

	pPhysics->Action(&m_action, 1);

	if (Boosting())  
		ApplyBoost(speed, 1.2f*m_maxSpeed*GetWheelCondition()*damageMul, m_boostStrength, deltaTime);  

	if (m_wheelContacts <= 1 && speed > 5.f)
	{
		ApplyAirDamp(DEG2RAD(20.f), DEG2RAD(10.f), deltaTime, THREAD_SAFE);
		UpdateGravity(-9.81f * 1.4f);
	}

	if (m_netActionSync.PublishActions( CNetworkMovementStdWheeled(this) ))
		CHANGED_NETWORK_STATE(m_pVehicle,  eEA_GameClientDynamic );
}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementHelicopter::ProcessMovement(const float deltaTime)
{
	FUNCTION_PROFILER(GetISystem(), PROFILE_GAME);

	IPhysicalEntity *pPhysics = GetPhysics();
	assert(pPhysics);

	m_netActionSync.UpdateObject(this);

	CryAutoCriticalSection lk(m_lock);

	Vec3 &impulse = m_control.impulse;
	Vec3 &angImpulse = m_control.angImpulse;

	impulse.zero();
	angImpulse.zero();

	m_actionPitch = m_actionRoll = m_actionYaw = m_hoveringPower = 0.0f;

	if(!m_isEnginePowered)
		return;

	// This results in either ProcessActions or ProcessAI getting called
	CVehicleMovementBase::ProcessMovement(deltaTime);

	const Matrix33 tm(m_PhysPos.q);
	Ang3 angles = Ang3::GetAnglesXYZ(tm);

	m_currentFwdDir		= tm * Vec3(0.0f, 1.0f , 0.0f);
	m_currentLeftDir	= tm * Vec3(-1.0f, 0.0f, 0.0f);
	m_currentUpDir		= tm * Vec3(0.0f, 0.0f , 1.0f);

	m_mass				= m_PhysDyn.mass;
	Vec3 &velocity		= m_PhysDyn.v;
	Vec3 &angVelocity	= m_PhysDyn.w;

	/*	float gravity;

	pe_simulation_params paramsSim;
	if (pPhysics->GetParams(&paramsSim))
	gravity = abs(paramsSim.gravity.z);
	else
	gravity = 9.8f;
	*/
	UpdateDamages(deltaTime);
	UpdateEngine(deltaTime);
	PreProcessMovement(deltaTime);

	m_control.iSource = 3;
	m_control.iApplyTime = 0;

	if(!m_controlDamages.impulse.IsZero() || !m_controlDamages.angImpulse.IsZero())
	{
		m_controlDamages.iSource = 3;
		m_controlDamages.iApplyTime = 0;

		pPhysics->Action(&m_controlDamages,1);
	}

	if(abs(angles.x) < 0.01f)
		angles.x = 0.0f;

	if(abs(angles.y) < 0.01f)
		angles.y = 0.0f;

	float turbulenceMult = 1.0f - min(m_turbulenceMultMax, m_turbulence);

	Vec3 engineImpulse;
	engineImpulse  = m_workingUpDir * m_engineForce * m_hoveringPower;

	impulse += (engineImpulse - (velocity * m_velDamp * turbulenceMult));
	impulse *= deltaTime * m_mass;

	angImpulse += -m_currentLeftDir * m_actionPitch * m_pitchResponsiveness;
	angImpulse += m_currentFwdDir * m_actionRoll * m_rollResponsiveness;
	angImpulse += m_currentUpDir * m_actionYaw * m_yawResponsiveness;
	angImpulse += m_currentUpDir * m_steeringDamage * m_yawResponsiveness * 0.5f;
	angImpulse *= m_mass * deltaTime;

	angImpulse -= (angVelocity - m_controlDamages.angImpulse) * m_mass * m_rotationDamping * deltaTime;

	float powerScale = GetEnginePower();
	impulse *= powerScale;
	angImpulse *= powerScale;

	// apply the action
	pPhysics->Action(&m_control, 1);

	m_turbulence -= m_turbulence * deltaTime;

	if(m_turbulence < 0.01)
		m_turbulence = 0.0f;
}
Ejemplo n.º 21
0
//--------------------------------------
void CThrow::DoDrop()
{
	m_pWeapon->HideItem(true);

	if (m_throwableId)
	{
		IEntity *pEntity = gEnv->pEntitySystem->GetEntity(m_throwableId);

		if (pEntity)
		{
			IPhysicalEntity *pPE = pEntity->GetPhysics();

			if (pPE && (pPE->GetType() == PE_RIGID || pPE->GetType() == PE_PARTICLE))
			{
				Vec3 hit = GetProbableHit(WEAPON_HIT_RANGE);
				Vec3 pos = GetFiringPos(hit);
				CActor *pActor = m_pWeapon->GetOwnerActor();
				IMovementController *pMC = pActor ? pActor->GetMovementController() : 0;

				if (pMC)
				{
					SMovementState info;
					pMC->GetMovementState(info);
					float speed = 2.5f;
					CPlayer *pPlayer = static_cast<CPlayer *>(m_pWeapon->GetOwnerActor());

					if(info.aimDirection.z < -0.1f)
					{
						if(pPlayer)
						{
							if(SPlayerStats *pStats = static_cast<SPlayerStats *>(pPlayer->GetActorStats()))
							{
								if(pStats->grabbedHeavyEntity)
								{
									speed = 4.0f;
								}
							}
						}
					}

					if(CheckForIntersections(pPE, info.eyeDirection))
					{
						Matrix34 newTM = pEntity->GetWorldTM();
						newTM.SetTranslation(newTM.GetTranslation() - (info.eyeDirection * 0.4f));
						pEntity->SetWorldTM(newTM, ENTITY_XFORM_POS);
						pe_action_set_velocity asv;
						asv.v = (-info.eyeDirection * speed);
						pPE->Action(&asv);
					}
					else
					{
						pe_action_set_velocity asv;
						asv.v = (info.eyeDirection * speed);
						pPE->Action(&asv);
					}

					SEntityEvent entityEvent;
					entityEvent.event = ENTITY_EVENT_PICKUP;
					entityEvent.nParam[0] = 0;

					if (pPlayer)
					{
						entityEvent.nParam[1] = pPlayer->GetEntityId();
					}

					entityEvent.fParam[0] = speed;
					pEntity->SendEvent( entityEvent );
				}
			}
		}

		if (m_throwableAction)
		{
			m_throwableAction->execute(m_pWeapon);
		}
	}
}
void CVehicleMovementHelicopter::ProcessAI(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	CryAutoCriticalSection lk(m_lock);
	SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread];
		
	if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code
	{
		//ResetActions();
		m_movementAction.Clear();
		m_movementAction.isAI = true;

		SVehiclePhysicsHelicopterProcessAIParams params;
		params.pPhysStatus = physStatus;
		params.pInputAction = &m_inputAction;
		params.pAiRequest = &m_aiRequest;
		params.dt = deltaTime;
		params.aiRequiredVel = m_CurrentVel;
		params.aiCurrentSpeed = m_CurrentSpeed;
		params.aiYawResponseScalar = m_yawResponseScalar;
		m_yawResponseScalar = 1.f;
	
		// Use helper class to process the AI input
		// It will return a requested velocity, and change the input
		m_arcade.ProcessAI(params);

		// Get the output velocity
		m_CurrentVel = params.aiRequiredVel;
		m_CurrentSpeed = params.aiCurrentSpeed;
		return;
	}
	////////////////////// OLD DEPRECATED CODE :( //////////////////////////////////

	m_movementAction.Clear();
	ResetActions();

	// Our current state
	const Vec3 worldPos =  physStatus->pos;
	const Matrix33 worldMat( physStatus->q);
	const Matrix33 localMat( physStatus->q.GetInverted());
	const Ang3 worldAngles = Ang3::GetAnglesXYZ(worldMat);
	const Ang3 localAngles = Ang3::GetAnglesXYZ(localMat);

	const Vec3 currentVel = physStatus->v;
	const Vec3 currentVel2D(currentVel.x, currentVel.y, 0.0f);
	m_CurrentSpeed = m_CurrentVel.len(); //currentVel.len();
  float currentSpeed2d = currentVel2D.len();

	// +ve direction mean rotation anti-clocwise about the z axis - 0 means along y
	float currentDir = worldAngles.z;

	// to avoid singularity
	const Vec3 vWorldDir = worldMat.GetRow(1);
	const Vec3 vSideWays = worldMat.GetRow(0);
	const Vec3 vWorldDir2D =  Vec3( vWorldDir.x,  vWorldDir.y, 0.0f ).GetNormalizedSafe();

	// Our inputs
	float desiredSpeed = m_aiRequest.HasDesiredSpeed() ? m_aiRequest.GetDesiredSpeed() : 0.0f;
	Limit(desiredSpeed, -m_maxSpeed, m_maxSpeed);

	const Vec3 desiredMoveDir = m_aiRequest.HasMoveTarget() ? (m_aiRequest.GetMoveTarget() - worldPos).GetNormalizedSafe() : vWorldDir;
	Vec3 desiredMoveDir2D = Vec3(desiredMoveDir.x, desiredMoveDir.y, 0.0f);
	desiredMoveDir2D = desiredMoveDir2D.GetNormalizedSafe(desiredMoveDir2D);

	const Vec3 desiredVel = desiredMoveDir * desiredSpeed; 
	const Vec3 desiredVel2D(desiredVel.x, desiredVel.y, 0.0f);

  Vec3 desiredLookDir(desiredMoveDir);

  if (m_aiRequest.HasDesiredBodyDirectionAtTarget())
  {
	    desiredLookDir = m_aiRequest.GetDesiredBodyDirectionAtTarget().GetNormalizedSafe(desiredMoveDir);
  }
  else if (m_aiRequest.HasLookTarget())
  {
    desiredLookDir = (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe(desiredMoveDir);  
  }


	//const Vec3 desiredLookDir = m_aiRequest.HasLookTarget() ? (m_aiRequest.GetLookTarget() - worldPos).GetNormalizedSafe() : desiredMoveDir;
	const Vec3 desiredLookDir2D = Vec3(desiredLookDir.x, desiredLookDir.y, 0.0f).GetNormalizedSafe(vWorldDir2D);

  Vec3 prediction = m_aiRequest.HasBodyTarget() ? m_aiRequest.GetBodyTarget() : ZERO;

  prediction = (prediction.IsEquivalent(ZERO)) ? desiredMoveDir2D : prediction - worldPos;
  prediction.z = 0.0f;

  float speedLimit = prediction.GetLength2D();

	if(speedLimit > 0.0f)
	{
		prediction *= 1.0f / speedLimit;
	}

  Vec3 tempDir = currentVel2D.IsEquivalent(ZERO) ? localMat.GetRow(1) : currentVel2D;
  tempDir.z = 0.0f;
  tempDir.NormalizeFast();

	float dotProd = tempDir.dot(prediction);
	Limit(dotProd, FLT_EPSILON, 1.0f);

	float accel = m_enginePowerMax * min(2.0f,  1.0f / dotProd); // * dotProd;

	if (!m_aiRequest.HasDesiredBodyDirectionAtTarget())
	{
		dotProd *= dotProd;
		dotProd *= dotProd;
		float tempf = min(max(speedLimit * speedLimit, 2.0f), m_maxSpeed * dotProd);
		Limit(desiredSpeed, -tempf, tempf);
	}
	else if (dotProd < 0.0125f)
	{
		Limit(desiredSpeed, -m_maxSpeed * 0.25f, m_maxSpeed * 0.25f);
	}
  
  float posNeg = (float)__fsel(desiredSpeed - m_CurrentSpeed, 1.0f, -5.0f);

  if (desiredVel2D.GetLengthSquared() > FLT_EPSILON)
  {
	  m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime;
  }
  else
  {
    m_CurrentSpeed = m_CurrentSpeed + posNeg * accel * deltaTime;
  }

	if (posNeg > 0.0f && m_CurrentSpeed > desiredSpeed)
	{
		m_CurrentSpeed = desiredSpeed;
	}
	else if (posNeg < 0.0f && m_CurrentSpeed < desiredSpeed)
	{
		m_CurrentSpeed = desiredSpeed;
	}

	
	// ---------------------------- Rotation ----------------------------
	
	float desiredDir = (desiredLookDir2D.GetLengthSquared() > 0.0f) ? atan2f(-desiredLookDir2D.x, desiredLookDir2D.y) : atan2f(-vWorldDir2D.x, vWorldDir2D.y);
	while (currentDir < desiredDir - gf_PI)
		currentDir += 2.0f * gf_PI;
	while (currentDir > desiredDir + gf_PI)
		currentDir -= 2.0f * gf_PI;

	// ---------------------------- Yaw ----------------------------

	Ang3 dirDiff(0.0f, 0.0f, desiredDir - currentDir);
	dirDiff.RangePI();
	float absDiff   = fabsf(dirDiff.z);

	float rotSpeed		= (float)__fsel(dirDiff.z, m_yawPerRoll, -m_yawPerRoll);
	m_actionYaw		= m_actionYaw + deltaTime * (rotSpeed - m_actionYaw);

	float temp = fabsf(m_actionYaw);

	float multiplier = ((absDiff / (temp + 0.001f)) + 1.0f) * 0.5f;
	
	m_actionYaw	*= (float)__fsel(absDiff - temp, 1.0f, multiplier);

	// ---------------------------- Yaw ------------------------------

	m_CurrentVel = desiredMoveDir * m_CurrentSpeed;

  // ---------------------------- Pitch ----------------------------

  if (m_CurrentVel.GetLengthSquared2D() > 0.1f)
  {
    CalculatePitch(worldAngles, desiredMoveDir, currentSpeed2d, desiredSpeed, deltaTime);
  }
  else
  {
    Quat rot;
    rot.SetRotationVDir(desiredLookDir, 0.0f);
    float desiredXRot = Ang3::GetAnglesXYZ(rot).x + m_steeringDamage.x;

    m_actionPitch = worldAngles.x + (desiredXRot - worldAngles.x) * deltaTime/* * 10.0f*/;
    Limit(m_actionPitch, -m_maxPitchAngle * 2.0f, m_maxPitchAngle * 2.0f);
  }


	// ---------------------------- Roll ----------------------------
	float rollSpeed = GetRollSpeed();

	rollSpeed *= deltaTime;
	rollSpeed		= (float)__fsel(absDiff - rollSpeed, rollSpeed, absDiff);
	float roll		=(float) __fsel(dirDiff.z, -rollSpeed, rollSpeed);

	float speedPerUnit	   = 1.5f;
	float desiredRollSpeed = absDiff * speedPerUnit * (float)__fsel(dirDiff.z, 1.0f, -1.0f);
  
	desiredRollSpeed = -m_actionYaw * 2.5f;
  desiredRollSpeed += m_steeringDamage.y;

	m_actionRoll = m_actionRoll + deltaTime * (desiredRollSpeed - m_actionRoll);
	Limit(m_actionRoll, -m_maxRollAngle + m_steeringDamage.y, m_maxRollAngle - m_steeringDamage.y);
	m_actionRoll *= m_rollDamping;
	// ---------------------------- Roll ----------------------------


	// ---------------------------- Convert and apply ----------------------------
	Ang3 angles(m_actionPitch, m_actionRoll, worldAngles.z + deltaTime * m_actionYaw);
	
	pe_params_pos paramPos;
	paramPos.q.SetRotationXYZ(angles);
	paramPos.q.Normalize();

	IPhysicalEntity * pPhysicalEntity = GetPhysics();
	pPhysicalEntity->SetParams(&paramPos, 1);

	pe_action_set_velocity vel;
	vel.v = m_CurrentVel + m_netPosAdjust;
	pPhysicalEntity->Action(&vel, 1);

	// ---------------------------- Convert and apply ----------------------------

  m_rpmScale = max(0.2f, cry_fabsf(m_CurrentSpeed / m_maxSpeed));
}
Ejemplo n.º 23
0
//------------------------------------------------------------------------
void CVehicleDamageBehaviorBlowTire::Activate(bool activate)
{
  if (activate == m_isActive)
    return;

  if (activate && m_pVehicle->IsDestroyed())
    return;

	if (activate)
	{
		// NOTE: stance and physics position when getting into vehicles is set wrong
		if (!gEnv->pSystem->IsSerializingFile())
			DamagePlayers();
	}

  IVehicleComponent* pComponent = m_pVehicle->GetComponent(m_component.c_str());
  if (!pComponent)
    return;

  IVehiclePart* pPart = pComponent->GetPart(0);
  if (!pPart)
    return;

  // if IVehicleWheel available, execute full damage behavior. if null, only apply effects
  IVehicleWheel* pWheel = pPart->GetIWheel();
  
  if (activate)
  {
    IEntity* pEntity = m_pVehicle->GetEntity();
    IPhysicalEntity* pPhysics = pEntity->GetPhysics();
    const Matrix34& wheelTM = pPart->GetLocalTM(false);
    const SVehicleStatus& status = m_pVehicle->GetStatus();

    if (pWheel)
    { 
      const pe_cargeomparams* pParams = pWheel->GetCarGeomParams();  
            
      // handle destroyed wheel
      pe_params_wheel wheelParams;
      wheelParams.iWheel = pWheel->GetWheelIndex();            
      wheelParams.minFriction = wheelParams.maxFriction = 0.5f * pParams->maxFriction;      
      pPhysics->SetParams(&wheelParams); 
      
      if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
      { 
        SVehicleMovementEventParams params;
        params.pComponent = pComponent;
        params.iValue = pWheel->GetWheelIndex();
        pMovement->OnEvent(IVehicleMovement::eVME_TireBlown, params);
      }

      if (status.speed > 0.1f)
      {
        // add angular impulse
        pe_action_impulse angImp;
        float amount = m_pVehicle->GetMass() * status.speed * Random(0.25f, 0.45f) * -sgn(wheelTM.GetTranslation().x);
        angImp.angImpulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount));    
        pPhysics->Action(&angImp);
      }
      
      m_aiImmobilizedTimer = m_pVehicle->SetTimer(-1, AI_IMMOBILIZED_TIME*1000, this);  
    }

    if (!gEnv->pSystem->IsSerializingFile())
    {
      // add linear impulse       
      pe_action_impulse imp;
      imp.point = pPart->GetWorldTM().GetTranslation();

      float amount = m_pVehicle->GetMass() * Random(0.1f, 0.15f);

      if (pWheel)
      {
        amount *= max(0.5f, min(10.f, status.speed));

        if (status.speed < 0.1f)
          amount = -0.5f*amount;
      }
      else    
        amount *= 0.5f;

      imp.impulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount));
      pPhysics->Action(&imp);     

      // effect
      IParticleEffect* pEffect = gEnv->pParticleManager->FindEffect(TIRE_BLOW_EFFECT);
      if (pEffect)
      {
        int slot = pEntity->LoadParticleEmitter(-1, pEffect);
        if (slot > -1)
        { 
          float rotation = pWheel ? 0.5f * gf_PI * -sgn(wheelTM.GetTranslation().x) : gf_PI;
          Matrix34 tm = Matrix34::CreateRotationZ(rotation);        
          tm.SetTranslation(wheelTM.GetTranslation());        
          pEntity->SetSlotLocalTM(slot, tm);
        }
      }

			// remove affected decals
			{
				Vec3 pos = pPart->GetWorldTM().GetTranslation();
				AABB aabb = pPart->GetLocalBounds();
				float radius = aabb.GetRadius();
				Vec3 vRadius(radius,radius,radius);
        AABB areaBox(pos-vRadius, pos+vRadius);
        
        IRenderNode * pRenderNode = NULL;				
        if (IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER))
					pRenderNode = pRenderProxy->GetRenderNode();

        gEnv->p3DEngine->DeleteDecalsInRange(&areaBox, pRenderNode);
			}
    }    
  }
  else
  { 
    if (pWheel)
    {
      // restore wheel properties        
      IPhysicalEntity* pPhysics = m_pVehicle->GetEntity()->GetPhysics();    
      pe_params_wheel wheelParams;

      for (int i=0; i<m_pVehicle->GetWheelCount(); ++i)
      { 
        const pe_cargeomparams* pParams = m_pVehicle->GetWheelPart(i)->GetIWheel()->GetCarGeomParams();

        wheelParams.iWheel = i;
        wheelParams.bBlocked = 0;
        wheelParams.suspLenMax = pParams->lenMax;
        wheelParams.bDriving = pParams->bDriving;      
        wheelParams.minFriction = pParams->minFriction;
        wheelParams.maxFriction = pParams->maxFriction;
        pPhysics->SetParams(&wheelParams);
      }

			if (IVehicleMovement* pMovement = m_pVehicle->GetMovement())
			{ 
				SVehicleMovementEventParams params;
				params.pComponent = pComponent;
				params.iValue = pWheel->GetWheelIndex();
				// reset the particle status
				pMovement->OnEvent(IVehicleMovement::eVME_TireRestored, params);
			}
    }  
    
    m_aiImmobilizedTimer = -1;
  }

  m_isActive = activate;      
}
Ejemplo n.º 24
0
bool CJaw::SetAspectProfile(EEntityAspects aspect, uint8 profile)
{
	if(aspect!=eEA_Physics)
		return BaseClass::SetAspectProfile(aspect, profile);

	bool ok = false;
	if(!gEnv->bMultiplayer && gEnv->pSystem->IsSerializingFile() && m_auxSlotUsedBQS)
		ok = true;

	int slot = (m_auxSlotUsed||ok)?eIGS_ThirdPersonAux:eIGS_ThirdPerson;

	if (aspect == eEA_Physics)
	{
		switch (profile)
		{
		case eIPhys_PhysicalizedStatic:
			{
				SEntityPhysicalizeParams params;
				params.type = PE_STATIC;
				params.nSlot = slot;

				GetEntity()->Physicalize(params);

				return true;
			}
			break;
		case eIPhys_PhysicalizedRigid:
			{
				SEntityPhysicalizeParams params;
				params.type = PE_RIGID;
				params.nSlot = slot;
				params.mass = m_sharedparams->params.mass;

				pe_params_buoyancy buoyancy;
				buoyancy.waterDamping = 1.5;
				buoyancy.waterResistance = 1000;
				buoyancy.waterDensity = 0;
				params.pBuoyancy = &buoyancy;

				GetEntity()->Physicalize(params);

				IPhysicalEntity *pPhysics = GetEntity()->GetPhysics();
				if (pPhysics)
				{
					pe_action_awake action;
					action.bAwake = m_owner.GetId()!=0;
					pPhysics->Action(&action);
				}
			}
			return true;
		case eIPhys_NotPhysicalized:
			{
				IEntityPhysicalProxy *pPhysicsProxy = GetPhysicalProxy();
				if (pPhysicsProxy)
				{
					SEntityPhysicalizeParams params;
					params.type = PE_NONE;
					params.nSlot = slot;
					pPhysicsProxy->Physicalize(params);
				}
			}
			return true;
		}
	}

	return false;
}
//------------------------------------------------------------------------
void CVehicleMovementHelicopter::OnEvent(EVehicleMovementEvent event, const SVehicleMovementEventParams& params)
{
	switch (event)
	{
	case eVME_Repair:
		{
			if(params.fValue < 0.25)
			{
				m_damageActual = 0.0f;
				m_damage = 0.0f;
			}
		}
		break;

  case eVME_Collision:
    {
      if (0)
      {
        m_isEnginePowered = false;

        pe_simulation_params simParams;
        simParams.dampingFreefall = 0.01f;
        simParams.gravity = Vec3(0.0f, 0.0f, -9.8f);
        GetPhysics()->SetParams(&simParams);
      }
    }
    break;

	case eVME_GroundCollision:
		{
			const float stopOver = 1.0f;
		}
		break;

	case eVME_Damage:
		{
      if (!m_pVehicle->IsIndestructable())
      {
			  const float stopOver = 1.0f;

			  m_damage = params.fValue;

        if (m_damage > 0.95f)
        {
          m_isEngineDisabled	= true;
          m_isEnginePowered	= false;

          StopExhaust();
          StopSounds();

					IPhysicalEntity * pPhysicalEntity = GetPhysics();

          pe_action_impulse impulse;
          impulse.angImpulse = Vec3(0.1f, 100.f, 0.0f);
          pPhysicalEntity->Action(&impulse);

          pe_simulation_params simParams;
          simParams.dampingFreefall = 0.01f;
          simParams.gravity = Vec3(0.0f, 0.0f, -9.8f);
          pPhysicalEntity->SetParams(&simParams);

          SVehicleEventParams eventParams;
          eventParams.entityId = 0;
          m_pVehicle->BroadcastVehicleEvent(eVE_Destroyed, eventParams);

          if (m_pVehicle)
          {
            if (IEntity *entity = m_pVehicle->GetEntity())
            {
              if (IAIObject *aiobject = entity->GetAI())
              {
                aiobject->Event(AIEVENT_DISABLE, NULL);
              }
            }
          }
        }
      }
		}
		break;

	case eVME_WarmUpEngine:
		m_enginePower = m_enginePowerMax;
		break;

	//case eVME_Turbulence:
	//	m_turbulence = max(m_turbulence, params.fValue);
	//	break;

	default:
		CVehicleMovementBase::OnEvent(event, params);
		break; 
	}
}
Ejemplo n.º 26
0
//------------------------------------------------------------------------
bool CNetworkedPhysicsEntity::SetAspectProfile( EEntityAspects aspect, uint8 profile )
{
	bool bRetVal = false;
	if (aspect == eEA_Physics)
	{
		switch (profile)
		{
			case ePhys_PhysicalizedRigid:
			{
				if (m_physicsType!=ePhys_PhysicalizedRigid)
				{
					m_physicsParams.type = PE_RIGID;
					GetEntity()->Physicalize(m_physicsParams);
					m_physicsType = ePhys_PhysicalizedRigid;
					GetEntity()->GetPhysics()->SetParams(m_physicsParams.pBuoyancy);
				}
				bRetVal = true;
				break;
			}
			case ePhys_PhysicalizedStatic:
			{
				if (m_physicsType != ePhys_PhysicalizedStatic)
				{
					m_physicsParams.type = PE_STATIC;
					GetEntity()->Physicalize(m_physicsParams);
					m_physicsType = ePhys_PhysicalizedStatic;
				}
				bRetVal = true;
				break;
			}
			case ePhys_NotPhysicalized:
			{
				if (m_physicsType!=ePhys_NotPhysicalized)
				{
					SEntityPhysicalizeParams params;
					params.type = PE_NONE;
					GetEntity()->Physicalize(params);
					m_physicsType = ePhys_NotPhysicalized;
				}
				bRetVal = true;
				break;
			}
			default:
				{
					CryLog("Unsupported physicalization type in CNetworkedPhysicsEntity!");
				}
		}
	}

	IPhysicalEntity * pPhysEnt = GetEntity()->GetPhysics();
	if(pPhysEnt)
	{
			// Turn off some collisions
			// NB: by leaving pe_params_part.ipart undefined, all the geom flags will changed
			pe_params_part pp;
			pp.flagsAND = ~(geom_colltype_ray|geom_colltype_player|geom_colltype_explosion|geom_colltype_debris|geom_colltype_foliage_proxy);
			pPhysEnt->SetParams(&pp);

			pe_simulation_params psp;
			psp.damping = 0.5f;
			pPhysEnt->SetParams(&psp);

			//Add a bit of angular velocity so it doesn't look bizzare.
			pe_action_set_velocity physicsAction;
			physicsAction.w.Set((rnd()-0.5f)*15.0f, (rnd()-0.5f)*15.0f, (rnd()-0.5f)*15.0f);
			pPhysEnt->Action(&physicsAction);
	}

	return bRetVal;
}
//////////////////////////////////////////////////////////////////////////
// NOTE: This function must be thread-safe. Before adding stuff contact MarcoC.
void CVehicleMovementHelicopter::ProcessMovement(const float deltaTime)
{
	FUNCTION_PROFILER( GetISystem(), PROFILE_GAME );

	IPhysicalEntity* pPhysics = GetPhysics();
	assert(pPhysics);
	
	if (m_arcade.m_handling.maxSpeedForward>0.f) // Use the new handling code
	{
		CryAutoCriticalSection lk(m_lock);

		if (!m_isEnginePowered)
			return;

		CVehicleMovementBase::ProcessMovement(deltaTime);
		SVehiclePhysicsStatus* physStatus = &m_physStatus[k_physicsThread];

		if(m_bApplyNoiseAsVelocity)
		{
			physStatus->v -= m_pNoise->m_posDifference;
			physStatus->w -= m_pNoise->m_angDifference;

			m_pNoise->Update(deltaTime);
		}

	
		///////////////////////////////////////////////////////////////
		// Pass on the movement request to the active physics handler
		// NB: m_physStatus is update by this call
		SVehiclePhysicsHelicopterProcessParams params;
		params.pPhysics = pPhysics;
		params.pPhysStatus = physStatus;
		params.pInputAction = &m_inputAction;
		params.dt = deltaTime;
		params.haveDriver = (m_actorId!=0)||m_remotePilot;
		params.isAI = m_movementAction.isAI;
		params.aiRequiredVel = m_CurrentVel;
		
		m_arcade.ProcessMovement(params);
		
		// Network error adjustment
		m_netPosAdjust *= max(0.f, 1.f-deltaTime*k_netErrorPosScale);
		physStatus->v += m_netPosAdjust * k_netErrorPosScale;

		if(m_bApplyNoiseAsVelocity)
		{
			physStatus->v += m_pNoise->m_posDifference;
			physStatus->w += m_pNoise->m_angDifference;
		}

		//===============================================
		// Commit the velocity back to the physics engine
		//===============================================
		// if (fabsf(m_movementAction.rotateYaw)>0.05f || vel.GetLengthSquared()>0.001f || m_chassis.vel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f || angVel.GetLengthSquared()>0.001f) 
		{
			pe_action_set_velocity setVelocity;
			setVelocity.v = physStatus->v;
			setVelocity.w = physStatus->w;
			pPhysics->Action(&setVelocity, 1);
		}
		///////////////////////////////////////////////////////////////
	}
	else
	{
		if (m_isEnginePowered && pPhysics)
		{
			m_movementAction.isAI = true;
	
			pe_status_pos psp;
			pe_status_dynamics psd;
			if (!pPhysics->GetStatus(&psp) || !pPhysics->GetStatus(&psd))
				return;
			UpdatePhysicsStatus(&m_physStatus[k_physicsThread], &psp, &psd);

			ProcessAI(deltaTime);
		}
	}
}
//------------------------------------------------------------------------
void CVehicleDamageBehaviorDetachPart::OnDamageEvent(EVehicleDamageBehaviorEvent event, const SVehicleDamageBehaviorEventParams& behaviorParams)
{
	if (event == eVDBE_Repair)
		return;

	if (!m_detachedEntityId && behaviorParams.componentDamageRatio >= 1.0f)
	{
    CVehiclePartBase* pPart = (CVehiclePartBase*)m_pVehicle->GetPart(m_partName.c_str());
    if (!pPart || !pPart->GetStatObj())
      return;

		if (max(1.f-behaviorParams.randomness, pPart->GetDetachProbability()) < cry_random(0.0f, 1.0f)) 
			return;

		IEntity* pDetachedEntity = SpawnDetachedEntity();
		if (!pDetachedEntity)
			return;

		m_detachedEntityId = pDetachedEntity->GetId();

    const Matrix34& partWorldTM = pPart->GetWorldTM();
    pDetachedEntity->SetWorldTM(partWorldTM);
		
    MovePartToTheNewEntity(pDetachedEntity, pPart);
		
		SEntityPhysicalizeParams physicsParams;
		physicsParams.mass = pPart->GetMass();
		physicsParams.type = PE_RIGID;    		    
		physicsParams.nSlot = 0;
		pDetachedEntity->Physicalize(physicsParams);
  
    IPhysicalEntity* pPhysics = pDetachedEntity->GetPhysics();
    if (pPhysics)
    {
      pe_params_part params;      
      params.flagsOR = geom_collides|geom_floats;
      params.flagsColliderAND = ~geom_colltype3;
      params.flagsColliderOR = geom_colltype0;
      pPhysics->SetParams(&params);

      pe_action_add_constraint ac;
      ac.flags = constraint_inactive|constraint_ignore_buddy;
      ac.pBuddy = m_pVehicle->GetEntity()->GetPhysics();
      ac.pt[0].Set(0,0,0);
      pPhysics->Action(&ac);
			
			// after 1s, remove the constraint again
			m_pVehicle->SetTimer(-1, 1000, this);
    
		  // set the impulse
		  const Vec3& velocity = m_pVehicle->GetStatus().vel;  				  		  
		  Vec3 baseForce = m_pVehicle->GetEntity()->GetWorldTM().TransformVector(pPart->GetDetachBaseForce());
		  baseForce *= cry_random(6.0f, 10.0f);
  		
      pe_action_impulse actionImpulse;
		  actionImpulse.impulse = physicsParams.mass * (velocity + baseForce);
      actionImpulse.angImpulse = physicsParams.mass * Vec3(cry_random(-1.0f,1.0f), cry_random(-1.0f,1.0f), cry_random(-1.0f,1.0f));
      actionImpulse.iApplyTime = 1;
		  
      pPhysics->Action(&actionImpulse);		
    }

		// copy vehicle's material to new entity (fixes detaching parts from vehicles with different paints),
		// or specify the destroyed material if it exists

		IStatObj* pExternalStatObj = pPart->GetExternalGeometry(false);	// Get undamaged external geometry (if any)
		IMaterial *pMaterial = pExternalStatObj ? pExternalStatObj->GetMaterial() : m_pVehicle->GetEntity()->GetMaterial();

		if(event == eVDBE_VehicleDestroyed || event == eVDBE_Hit)
		{
			if (pExternalStatObj)
			{
				if (IStatObj* pStatObj = pPart->GetExternalGeometry(true))     // Try to get the destroyed, external geometry material
					pMaterial = pStatObj->GetMaterial();
			}
			else if (m_pVehicle->GetDestroyedMaterial())  // If there is no external geometry, try the vehicle's destroyed material
			{
				pMaterial = m_pVehicle->GetDestroyedMaterial();
			}
		}

		pDetachedEntity->SetMaterial(pMaterial);
		
		AttachParticleEffect(pDetachedEntity, m_pEffect);

		if (m_notifyMovement)
		{
			SVehicleMovementEventParams params;
			params.iValue = pPart->GetIndex();
			m_pVehicle->GetMovement()->OnEvent(IVehicleMovement::eVME_PartDetached, params);
		}
	}
}
Ejemplo n.º 29
0
	virtual void ProcessEvent( EFlowEvent event, SActivationInfo *pActInfo )
	{
		if (!pActInfo->pEntity)
			return;

		if (event == eFE_Activate && IsPortActive(pActInfo, IN_ACTIVATE))
		{
			pe_action_impulse action;

			int ipart = GetPortInt( pActInfo, IN_PARTINDEX );
			if (ipart>0)
				action.ipart = ipart-1;

			IEntity* pEntity = pActInfo->pEntity;
			ECoordSys coordSys = (ECoordSys)GetPortInt( pActInfo, IN_COORDSYS );

			if (coordSys==CS_PARENT && !pEntity->GetParent())
				coordSys = CS_WORLD;

			// When a "zero point" is set in the node, the value is left undefined and physics assume it is the CM of the object.
			// but when the entity has a parent (is linked), then we have to use a real world coordinate for the point, because we have to apply the impulse to the highest entity 
			// on the hierarchy and physics will use the position of that entity instead of the position of the entity assigned to the node
			bool bHaveToUseTransformedZeroPoint = false;
			Vec3 transformedZeroPoint;
			Matrix34 transMat;

		  switch (coordSys)
			{
				case CS_WORLD:
				default:
				{
					transMat.SetIdentity();
					bHaveToUseTransformedZeroPoint = pEntity->GetParent()!=NULL;
					transformedZeroPoint = pEntity->GetWorldPos();
					break;
				}

				case CS_PARENT:
				{
					transMat = pEntity->GetParent()->GetWorldTM();
					bHaveToUseTransformedZeroPoint = pEntity->GetParent()->GetParent()!=NULL;
					transformedZeroPoint = pEntity->GetParent()->GetWorldPos();
					break;
				}

				case CS_LOCAL:
				{
					transMat = pEntity->GetWorldTM();
					bHaveToUseTransformedZeroPoint = pEntity->GetParent()!=NULL;
					transformedZeroPoint = pEntity->GetWorldPos();
					break;
				}
			}

			action.impulse = GetPortVec3( pActInfo, IN_IMPULSE );
			action.impulse = transMat.TransformVector( action.impulse );

			Vec3 angImpulse = GetPortVec3( pActInfo, IN_ANGIMPULSE );
			if (!angImpulse.IsZero())
				action.angImpulse = transMat.TransformVector( angImpulse );

			Vec3 pointApplication = GetPortVec3( pActInfo, IN_POINT );
			if (!pointApplication.IsZero())
				action.point = transMat.TransformPoint( pointApplication );
			else
			{
				if (bHaveToUseTransformedZeroPoint)
					action.point = transformedZeroPoint;
			}


			// the impulse has to be applied to the highest entity in the hierarchy. This comes from how physics manage linked entities.
			IEntity* pEntityImpulse = pEntity;
			while (pEntityImpulse->GetParent())
			{
				pEntityImpulse = pEntityImpulse->GetParent();
			}

			IPhysicalEntity * pPhysEntity = pEntityImpulse->GetPhysics();
			if (pPhysEntity)
				pPhysEntity->Action( &action );
		}
	}
Ejemplo n.º 30
0
void CTornado::UpdateFlow()
{
	IVehicleSystem* pVehicleSystem = g_pGame->GetIGameFramework()->GetIVehicleSystem();
	assert(pVehicleSystem);

	float frameTime(gEnv->pTimer->GetFrameTime());

	IPhysicalWorld *ppWorld = gEnv->pPhysicalWorld;

	Vec3 pos(GetEntity()->GetWorldPos());

	//first, check the entities in range
	m_nextEntitiesCheck -= frameTime;
	if (m_nextEntitiesCheck<0.0f)
	{
		m_nextEntitiesCheck = 1.0f;
		
		Vec3 radiusVec(m_radius,m_radius,0);
		
		IPhysicalEntity **ppList = NULL;

		int	numEnts = ppWorld->GetEntitiesInBox(pos-radiusVec,pos+radiusVec+Vec3(0,0,m_cloudHeight*0.5f),ppList,ent_sleeping_rigid|ent_rigid|ent_living);

		m_spinningEnts.clear();
		for (int i=0;i<numEnts;++i)
		{
			// add check for spectating players...
			EntityId id = ppWorld->GetPhysicalEntityId(ppList[i]);
			CActor* pActor = static_cast<CActor*>(g_pGame->GetIGameFramework()->GetIActorSystem()->GetActor(id));
			if(!pActor || !pActor->GetSpectatorMode())
			{
				m_spinningEnts.push_back(id);
			}
		}
		//OutputDistance();
	}

	//mess entities around
	for (size_t i=0;i<m_spinningEnts.size();++i)
	{
		IPhysicalEntity *ppEnt = ppWorld->GetPhysicalEntityById(m_spinningEnts[i]);
		if (ppEnt)
		{
			pe_status_pos spos;
			pe_status_dynamics sdyn;

			if (!ppEnt->GetStatus(&spos) || !ppEnt->GetStatus(&sdyn))
				continue;
		
			//gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(spos.pos,2.0f,ColorB(255,0,255,255));
						
			Vec3 delta(pos - spos.pos);
			delta.z = 0.0f;

			float dLen(delta.len());
			float forceMult(max(0.0f,(m_radius-dLen)/m_radius));

			if (dLen>0.001f)
				delta /= dLen;
			else
				delta.zero();

			Vec3 upVector(0,0,1);

			float spinImpulse(m_spinImpulse);
			float attractionImpulse(m_attractionImpulse);
			float upImpulse(m_upImpulse);

			if (ppEnt->GetType() == PE_LIVING)
			{
				upImpulse *= 0.75f;
				attractionImpulse *= 0.35f;
				spinImpulse *= 1.5f;
			}

			
			if (IVehicle* pVehicle = pVehicleSystem->GetVehicle(m_spinningEnts[i]))
			{
				IVehicleMovement* pMovement = pVehicle->GetMovement();

				if (pMovement && pMovement->GetMovementType() == IVehicleMovement::eVMT_Air)
				{
					SVehicleMovementEventParams params;
					params.fValue = forceMult;
					pMovement->OnEvent(IVehicleMovement::eVME_Turbulence, params);
				}
			}

			Vec3 spinForce( (delta % upVector) * spinImpulse );
			Vec3 attractionForce(delta * attractionImpulse);
			Vec3 upForce(0,0,upImpulse);

			pe_action_impulse aimpulse;

			aimpulse.impulse = (spinForce + attractionForce + upForce) * (forceMult * sdyn.mass * frameTime);
			aimpulse.angImpulse = (upVector + (delta % upVector)) * (gf_PI * 0.33f * forceMult * sdyn.mass * frameTime);

			aimpulse.iApplyTime = 0;
			ppEnt->Action(&aimpulse);

			//gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(spos.pos,ColorB(255,0,255,255),spos.pos+aimpulse.impulse.GetNormalizedSafe(ZERO),ColorB(255,0,255,255));
		}
	}
}