void CDockingPorts::UpdateDockingManeuvers (CSpaceObject *pOwner, DockingPort &Port) // UpdateDockingManeuvers // // Updates the motion of a ship docking with a port { CShip *pShip = Port.pObj->AsShip(); ASSERT(pShip); if (pShip == NULL) return; CVector vDest = pOwner->GetPos() + Port.vPos; CVector vDestVel = pOwner->GetVel(); // Figure out how far we are from where we want to be CVector vDelta = vDest - pShip->GetPos(); // Figure out if we're aligned int iFinalRotation = pShip->AlignToRotationAngle(Port.iRotation); // If the docking object is within the appropriate threshold // of the port, then complete the docking sequence. Metric rDelta2 = vDelta.Length2(); if (rDelta2 < DOCKING_THRESHOLD2 && (pShip == g_pUniverse->GetPlayer() || iFinalRotation == pShip->GetRotation())) { pShip->Place(vDest); pShip->UnfreezeControls(); IShipController *pController = pShip->GetController(); pController->SetManeuver(IShipController::NoRotation); Port.iStatus = psInUse; // Tell the owner that somone has docked with it first // (We do this because sometimes we want to handle stuff // in OnObjDocked before we show the player a dock screen) if (pOwner && pOwner->HasOnObjDockedEvent() && pOwner != pShip && !pOwner->IsDestroyed() && pShip->IsSubscribedToEvents(pOwner)) pOwner->FireOnObjDocked(pShip, pOwner); // Set the owner as "explored" (if the ship is the player) if (pShip->IsPlayer()) pOwner->SetExplored(); // Dock pShip->OnDocked(pOwner); // Notify other subscribers pShip->NotifyOnObjDocked(pOwner); } // Otherwise accelerate the ship towards the docking port else { Metric rMaxSpeed = pShip->GetMaxSpeed(); Metric rMinSpeed = rMaxSpeed / 10.0; // We slow down as we get closer Metric rSpeed; if (rDelta2 < FINAL_DOCKING2) rSpeed = rMinSpeed; else if (rDelta2 < FINAL_APPROACH2) { Metric rSpeedRange = rMaxSpeed - rMinSpeed; Metric rDelta = sqrt(rDelta2); rSpeed = rMinSpeed + (rSpeedRange * (rDelta - FINAL_DOCKING) / (FINAL_APPROACH - FINAL_DOCKING)); } else rSpeed = rMaxSpeed; // Figure out the ideal velocity vector that we want to // be following. CVector vIdealVel = vDelta.Normal() * rSpeed; // Calculate the delta v that we need CVector vDeltaV = vIdealVel - pShip->GetVel(); // Rotate if (!pShip->IsPlayer()) { IShipController *pController = pShip->GetController(); // If we're close enough, align to rotation angle if (rDelta2 < FINAL_APPROACH2) pController->SetManeuver(CalcTurnManeuver(iFinalRotation, pShip->GetRotation(), pShip->GetRotationAngle())); // Otherwise, align along delta v else pController->SetManeuver(CalcTurnManeuver(VectorToPolar(vDeltaV), pShip->GetRotation(), pShip->GetRotationAngle())); // Don't let the AI thrust pController->SetThrust(false); } // Accelerate pShip->Accelerate(vDeltaV * pShip->GetMass() / 10000.0, g_SecondsPerUpdate); pShip->ClipSpeed(rSpeed); } }
void CDockingPorts::UpdateAll (CSpaceObject *pOwner) // UpdateAll // // UpdateAll { int i, j; for (i = 0; i < m_iPortCount; i++) { if (m_pPort[i].iStatus == psDocking) { CShip *pShip = m_pPort[i].pObj->AsShip(); ASSERT(pShip); if (pShip == NULL) continue; CVector vDest = pOwner->GetPos() + m_pPort[i].vPos; CVector vDestVel = pOwner->GetVel(); // Figure out how far we are from where we want to be CVector vDelta = vDest - pShip->GetPos(); // Figure out if we're aligned int iFinalRotation = pShip->AlignToRotationAngle(m_pPort[i].iRotation); // If the docking object is within the appropriate threshold // of the port, then complete the docking sequence. Metric rDelta2 = vDelta.Length2(); if (rDelta2 < DOCKING_THRESHOLD2 && (pShip == g_pUniverse->GetPlayer() || iFinalRotation == pShip->GetRotation())) { pShip->Place(vDest); pShip->UnfreezeControls(); IShipController *pController = pShip->GetController(); pController->SetManeuver(IShipController::NoRotation); m_pPort[i].iStatus = psInUse; // Tell the owner that somone has docked with it first // (We do this because sometimes we want to handle stuff // in OnObjDocked before we show the player a dock screen) if (pOwner && pOwner->HasOnObjDockedEvent() && pOwner != pShip) pOwner->OnObjDocked(pShip, pOwner); // Dock pShip->OnDocked(pOwner); // Tell all objects in the system that a ship has docked CSystem *pSystem = pShip->GetSystem(); for (j = 0; j < pSystem->GetObjectCount(); j++) { CSpaceObject *pObj = pSystem->GetObject(j); if (pObj && pObj->HasOnObjDockedEvent() && pObj != pShip && pObj != pOwner) pObj->OnObjDocked(pShip, pOwner); } } // Otherwise accelerate the ship towards the docking port else { Metric rMaxSpeed = pShip->GetMaxSpeed(); Metric rMinSpeed = rMaxSpeed / 10.0; // We slow down as we get closer Metric rSpeed; if (rDelta2 < FINAL_DOCKING2) rSpeed = rMinSpeed; else if (rDelta2 < FINAL_APPROACH2) { Metric rSpeedRange = rMaxSpeed - rMinSpeed; Metric rDelta = sqrt(rDelta2); rSpeed = rMinSpeed + (rSpeedRange * (rDelta - FINAL_DOCKING) / (FINAL_APPROACH - FINAL_DOCKING)); } else rSpeed = rMaxSpeed; // Figure out the ideal velocity vector that we want to // be following. CVector vIdealVel = vDelta.Normal() * rSpeed; // Calculate the delta v that we need CVector vDeltaV = vIdealVel - pShip->GetVel(); // Rotate if (pShip != g_pUniverse->GetPlayer()) { IShipController *pController = pShip->GetController(); // If we're close enough, align to rotation angle if (rDelta2 < FINAL_APPROACH2) pController->SetManeuver(CalcTurnManeuver(iFinalRotation, pShip->GetRotation(), pShip->GetRotationAngle())); // Otherwise, align along delta v else pController->SetManeuver(CalcTurnManeuver(VectorToPolar(vDeltaV), pShip->GetRotation(), pShip->GetRotationAngle())); } // Accelerate pShip->Accelerate(vDeltaV * pShip->GetMass() / 10000.0, g_SecondsPerUpdate); pShip->ClipSpeed(rSpeed); } } } }