FVector UProjectileMovementComponent::LimitVelocity(FVector NewVelocity) const { const float CurrentMaxSpeed = GetMaxSpeed(); if (CurrentMaxSpeed > 0.f) { NewVelocity = NewVelocity.GetClampedToMaxSize(CurrentMaxSpeed); } return ConstrainDirectionToPlane(NewVelocity); }
static FVector CombineAdjustments(FVector CurrentAdjustment, FVector AdjustmentToAdd) { // remove the part of the new adjustment that's parallel to the current adjustment if (CurrentAdjustment.IsZero()) { return AdjustmentToAdd; } FVector Projection = AdjustmentToAdd.ProjectOnTo(CurrentAdjustment); Projection = Projection.GetClampedToMaxSize(CurrentAdjustment.Size()); FVector OrthogalAdjustmentToAdd = AdjustmentToAdd - Projection; return CurrentAdjustment + OrthogalAdjustmentToAdd; }
void UFlareSpacecraftNavigationSystem::PhysicSubTick(float DeltaSeconds) { TArray<UActorComponent*> Engines = Spacecraft->GetComponentsByClass(UFlareEngine::StaticClass()); if (Spacecraft->GetDamageSystem()->IsPowered()) { // Linear physics FVector DeltaV = LinearTargetVelocity - Spacecraft->GetLinearVelocity(); FVector DeltaVAxis = DeltaV; DeltaVAxis.Normalize(); bool Log = false; if (Spacecraft->GetParent()->GetCompany() == Spacecraft->GetGame()->GetPC()->GetCompany()) { //Log = true; } bool HasUsedOrbitalBoost = false; float LinearMasterAlpha = 0.f; float LinearMasterBoostAlpha = 0.f; if(Log) { FLOGV("PhysicSubTick DeltaSeconds=%f", DeltaSeconds); FLOGV("PhysicSubTick LinearTargetVelocity=%s", *LinearTargetVelocity.ToString()); FLOGV("PhysicSubTick Spacecraft->GetLinearVelocity()=%s", *Spacecraft->GetLinearVelocity().ToString()); FLOGV("PhysicSubTick DeltaV=%s", *DeltaV.ToString()); } if (!DeltaV.IsNearlyZero()) { // First, try without using the boost FVector Acceleration = DeltaVAxis * GetTotalMaxThrustInAxis(Engines, -DeltaVAxis, false).Size() / Spacecraft->GetSpacecraftMass(); float AccelerationDeltaV = Acceleration.Size() * DeltaSeconds; LinearMasterAlpha = FMath::Clamp(DeltaV.Size()/ AccelerationDeltaV, 0.0f, 1.0f); // Second, if the not enought trust check with the boost if (UseOrbitalBoost && AccelerationDeltaV < DeltaV.Size() ) { FVector AccelerationWithBoost = DeltaVAxis * GetTotalMaxThrustInAxis(Engines, -DeltaVAxis, true).Size() / Spacecraft->GetSpacecraftMass(); if (AccelerationWithBoost.Size() > Acceleration.Size()) { HasUsedOrbitalBoost = true; float BoostDeltaV = (AccelerationWithBoost.Size() - Acceleration.Size()) * DeltaSeconds; float DeltaVAfterClassicalAcceleration = DeltaV.Size() - AccelerationDeltaV; LinearMasterBoostAlpha = FMath::Clamp(DeltaVAfterClassicalAcceleration/ BoostDeltaV, 0.0f, 1.0f); Acceleration = AccelerationWithBoost; } } FVector ClampedAcceleration = Acceleration.GetClampedToMaxSize(DeltaV.Size() / DeltaSeconds); Spacecraft->Airframe->SetPhysicsLinearVelocity(ClampedAcceleration * DeltaSeconds * 100, true); // Multiply by 100 because UE4 works in cm } // Angular physics FVector DeltaAngularV = AngularTargetVelocity - Spacecraft->Airframe->GetPhysicsAngularVelocity(); FVector DeltaAngularVAxis = DeltaAngularV; DeltaAngularVAxis.Normalize(); if (!DeltaAngularV.IsNearlyZero()) { FVector SimpleAcceleration = DeltaAngularVAxis * AngularAccelerationRate; // Scale with damages float TotalMaxTorqueInAxis = GetTotalMaxTorqueInAxis(Engines, DeltaAngularVAxis, false); if (!FMath::IsNearlyZero(TotalMaxTorqueInAxis)) { float DamageRatio = GetTotalMaxTorqueInAxis(Engines, DeltaAngularVAxis, true) / TotalMaxTorqueInAxis; FVector DamagedSimpleAcceleration = SimpleAcceleration * DamageRatio; FVector ClampedSimplifiedAcceleration = DamagedSimpleAcceleration.GetClampedToMaxSize(DeltaAngularV.Size() / DeltaSeconds); Spacecraft->Airframe->SetPhysicsAngularVelocity(ClampedSimplifiedAcceleration * DeltaSeconds, true); } } // Update engine alpha for (int32 EngineIndex = 0; EngineIndex < Engines.Num(); EngineIndex++) { UFlareEngine* Engine = Cast<UFlareEngine>(Engines[EngineIndex]); FVector ThrustAxis = Engine->GetThrustAxis(); float LinearAlpha = 0; float AngularAlpha = 0; if (Spacecraft->IsPresentationMode()) { LinearAlpha = true; } else if (!DeltaV.IsNearlyZero() || !DeltaAngularV.IsNearlyZero()) { if(Engine->IsA(UFlareOrbitalEngine::StaticClass())) { if(HasUsedOrbitalBoost) { LinearAlpha = (-FVector::DotProduct(ThrustAxis, DeltaVAxis) + 0.2) * LinearMasterBoostAlpha; } AngularAlpha = 0; } else { LinearAlpha = -FVector::DotProduct(ThrustAxis, DeltaVAxis) * LinearMasterAlpha; FVector EngineOffset = (Engine->GetComponentLocation() - COM) / 100; FVector TorqueDirection = FVector::CrossProduct(EngineOffset, ThrustAxis); TorqueDirection.Normalize(); if (!DeltaAngularV.IsNearlyZero() && !Engine->IsA(UFlareOrbitalEngine::StaticClass())) { AngularAlpha = -FVector::DotProduct(TorqueDirection, DeltaAngularVAxis); } } } Engine->SetAlpha(FMath::Clamp(LinearAlpha + AngularAlpha, 0.0f, 1.0f)); } } else { // Shutdown engines for (int32 EngineIndex = 0; EngineIndex < Engines.Num(); EngineIndex++) { UFlareEngine* Engine = Cast<UFlareEngine>(Engines[EngineIndex]); Engine->SetAlpha(0); } } }