void CVehicleSeatActionRotateTurret::MaintainPartRotationWorldSpace(EVehicleTurretRotationType eType) { CVehiclePartBase* pPart = m_rotations[eType].m_pPart; IVehiclePart* pParent = pPart->GetParent(); IActor* pActor = m_pSeat->GetPassengerActor(); bool remote = m_pSeat->GetCurrentTransition() == IVehicleSeat::eVT_RemoteUsage; bool worldSpace = m_rotations[eType].m_worldSpace && VehicleCVars().v_independentMountedGuns != 0; if (worldSpace && pParent && pActor && pActor->IsClient() && !remote) { // we want to keep the old worldspace rotation // therefore we're updating the local transform from it // NB: there is no need to clamp here, its done later Matrix34 localTM = pParent->GetWorldTM().GetInverted() * Matrix34(m_rotations[eType].m_prevWorldQuat); localTM.OrthonormalizeFast(); // precision issue const Matrix34 &baseTM = pPart->GetLocalBaseTM(); if (!Matrix34::IsEquivalent(baseTM,localTM)) { Ang3 anglesCurr(baseTM); Ang3 angles(localTM); if (eType == eVTRT_Pitch) { angles.y = anglesCurr.y; angles.z = anglesCurr.z; } else if (eType == eVTRT_Yaw) { angles.x = anglesCurr.x; angles.y = anglesCurr.y; } localTM.SetRotationXYZ(angles); localTM.SetTranslation(baseTM.GetTranslation()); pPart->SetLocalBaseTM(localTM); m_pSeat->ChangedNetworkState(CVehicle::ASPECT_PART_MATRIX); } #if ENABLE_VEHICLE_DEBUG if (VehicleCVars().v_debugdraw == eVDB_Parts) { float color[] = {1,1,1,1}; Ang3 a(localTM), aBase(baseTM); gEnv->pRenderer->Draw2dLabel(200,200,1.4f,color,false,"localAng: %.1f (real: %.1f)", RAD2DEG(a.z), RAD2DEG(aBase.z)); } #endif } }
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; }