bool UFlareSpacecraftNavigationSystem::Undock() { // Try undocking if (IsDocked()) { FLOGV("UFlareSpacecraftNavigationSystem::Undock : '%s' undocking from '%s'", *Spacecraft->GetParent()->GetImmatriculation().ToString(), *Data->DockedTo.ToString()); // Detach from station if(DockConstraint) { DockConstraint->BreakConstraint(); DockConstraint->DestroyComponent(); DockConstraint = NULL; } AFlareSpacecraft* DockStation = GetDockStation(); DockStation->GetDockingSystem()->ReleaseDock(Spacecraft, Data->DockedAt); // Update data SetStatus(EFlareShipStatus::SS_AutoPilot); Data->DockedTo = NAME_None; Data->DockedAt = -1; // Update Angular acceleration rate : when it's docked the mass is the ship mass + the station mass Spacecraft->SetRCSDescription(Spacecraft->GetRCSDescription()); Spacecraft->OnUndocked(DockStation); // Leave PushCommandLocation(Spacecraft->GetRootComponent()->GetComponentTransform().TransformPositionNoScale(5000 * FVector(-1, 0, 0))); FLOG("UFlareSpacecraftNavigationSystem::Undock : successful"); // Hack for bug #195: for ue4 to reweld all. Spacecraft->Airframe->SetSimulatePhysics(false); Spacecraft->Airframe->SetSimulatePhysics(true); return true; } // Failed else { FLOGV("UFlareSpacecraftNavigationSystem::Undock : '%s' is not docked", *Spacecraft->GetParent()->GetImmatriculation().ToString()); return false; } }
void UFlareSpacecraftNavigationSystem::AbortAllCommands() { FFlareShipCommandData Command; while (CommandData.Dequeue(Command)) { FLOGV("UFlareSpacecraftNavigationSystem::AbortAllCommands : '%s' has aborted command '%s'", *Spacecraft->GetParent()->GetImmatriculation().ToString(), *EFlareCommandDataType::ToString(Command.Type)); if (Command.Type == EFlareCommandDataType::CDT_Dock) { // Release dock grant AFlareSpacecraft* Station = Command.ActionTarget; Station->GetDockingSystem()->ReleaseDock(Spacecraft, Command.ActionTargetParam); } } SetStatus(EFlareShipStatus::SS_Manual); }
void UFlareSpacecraftNavigationSystem::CheckCollisionDocking(AFlareSpacecraft* DockingCandidate) { if (IsAutoPilot()) { FFlareShipCommandData CurrentCommand; if (CommandData.Peek(CurrentCommand)) { if (CurrentCommand.Type == EFlareCommandDataType::CDT_Dock) { // We are in a automatic docking process AFlareSpacecraft* DockStation = CurrentCommand.ActionTarget; if (DockStation != DockingCandidate) { // The hit spacecraft is not the docking target station return; } // Check dock alignement // TODO Put to external constants float DockingAngleLimit = 2; // 1° of angle error to dock float DockingVelocityLimit = 200; // 1 m/s float DockingLateralVelocityLimit = 20; // 10 cm/s float DockingAngularVelocityLimit = 10; // 5 °/s int32 DockId = CurrentCommand.ActionTargetParam; FVector ShipAngularVelocity = Spacecraft->Airframe->GetPhysicsAngularVelocity(); FVector ShipDockLocation = GetDockLocation(); FFlareDockingInfo StationDockInfo = DockStation->GetDockingSystem()->GetDockInfo(DockId); FVector StationCOM = DockStation->Airframe->GetBodyInstance()->GetCOMPosition(); FVector StationAngularVelocity = DockStation->Airframe->GetPhysicsAngularVelocity(); FVector StationDockLocation = DockStation->Airframe->GetComponentTransform().TransformPosition(StationDockInfo.LocalLocation); FVector StationDockSelfRotationInductedLinearVelocity = (PI / 180.f) * FVector::CrossProduct(StationAngularVelocity, StationDockLocation- StationCOM); FVector ShipDockSelfRotationInductedLinearVelocity = (PI / 180.f) * FVector::CrossProduct(ShipAngularVelocity, ShipDockLocation-COM); FVector StationDockLinearVelocity = StationDockSelfRotationInductedLinearVelocity + DockStation->GetLinearVelocity() * 100; FVector ShipDockLinearVelocity = ShipDockSelfRotationInductedLinearVelocity + Spacecraft->GetLinearVelocity() * 100; FVector ShipDockAxis = Spacecraft->Airframe->GetComponentToWorld().GetRotation().RotateVector(FVector(1, 0, 0)); // Ship docking port are always at front FVector StationDockAxis = DockStation->Airframe->GetComponentToWorld().GetRotation().RotateVector(StationDockInfo.LocalAxis); float DockToDockAngle = FMath::RadiansToDegrees(FMath::Acos(FVector::DotProduct(-ShipDockAxis, StationDockAxis))); FVector RelativeDockToDockLinearVelocity = StationDockLinearVelocity - ShipDockLinearVelocity; // Angular velocity must be the same FVector RelativeDockAngularVelocity = ShipAngularVelocity - StationAngularVelocity; // Check if dockable bool OkForDocking = true; if (DockToDockAngle > DockingAngleLimit) { //FLOG("OkForDocking ? Not aligned"); // Not aligned OkForDocking = false; } else if (RelativeDockToDockLinearVelocity.Size() > DockingVelocityLimit) { //FLOG("OkForDocking ? Too fast"); // Too fast OkForDocking = false; } else if (FVector::VectorPlaneProject(RelativeDockToDockLinearVelocity, StationDockAxis).Size() > DockingLateralVelocityLimit) { //FLOG("OkForDocking ? Too much lateral velocity"); // Too much lateral velocity OkForDocking = false; } else if (RelativeDockAngularVelocity.Size() > DockingAngularVelocityLimit) { //FLOG("OkForDocking ? Too much angular velocity"); // Too much angular velocity OkForDocking = false; } if (OkForDocking) { // All is ok for docking, perform dock //FLOG(" Ok for docking after hit"); ConfirmDock(DockStation, DockId); return; } } } } }