bool SkillKill::IsKickedCarKill(CPlayer* pKicker, CPlayer* pTargetPlayer, EntityId vehicleId) { if(pKicker->IsClient() && g_pGameCVars->g_mpKickableCars) { if (IVehicle* pKickedVehicle = g_pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle(vehicleId)) { if (CVehicleMovementBase* pMovement = StaticCast_CVehicleMovementBase(pKickedVehicle->GetMovement())) { if (const SVehicleMovementLargeObjectInfo* info = pMovement->GetLargeObjectInfo()) { if (info->kicker && info->kicker == pKicker->GetEntityId()) { return true; } } } } else { static const IEntityClass* pDestroyedVehicleClass = gEnv->pEntitySystem->GetClassRegistry()->FindClass("DestroyedVehicle"); CRY_ASSERT(pDestroyedVehicleClass); IEntity* pEntity = gEnv->pEntitySystem->GetEntity(vehicleId); return pEntity && pEntity->GetClass() == pDestroyedVehicleClass; } } return false; }
float CGameRulesMPDamageHandling::ProcessActorVehicleCollision(IActor* victimActor, EntityId victimId, IVehicle* pVehicle, EntityId vehicleId, float damage, const CGameRules::SCollisionHitInfo& collisionHitInfo, EntityId& kickerId) { kickerId = 0; if (g_pGameCVars->g_mpKickableCars) { if (CVehicleMovementBase* pMovement = StaticCast_CVehicleMovementBase(pVehicle->GetMovement())) { if (const SVehicleMovementLargeObjectInfo* info = pMovement->GetLargeObjectInfo()) { kickerId = info->kicker; } } } return ProcessActorKickedVehicle(victimActor, victimId, kickerId, vehicleId, damage, collisionHitInfo); }
void CVTOLVehicleManager::SetupMovement(EntityId entityId) { IVehicle* pVehicle = m_pVehicleSystem->GetVehicle(entityId); if(pVehicle) { if (CVehicleMovementBase* pMovement = StaticCast_CVehicleMovementBase(pVehicle->GetMovement())) { pMovement->Reset(); pMovement->SetRemotePilot(true); pMovement->StartDriving(0); } IGameObject* pGameObject = pVehicle->GetGameObject(); pGameObject->SetUpdateSlotEnableCondition(pVehicle, IVehicle::eVUS_Always, eUEC_WithoutAI); pGameObject->SetUpdateSlotEnableCondition(pVehicle, IVehicle::eVUS_EnginePowered, eUEC_WithoutAI); pGameObject->EnableUpdateSlot(pVehicle, IVehicle::eVUS_EnginePowered); pGameObject->EnableUpdateSlot(pVehicle, IVehicle::eVUS_Always); } }
//------------------------------------------------------------------------ void CVehicleViewSteer::Update(float dt) { IEntity * pEntity = m_pVehicle->GetEntity(); assert(pEntity); CVehicleMovementBase * pVehicleMovement = StaticCast_CVehicleMovementBase(m_pVehicle->GetMovement()); if (pVehicleMovement==NULL) return; const SVehiclePhysicsStatus& dynStatus = pVehicleMovement->GetPhysicsStatus(CVehicleMovementBase::k_mainThread); SMovementState movementState; pVehicleMovement->GetMovementState(movementState); const float pedal = pVehicleMovement->GetEnginePedal(); const float maxSpeed = movementState.maxSpeed; const Matrix34& pose = m_pAimPart ? m_pAimPart->GetWorldTM() : pEntity->GetWorldTM(); const Vec3 entityPos = pose.GetColumn3(); const Vec3 xAxis = pose.GetColumn0(); const Vec3 yAxis = pose.GetColumn1(); const Vec3 zAxis = pose.GetColumn2(); const float forwardSpeed = dynStatus.v.dot(yAxis); const float speedNorm = clamp_tpl(forwardSpeed / maxSpeed, 0.0f, 1.0f); const Vec3 maxRotation = m_maxRotation + speedNorm * (m_maxRotation2 - m_maxRotation); CalcLookAt(pose); if (m_lookAt.IsValid()) { if (!m_lastOffset.IsValid()) { m_position = pose * m_localSpaceCameraOffset; m_lastOffset = m_position - m_lookAt; m_lastOffsetBeforeElev = m_lastOffset; } Vec3 offset = m_lastOffsetBeforeElev; if (pedal<0.1f && forwardSpeed<1.0f) { // Going Backwards m_flags &= ~(eVCam_goingForwards | m_forwardFlags); m_flags |= m_backwardsFlags; } if (offset.dot(yAxis) < 0.8f && forwardSpeed>1.f) { // Going Forwards m_flags &= ~m_backwardsFlags; m_flags |= eVCam_goingForwards | m_forwardFlags; } float sensitivity = (1.f-speedNorm) * m_stickSensitivity.z + speedNorm * m_stickSensitivity2.z; float rotate = -m_rotatingAction.z * sensitivity; rotate = rotate * dt; if (zAxis.z > 0.1f) { // Safe to update curYaw Vec3 projectedX = xAxis; projectedX.z = 0.f; Vec3 projectedY = yAxis; projectedY.z = 0.f; const float newYaw = atan2_tpl(offset.dot(projectedX), -(offset.dot(projectedY))); const float maxChange = DEG2RAD(270.f)*dt; const float delta = clamp_tpl(newYaw - m_curYaw, -maxChange, +maxChange); m_curYaw += delta; } // Rotation Action { if (m_flags & eVCam_rotationClamp) { float newYaw = clamp_tpl(m_curYaw + rotate, -maxRotation.z, +maxRotation.z); rotate = newYaw - m_curYaw; rotate = clamp_tpl(newYaw - m_curYaw, -fabsf(rotate), +fabsf(rotate)); m_rotation.z += rotate; } else { m_rotation.z=0.f; } if (speedNorm > 0.1f) { float reduce = dt * 1.f; m_rotation.z = m_rotation.z - reduce*m_rotation.z/(fabsf(m_rotation.z) + reduce); } } // Ang Spring { float angSpeedCorrection = dt*dt*m_angSpeedCorrection/(dt*m_angSpeedCorrection+1.f)*dynStatus.w.z; if ((m_flags & eVCam_rotationSpring)==0) { m_angReturnSpeed = 0.f; angSpeedCorrection = 0.f; } float difference = m_rotation.z - m_curYaw; float relax = difference * (m_angReturnSpeed*dt) / ((m_angReturnSpeed*dt) + 1.f); const float delta = +relax + angSpeedCorrection + rotate; m_curYaw += delta; Matrix33 rot = Matrix33::CreateRotationZ(delta); offset = rot * offset; // Lerp the spring speed float angSpeedTarget = m_angReturnSpeed1 + speedNorm * (m_angReturnSpeed2 - m_angReturnSpeed1); m_angReturnSpeed += (angSpeedTarget - m_angReturnSpeed) * (dt/(dt+0.3f)); m_angSpeedCorrection += (m_angSpeedCorrection0 - m_angSpeedCorrection) * (dt/(dt+0.3f)); } if (!offset.IsValid()) offset = m_lastOffset; // Velocity influence Vec3 displacement = -((2.f-speedNorm) * dt) * dynStatus.v;// - yAxis*(0.0f*speedNorm*(yAxis.dot(dynStatus.v)))); float dot = offset.dot(displacement); if (dot < 0.f) { displacement = displacement + offset * -0.1f * (offset.dot(displacement) / offset.GetLengthSquared()); } offset = offset + displacement; const float radius0 = fabsf(m_localSpaceCameraOffset.y); const float minRadius = radius0 * m_radiusMin; const float maxRadius = radius0 * m_radiusMax; float radiusXY = sqrtf(sqr(offset.x) + sqr(offset.y)); Vec3 offsetXY = offset; offsetXY.z = 0.f; Vec3 accelerationV = (dynStatus.v - m_lastVehVel); float acceleration = offsetXY.dot(accelerationV) / radiusXY; m_lastVehVel = dynStatus.v; m_radiusVel -= acceleration; m_radius += m_radiusVel * dt - dt*m_radiusVelInfluence * offsetXY.dot(dynStatus.v)/radiusXY; m_radiusVel *= expf(-dt*m_radiusDampRate); m_radius += (radius0-m_radius)*(dt*m_radiusRelaxRate)/(dt*m_radiusRelaxRate+1.f); m_radius = clamp_tpl(m_radius, minRadius, maxRadius); offset = offset * (m_radius/radiusXY); // Vertical motion float targetOffsetHeight = m_localSpaceCameraOffset.z * (m_radius/radius0); float oldOffsetHeight = offset.z; offset.z += (targetOffsetHeight - offset.z)*(dt/(dt+0.3f)); Limit(offset.z, targetOffsetHeight - 2.f, targetOffsetHeight + 2.f); float verticalChange = offset.z - oldOffsetHeight; m_lastOffsetBeforeElev = offset; // Add up and down camera tilt { offset.z -= verticalChange; m_rotation.x += dt * m_stickSensitivity.x * m_rotatingAction.x; m_rotation.x = clamp_tpl(m_rotation.x, -maxRotation.x, +maxRotation.x); float elevAngleVehicle = m_inheritedElev * yAxis.z; // yAxis.z == approx elevation angle float elevationAngle = m_rotation.x - elevAngleVehicle; float sinElev, cosElev; sincos_tpl(elevationAngle, &sinElev, &cosElev); float horizLen = sqrtf(offset.GetLengthSquared2D()); float horizLenNew = horizLen * cosElev - sinElev * offset.z; if (horizLen>1e-4f) { horizLenNew /= horizLen; offset.x *= horizLenNew; offset.y *= horizLenNew; offset.z = offset.z * cosElev + sinElev * horizLen; } offset.z += verticalChange; } if (!offset.IsValid()) offset = m_lastOffset; m_position = m_lookAt + offset; // Perform world intersection test. { CRY_ASSERT(m_pVehicle); // Initialise sphere and direction. primitives::sphere sphere; sphere.center = m_lookAt; sphere.r = g_CameraRadius; Vec3 direction = m_position - m_lookAt; // Calculate camera bounds. AABB localBounds; m_pVehicle->GetEntity()->GetLocalBounds(localBounds); const float cameraBoundsScale = 0.75f; localBounds.min *= cameraBoundsScale; localBounds.max *= cameraBoundsScale; OBB cameraBounds; Matrix34 worldTM = m_pVehicle->GetEntity()->GetWorldTM(); cameraBounds.SetOBBfromAABB(Matrix33(worldTM), localBounds); // Try to find point on edge of camera bounds to begin swept sphere intersection test. Vec3 rayBoxIntersect; if(Intersect::Ray_OBB(Ray(m_position, -direction), worldTM.GetTranslation(), cameraBounds, rayBoxIntersect) > 0) { Vec3 temp = m_position - rayBoxIntersect; if(direction.Dot(temp) > 0.0f) { sphere.center = rayBoxIntersect; direction = temp; } } // Perform swept sphere intersection test against world. geom_contact *pContact = NULL; IPhysicalEntity *pSkipEntities[10]; float distance = gEnv->pPhysicalWorld->PrimitiveWorldIntersection(sphere.type, &sphere, direction, ent_static | ent_terrain | ent_rigid | ent_sleeping_rigid, &pContact, 0, (geom_colltype_player << rwi_colltype_bit) | rwi_stop_at_pierceable, 0, 0, 0, pSkipEntities, m_pVehicle->GetSkipEntities(pSkipEntities, 10)); if(distance > 0.0f) { // Sweep intersects world so calculate new offset. offset = (sphere.center + (direction.GetNormalizedSafe() * distance)) - m_lookAt; } } Interpolate(m_lastOffset, offset, 10.f, dt); m_position = m_lookAt + m_lastOffset; } else { CRY_ASSERT_MESSAGE(0, "camera will fail because lookat position is invalid"); } m_rotatingAction.zero(); }
virtual void ProcessEvent(EFlowEvent flowEvent, SActivationInfo* pActivationInfo) { if (flowEvent == eFE_Activate && IsPortActive(pActivationInfo, EIP_StartDriving)) { IEntity* pEntity = pActivationInfo->pEntity; if(!pEntity) return; IVehicle* pVehicle; pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle( pEntity->GetId() ); if(!pVehicle || pVehicle->IsDestroyed()) { return; } IVehicleMovement* pMovement = pVehicle->GetMovement(); if (!pMovement) return; CVehicleMovementBase* pMovementBase = StaticCast_CVehicleMovementBase(pMovement); if (!pMovementBase) return; IActor* pPlayer = g_pGame->GetIGameFramework()->GetClientActor(); if (!pPlayer) return; const EntityId localPlayer = pPlayer->GetEntityId(); if (pVehicle->GetSeatCount() == 0) // Don't need to remotely enter { pMovement->StartDriving(localPlayer); } else { pVehicle->EvictAllPassengers(); IVehicleSeat* pSeat = pVehicle->GetSeatById(1); if (pSeat) { // Can't use remote entering to control otherwise if vehicle blows up, player dies //pSeat->EnterRemotely(localPlayer); pMovement->StartDriving(localPlayer); m_prevSeatLockStatus = pSeat->GetLockedStatus(); pSeat->SetLocked(eVSLS_Locked); } } m_fDuration = GetPortFloat(pActivationInfo, EIP_Time); m_fSpeed = GetPortFloat(pActivationInfo, EIP_Speed); m_actInfo = *pActivationInfo; m_entityId = pEntity->GetId(); SetActive(true); } else if (flowEvent == eFE_Update) { if (!m_bActive) { if (m_bNeedsCleanup) { Cleanup(); } return; } IEntity* pEntity = pActivationInfo->pEntity; if(!pEntity) { SetActive(false); return; } IVehicle* pVehicle; pVehicle = gEnv->pGame->GetIGameFramework()->GetIVehicleSystem()->GetVehicle( pEntity->GetId() ); if(!pVehicle || pVehicle->IsDestroyed()) { SetActive(false); return; } const float curTime = gEnv->pTimer->GetFrameStartTime().GetSeconds(); if ((curTime - m_fStartedTime) >= m_fDuration) { SetActive(false); ActivateOutput(pActivationInfo, EOP_TimeComplete, true); } else // Update every frame { IVehicleMovement* pMovement = pVehicle->GetMovement(); if (pMovement) { // prevent full pedal being kept pressed, but give it a bit pMovement->OnAction(eVAI_MoveForward, eAAM_OnPress, 1.0f); } } } }