//------------------------------------------------------------------------ void CVehicleSeatActionRotateTurret::UpdateAimGoal() { Vec3 aimGoalLocal = m_pVehicle->GetEntity()->GetWorldTM().GetInverted() * m_aimGoal; IVehiclePart* pPitchPart = m_rotations[eVTRT_Pitch].m_pPart; if (pPitchPart) { Vec3 pitchPartToAimGoal = aimGoalLocal - pPitchPart->GetLocalTM(false).GetTranslation(); Quat pitchAimDir = Quat::CreateRotationVDir(pitchPartToAimGoal.GetNormalizedSafe()); Ang3 desiredPitchAngles(pitchAimDir); Ang3 currentPitchAngles(pPitchPart->GetLocalTM(false)); m_rotations[eVTRT_Pitch].m_action = desiredPitchAngles.x - currentPitchAngles.x; } IVehiclePart* pYawPart = m_rotations[eVTRT_Yaw].m_pPart; if (pYawPart) { Vec3 yawPartToAimGoal = aimGoalLocal - pYawPart->GetLocalTM(false).GetTranslation(); Quat yawAimDir = Quat::CreateRotationVDir(yawPartToAimGoal.GetNormalizedSafe()); Ang3 desiredYawAngles(yawAimDir); Ang3 currentYawAngles(pYawPart->GetLocalTM(false)); m_rotations[eVTRT_Yaw].m_action = fmod(desiredYawAngles.z - currentYawAngles.z + 3.0f * gf_PI, gf_PI2) - gf_PI; } }
//------------------------------------------------------------------------ bool CVehicleSeatActionRotateTurret::GetRemainingAnglesToAimGoalInDegrees(float &pitch, float &yaw) { // no aim goal set (or it got cleared)? if (m_aimGoal.IsZero()) { return false; // have no aim goal } IVehiclePart* pPitchPart = m_rotations[eVTRT_Pitch].m_pPart; IVehiclePart* pYawPart = m_rotations[eVTRT_Yaw].m_pPart; if (!pYawPart) { pitch = yaw = 0.0f; return true; // have an aim goal } // aim goal is a world pos. Convert it to vehicle space: Vec3 aimGoalLocal = m_pVehicle->GetEntity()->GetWorldTM().GetInverted() * m_aimGoal; // direction from yaw part pivot to aim goal Vec3 yawPartToAimGoal = aimGoalLocal - pYawPart->GetLocalTM(false).GetTranslation(); // angles from yaw part to aim goal Quat aimDir = Quat::CreateRotationVDir(yawPartToAimGoal.GetNormalizedSafe()); Ang3 desiredAngles(aimDir); if (pPitchPart) { Ang3 pitchAngles(pPitchPart->GetLocalTM(false)); pitch = RAD2DEG(desiredAngles.x - pitchAngles.x); pitch = fmod(pitch, 360.0f); } else { pitch = 0.0f; } Ang3 yawAngles(pYawPart->GetLocalTM(false)); yaw = RAD2DEG(desiredAngles.z - yawAngles.z); yaw = fmod(yaw, 360.0f); return true; // have an aim goal }
//------------------------------------------------------------------------ void CVehicleHelper::GetVehicleTM(Matrix34& vehicleTM, bool forced) const { vehicleTM = m_localTM; IVehiclePart* pParent = m_pParentPart; while (pParent) { vehicleTM = pParent->GetLocalTM(true, forced) * vehicleTM; pParent = pParent->GetParent(); } }
void CVehicleWeaponPulseC::Update(SEntityUpdateContext& ctx, int update) { if(!m_vehicleId && GetEntity()->GetParent()) { m_vehicleId = GetEntity()->GetParent()->GetId(); CRY_ASSERT(gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(m_vehicleId) && "Using VehicleWeapons on non-vehicles may lead to unexpected behavior."); } IVehicle* pVehicle = GetVehicle(); if(pVehicle) { IVehiclePart* pPart = pVehicle->GetWeaponParentPart(GetEntityId()); if(pPart) { const Matrix34& partWorldTM = pPart->GetWorldTM(); const Vec3 partDirection = partWorldTM.GetColumn1(); const Vec3 partPosition = partWorldTM.GetTranslation(); //ColorB col(255, 0, 0); //gEnv->pRenderer->GetIRenderAuxGeom()->DrawLine(partPosition, col, partPosition + 100.0f * partDirection, col, 2.0f); //ok, ok, i'll optimise this later Matrix34 mat = pVehicle->GetEntity()->GetWorldTM(); Matrix33 matO(mat); matO.Invert(); const Vec3 diff = (m_TargetPos - partPosition).GetNormalized(); m_destination.SetLerp(partDirection, diff, ctx.fFrameTime); Quat quat1; //quat1.SetRotationVDir(diff, 0.0f); quat1.SetRotationVDir(m_destination.GetNormalized(), 0.0f); Matrix33 mat2(quat1); mat2 = matO * mat2; m_destination = m_destination * 10000.0f + partPosition; m_targetPosition = m_destination; m_aimPosition = m_destination; pPart->SetLocalTM(Matrix34(mat2, pPart->GetLocalTM(true, true).GetTranslation())); } } Base::Update(ctx, update); }
//------------------------------------------------------------------------ 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; }