void SpaceStation::PositionDockedShip(Ship *ship, int port) { SpaceStationType::positionOrient_t dport; PiVerify(m_type->GetDockAnimPositionOrient(port, m_type->numDockingStages, 1.0f, vector3d(0.0), dport, ship)); // const positionOrient_t *dport = &this->port[port]; const int dockMethod = m_type->dockMethod; if (dockMethod == SpaceStationType::ORBITAL) { matrix4x4d rot; GetRotMatrix(rot); vector3d p = GetPosition() + rot*dport.pos; ship->SetFrame(GetFrame()); ship->SetPosition(p); // duplicated from DoDockingAnimation() vector3d zaxis = dport.xaxis.Cross(dport.yaxis); ship->SetRotMatrix(matrix4x4d::MakeRotMatrix(dport.xaxis, dport.yaxis, zaxis) * rot); } else { Aabb aabb; ship->GetAabb(aabb); matrix4x4d stationRot; GetRotMatrix(stationRot); vector3d port_z = dport.xaxis.Cross(dport.yaxis); matrix4x4d rot = stationRot * matrix4x4d::MakeRotMatrix(dport.xaxis, dport.yaxis, port_z); // position slightly (1m) off landing surface vector3d pos = GetPosition() + stationRot*(dport.pos + dport.yaxis - dport.yaxis*aabb.min.y); ship->SetPosition(pos); ship->SetRotMatrix(rot); } }
/* The drawbacks of stuffing stuff into integers */ static int GetCrimeIdxFromEnum(enum Crime crime) { PiVerify(crime); for (int i=0; i<64; i++) { if (crime & (1<<i)) return i; } return 0; }
bool SpaceStation::OnCollision(Object *b, Uint32 flags, double relVel) { if ((flags & 0x10) && (b->IsType(Object::SHIP))) { Ship *s = static_cast<Ship*>(b); int port = -1; for (int i=0; i<MAX_DOCKING_PORTS; i++) { if (m_shipDocking[i].ship == s) { port = i; break; } } if (port == -1) return false; // no permission if (!m_type->dockOneAtATimePlease) { if (port != int(flags & 0xf)) return false; // wrong port } if (m_shipDocking[port].stage != 1) return false; // already docking? SpaceStationType::positionOrient_t dport; // why stage 2? Because stage 1 is permission to dock // granted, stage 2 is start of docking animation. PiVerify(m_type->GetDockAnimPositionOrient(port, 2, 0.0, vector3d(0.0), dport, s)); // must be oriented sensibly and have wheels down if (IsGroundStation()) { vector3d dockingNormal = GetOrient()*dport.yaxis; const double dot = s->GetOrient().VectorY().Dot(dockingNormal); if ((dot < 0.99) || (s->GetWheelState() < 1.0)) return false; // <0.99 harsh? if (s->GetVelocity().Length() > MAX_LANDING_SPEED) return false; } // if there is more docking port anim to do, don't set docked yet if (m_type->numDockingStages >= 2) { shipDocking_t &sd = m_shipDocking[port]; sd.ship = s; sd.stage = 2; sd.stagePos = 0; sd.fromPos = (s->GetPosition() - GetPosition()) * GetOrient(); // station space sd.fromRot = Quaterniond::FromMatrix3x3(GetOrient().Transpose() * s->GetOrient()); if (m_type->dockOneAtATimePlease) m_dockingLock = true; s->SetFlightState(Ship::DOCKING); s->SetVelocity(vector3d(0.0)); s->SetAngVelocity(vector3d(0.0)); s->ClearThrusterState(); } else { s->SetDockedWith(this, port); // bounces back to SS::SetDocked() LuaEvent::Queue("onShipDocked", s, this); } return false; } else { return true; } }
vector3d SpaceStation::GetTargetIndicatorPosition(const Frame *relTo) const { // return the next waypoint if permission has been granted for player, // and the docking point's position once the docking anim starts for (int i=0; i<MAX_DOCKING_PORTS; i++) { if (i >= m_type->numDockingPorts) break; if ((m_shipDocking[i].ship == Pi::player) && (m_shipDocking[i].stage > 0)) { SpaceStationType::positionOrient_t dport; if (!m_type->GetShipApproachWaypoints(i, m_shipDocking[i].stage+1, dport)) PiVerify(m_type->GetDockAnimPositionOrient(i, m_type->numDockingStages, 1.0f, vector3d(0.0), dport, m_shipDocking[i].ship)); vector3d v = GetInterpPositionRelTo(relTo); return v + GetInterpOrientRelTo(relTo) * dport.pos; } } return GetInterpPositionRelTo(relTo); }
vector3d SpaceStation::GetTargetIndicatorPosition(const Frame *relTo) const { // return the next waypoint if permission has been granted for player, // and the docking point's position once the docking anim starts for (int i=0; i<MAX_DOCKING_PORTS; i++) { if (i >= m_type->numDockingPorts) break; if ((m_shipDocking[i].ship == Pi::player) && (m_shipDocking[i].stage > 0)) { SpaceStationType::positionOrient_t dport; if (!m_type->GetShipApproachWaypoints(i, m_shipDocking[i].stage+1, dport)) PiVerify(m_type->GetDockAnimPositionOrient(i, m_type->numDockingStages, 1.0f, vector3d(0.0), dport, m_shipDocking[i].ship)); matrix4x4d rot; GetRotMatrix(rot); matrix4x4d m; Frame::GetFrameRenderTransform(GetFrame(), relTo, m); return m * (GetInterpolatedPosition() + (rot*dport.pos)); } } return GetInterpolatedPositionRelTo(relTo); }
void SpaceStation::PositionDockedShip(Ship *ship, int port) const { const shipDocking_t &dt = m_shipDocking[port]; SpaceStationType::positionOrient_t dport; PiVerify(m_type->GetDockAnimPositionOrient(port, dt.stage, dt.stagePos, dt.fromPos, dport, ship)); assert(dt.ship == ship); ship->SetPosition(GetPosition() + GetOrient()*dport.pos); // Still in docking animation process? if (dt.stage <= m_type->numDockingStages) { matrix3x3d wantRot = matrix3x3d::FromVectors(dport.xaxis, dport.yaxis); // use quaternion spherical linear interpolation to do // rotation smoothly Quaterniond wantQuat = Quaterniond::FromMatrix3x3(wantRot); Quaterniond q = Quaterniond::Nlerp(dt.fromRot, wantQuat, dt.stagePos); wantRot = q.ToMatrix3x3<double>(); ship->SetOrient(GetOrient() * wantRot); } else { // Note: ship bounding box is used to generate dport.pos ship->SetOrient(GetOrient() * matrix3x3d::FromVectors(dport.xaxis, dport.yaxis)); } }
void SpaceStation::DockingUpdate(const double timeStep) { vector3d p1, p2, zaxis; for (int i=0; i<MAX_DOCKING_PORTS; i++) { shipDocking_t &dt = m_shipDocking[i]; if (!dt.ship) continue; // docked stage is m_type->numDockingPorts + 1 => ship docked if (dt.stage > m_type->numDockingStages) continue; double stageDuration = (dt.stage > 0 ? m_type->dockAnimStageDuration[dt.stage-1] : m_type->undockAnimStageDuration[abs(dt.stage)-1]); dt.stagePos += timeStep / stageDuration; if (dt.stage == 1) { // SPECIAL stage! Docking granted but waiting for ship to dock m_doorAnimationStep = 0.3; // open door if (dt.stagePos >= 1.0) { if (dt.ship == static_cast<Ship*>(Pi::player)) Pi::onDockingClearanceExpired.emit(this); dt.ship = 0; dt.stage = 0; m_doorAnimationStep = -0.3; // close door } continue; } if (dt.stagePos > 1.0) { // use end position of last segment for start position of new segment SpaceStationType::positionOrient_t dport; PiVerify(m_type->GetDockAnimPositionOrient(i, dt.stage, 1.0f, dt.fromPos, dport, dt.ship)); matrix3x3d fromRot = matrix3x3d::FromVectors(dport.xaxis, dport.yaxis); dt.fromRot = Quaterniond::FromMatrix3x3(fromRot); dt.fromPos = dport.pos; // transition between docking stages dt.stagePos = 0; if (dt.stage >= 0) dt.stage++; else dt.stage--; } if (dt.stage < -m_type->shipLaunchStage && dt.ship->GetFlightState() != Ship::FLYING) { // launch ship dt.ship->SetFlightState(Ship::FLYING); dt.ship->SetAngVelocity(GetAngVelocity()); if (m_type->dockMethod == SpaceStationType::SURFACE) { dt.ship->SetThrusterState(1, 1.0); // up } else { dt.ship->SetThrusterState(2, -1.0); // forward } LuaEvent::Queue("onShipUndocked", dt.ship, this); } if (dt.stage < -m_type->numUndockStages) { // undock animation finished, clear port dt.stage = 0; dt.ship = 0; if (m_type->dockOneAtATimePlease) m_dockingLock = false; m_doorAnimationStep = -0.3; // close door } else if (dt.stage > m_type->numDockingStages) { // set docked dt.ship->SetDockedWith(this, i); LuaEvent::Queue("onShipDocked", dt.ship, this); if (m_type->dockOneAtATimePlease) m_dockingLock = false; m_doorAnimationStep = -0.3; // close door } } m_doorAnimationState = Clamp(m_doorAnimationState + m_doorAnimationStep*timeStep, 0.0, 1.0); if (m_doorAnimation) m_doorAnimation->SetProgress(m_doorAnimationState); }
void SpaceStation::DockingUpdate(const double timeStep) { vector3d p1, p2, zaxis; for (Uint32 i=0; i<m_shipDocking.size(); i++) { shipDocking_t &dt = m_shipDocking[i]; if (!dt.ship) continue; // docked stage is m_type->NumDockingPorts() + 1 => ship docked if (dt.stage > m_type->NumDockingStages()) continue; double stageDuration = (dt.stage > 0 ? m_type->GetDockAnimStageDuration(dt.stage-1) : m_type->GetUndockAnimStageDuration(abs(dt.stage)-1)); dt.stagePos += timeStep / stageDuration; if (dt.stage == 1) { // SPECIAL stage! Docking granted but waiting for ship to dock m_doorAnimationStep = 0.3; // open door if (dt.stagePos >= 1.0) { if (dt.ship == Pi::player) Pi::game->log->Add(GetLabel(), Lang::DOCKING_CLEARANCE_EXPIRED); dt.ship = 0; dt.stage = 0; m_doorAnimationStep = -0.3; // close door } continue; } if (dt.stagePos > 1.0) { // use end position of last segment for start position of new segment SpaceStationType::positionOrient_t dport; PiVerify(m_type->GetDockAnimPositionOrient(i, dt.stage, 1.0f, dt.fromPos, dport, dt.ship)); matrix3x3d fromRot = matrix3x3d::FromVectors(dport.xaxis, dport.yaxis, dport.zaxis); dt.fromRot = Quaterniond::FromMatrix3x3(fromRot); dt.fromPos = dport.pos; // transition between docking stages dt.stagePos = 0; if (dt.stage >= 0) dt.stage++; else dt.stage--; } if (dt.stage < -m_type->ShipLaunchStage() && dt.ship->GetFlightState() != Ship::FLYING) { // launch ship dt.ship->SetFlightState(Ship::FLYING); dt.ship->SetAngVelocity(GetAngVelocity()); if (m_type->IsSurfaceStation()) { dt.ship->SetThrusterState(1, 1.0); // up } else { dt.ship->SetThrusterState(2, -1.0); // forward } LuaEvent::Queue("onShipUndocked", dt.ship, this); } if (dt.stage < -m_type->NumUndockStages()) { // undock animation finished, clear port dt.stage = 0; dt.ship = 0; LockPort(i, false); m_doorAnimationStep = -0.3; // close door } else if (dt.stage > m_type->NumDockingStages()) { // set docked dt.ship->SetDockedWith(this, i); LuaEvent::Queue("onShipDocked", dt.ship, this); LockPort(i, false); m_doorAnimationStep = -0.3; // close door } } m_doorAnimationState = Clamp(m_doorAnimationState + m_doorAnimationStep*timeStep, 0.0, 1.0); if (m_doorAnimation) m_doorAnimation->SetProgress(m_doorAnimationState); }
bool SpaceStation::OnCollision(Object *b, Uint32 flags, double relVel) { if ((flags & 0x10) && (b->IsType(Object::SHIP))) { Ship *s = static_cast<Ship*>(b); matrix4x4d rot; GetRotMatrix(rot); bool canDock = true; int port = -1; for (int i=0; i<MAX_DOCKING_PORTS; i++) { if (m_shipDocking[i].ship == s) { port = i; break; } } if (m_type->dockOneAtATimePlease) { for (int i=0; i<m_type->numDockingPorts; i++) { if (m_shipDocking[i].ship && m_shipDocking[i].stage != 1 && (m_shipDocking[i].stage != m_type->numDockingStages+1)) { canDock = false; break; } } } else { // for non-dockOneAtATimePlease, the ship is expected // to hit the right docking trigger surface for that port if (m_shipDocking[flags&0xf].ship != s) canDock = false; } if (port == -1) canDock = false; // hitting docking area of a station if (canDock) { SpaceStationType::positionOrient_t dport; // why stage 2? Because stage 1 is permission to dock // granted, stage 2 is start of docking animation. PiVerify(m_type->GetDockAnimPositionOrient(port, 2, 0.0f, vector3d(0.0), dport, s)); double speed = s->GetVelocity().Length(); // must be oriented sensibly and have wheels down if (IsGroundStation()) { matrix4x4d shiprot; s->GetRotMatrix(shiprot); matrix4x4d invShipRot = shiprot.InverseOf(); vector3d dockingNormal = rot*dport.yaxis; // check player is sortof sensibly oriented for landing const double dot = vector3d(invShipRot[1], invShipRot[5], invShipRot[9]).Dot(dockingNormal); if ((dot < 0.99) || (s->GetWheelState() < 1.0)) return false; } if ((speed < MAX_LANDING_SPEED) && (!s->GetDockedWith()) && (m_shipDocking[port].stage == 1)) { // if there is more docking port anim to do, // don't set docked yet if (m_type->numDockingStages >= 2) { shipDocking_t &sd = m_shipDocking[port]; sd.ship = s; sd.stage = 2; sd.stagePos = 0; sd.fromPos = rot.InverseOf() * (s->GetPosition() - GetPosition()); matrix4x4d temp; s->GetRotMatrix(temp); sd.fromRot = Quaterniond::FromMatrix4x4(temp); s->Disable(); s->ClearThrusterState(); s->SetFlightState(Ship::DOCKING); } else { s->SetDockedWith(this, port); LuaEvent::Queue("onShipDocked", s, this); } } } return false; } else { return true; } }
void SpaceStationType::OnSetupComplete() { SceneGraph::Model::TVecMT approach_mts; SceneGraph::Model::TVecMT docking_mts; SceneGraph::Model::TVecMT leaving_mts; model->FindTagsByStartOfName("approach_", approach_mts); model->FindTagsByStartOfName("docking_", docking_mts); model->FindTagsByStartOfName("leaving_", leaving_mts); { SceneGraph::Model::TVecMT::const_iterator apprIter = approach_mts.begin(); for (; apprIter!=approach_mts.end() ; ++apprIter) { int bay, stage; PiVerify(2 == sscanf((*apprIter)->GetName().c_str(), "approach_stage%d_bay%d", &stage, &bay)); PiVerify(bay>0 && stage>0); SBayGroup* pGroup = GetGroupByBay(bay-1); assert(pGroup); pGroup->m_approach[stage] = (*apprIter)->GetTransform(); } SceneGraph::Model::TVecMT::const_iterator dockIter = docking_mts.begin(); for (; dockIter!=docking_mts.end() ; ++dockIter) { int bay, stage; PiVerify(2 == sscanf((*dockIter)->GetName().c_str(), "docking_stage%d_bay%d", &stage, &bay)); PiVerify(bay>0 && stage>0); m_ports[bay].m_docking[stage+1] = (*dockIter)->GetTransform(); } SceneGraph::Model::TVecMT::const_iterator leaveIter = leaving_mts.begin(); for (; leaveIter!=leaving_mts.end() ; ++leaveIter) { int bay, stage; PiVerify(2 == sscanf((*leaveIter)->GetName().c_str(), "leaving_stage%d_bay%d", &stage, &bay)); PiVerify(bay>0 && stage>0); m_ports[bay].m_leaving[stage] = (*leaveIter)->GetTransform(); } assert(!m_ports.empty()); assert(numDockingStages > 0); assert(numUndockStages > 0); for (PortMap::const_iterator pIt = m_ports.begin(), pItEnd = m_ports.end(); pIt!=pItEnd; ++pIt) { if (Uint32(numDockingStages-1) < pIt->second.m_docking.size()) { Error( "(%s): numDockingStages (%d) vs number of docking stages (" SIZET_FMT ")\n" "Must have at least the same number of entries as the number of docking stages " "PLUS the docking timeout at the start of the array.", modelName.c_str(), (numDockingStages-1), pIt->second.m_docking.size()); } else if (Uint32(numDockingStages-1) != pIt->second.m_docking.size()) { Warning( "(%s): numDockingStages (%d) vs number of docking stages (" SIZET_FMT ")\n", modelName.c_str(), (numDockingStages-1), pIt->second.m_docking.size()); } if (0!=pIt->second.m_leaving.size() && Uint32(numUndockStages) < pIt->second.m_leaving.size()) { Error( "(%s): numUndockStages (%d) vs number of leaving stages (" SIZET_FMT ")\n" "Must have at least the same number of entries as the number of leaving stages.", modelName.c_str(), (numDockingStages-1), pIt->second.m_docking.size()); } else if(0!=pIt->second.m_leaving.size() && Uint32(numUndockStages) != pIt->second.m_leaving.size()) { Warning( "(%s): numUndockStages (%d) vs number of leaving stages (" SIZET_FMT ")\n", modelName.c_str(), numUndockStages, pIt->second.m_leaving.size()); } } } }
void SpaceStationType::OnSetupComplete() { // Since the model contains (almost) all of the docking information we have to extract that // and then generate any additional locators and information the station will need from it. // First we gather the MatrixTransforms that contain the location and orientation of the docking // locators/waypoints. We store some information within the name of these which needs parsing too. // Next we build the additional information required for docking ships with SPACE stations // on autopilot - this is the only option for docking with SPACE stations currently. // This mostly means offsetting from one locator to create the next in the sequence. // ground stations have a "special-f*****g-case" 0 stage launch process shipLaunchStage = ((SURFACE==dockMethod) ? 0 : 3); // gather the tags SceneGraph::Model::TVecMT entrance_mts; SceneGraph::Model::TVecMT locator_mts; SceneGraph::Model::TVecMT exit_mts; model->FindTagsByStartOfName("entrance_", entrance_mts); model->FindTagsByStartOfName("loc_", locator_mts); model->FindTagsByStartOfName("exit_", exit_mts); Output("%s has:\n %lu entrances,\n %lu pads,\n %lu exits\n", modelName.c_str(), entrance_mts.size(), locator_mts.size(), exit_mts.size()); // Add the partially initialised ports for (auto apprIter : entrance_mts) { int portId; PiVerify(1 == sscanf(apprIter->GetName().c_str(), "entrance_port%d", &portId)); PiVerify(portId>0); SPort new_port; new_port.portId = portId; new_port.name = apprIter->GetName(); if(SURFACE==dockMethod) { const vector3f offDir = apprIter->GetTransform().Up().Normalized(); new_port.m_approach[1] = apprIter->GetTransform(); new_port.m_approach[1].SetTranslate( apprIter->GetTransform().GetTranslate() + (offDir * 500.0f) ); } else { const vector3f offDir = -apprIter->GetTransform().Back().Normalized(); new_port.m_approach[1] = apprIter->GetTransform(); new_port.m_approach[1].SetTranslate( apprIter->GetTransform().GetTranslate() + (offDir * 1500.0f) ); } new_port.m_approach[2] = apprIter->GetTransform(); m_ports.push_back( new_port ); } int bay=0; for (auto locIter : locator_mts) { int bayStr, portId; int minSize, maxSize; char padname[8]; const matrix4x4f &locTransform = locIter->GetTransform(); ++bay; // eg:loc_A001_p01_s0_500_b01 PiVerify(5 == sscanf(locIter->GetName().c_str(), "loc_%4s_p%d_s%d_%d_b%d", &padname[0], &portId, &minSize, &maxSize, &bayStr)); PiVerify(bay>0 && portId>0); // find the port and setup the rest of it's information bool bFoundPort = false; matrix4x4f approach1; matrix4x4f approach2; for(auto &rPort : m_ports) { if(rPort.portId == portId) { rPort.minShipSize = std::min(minSize,rPort.minShipSize); rPort.maxShipSize = std::max(maxSize,rPort.maxShipSize); rPort.bayIDs.push_back( std::make_pair(bay-1, padname) ); bFoundPort = true; approach1 = rPort.m_approach[1]; approach2 = rPort.m_approach[2]; break; } } assert(bFoundPort); // now build the docking/leaving waypoints if( SURFACE == dockMethod ) { // ground stations don't have leaving waypoints. m_portPaths[bay].m_docking[2] = locTransform; // final (docked) numDockingStages = 2; numUndockStages = 1; } else { struct TPointLine { // for reference: http://paulbourke.net/geometry/pointlineplane/ static bool ClosestPointOnLine( const vector3f &Point, const vector3f &LineStart, const vector3f &LineEnd, vector3f &Intersection ) { const float LineMag = ( LineStart - LineEnd ).Length(); const float U = ( ( ( Point.x - LineStart.x ) * ( LineEnd.x - LineStart.x ) ) + ( ( Point.y - LineStart.y ) * ( LineEnd.y - LineStart.y ) ) + ( ( Point.z - LineStart.z ) * ( LineEnd.z - LineStart.z ) ) ) / ( LineMag * LineMag ); if( U < 0.0f || U > 1.0f ) return false; // closest point does not fall within the line segment Intersection.x = LineStart.x + U * ( LineEnd.x - LineStart.x ); Intersection.y = LineStart.y + U * ( LineEnd.y - LineStart.y ); Intersection.z = LineStart.z + U * ( LineEnd.z - LineStart.z ); return true; } }; // create the docking locators // start m_portPaths[bay].m_docking[2] = approach2; m_portPaths[bay].m_docking[2].SetRotationOnly( locTransform.GetOrient() ); // above the pad vector3f intersectionPos(0.0f); const vector3f approach1Pos = approach1.GetTranslate(); const vector3f approach2Pos = approach2.GetTranslate(); { const vector3f p0 = locTransform.GetTranslate(); // plane position const vector3f l = (approach2Pos - approach1Pos).Normalized(); // ray direction const vector3f l0 = approach1Pos + (l*10000.0f); if(!TPointLine::ClosestPointOnLine(p0, approach1Pos, l0, intersectionPos)) { Output("No point found on line segment"); } } m_portPaths[bay].m_docking[3] = locTransform; m_portPaths[bay].m_docking[3].SetTranslate( intersectionPos ); // final (docked) m_portPaths[bay].m_docking[4] = locTransform; numDockingStages = 4; // leaving locators ... matrix4x4f orient = locTransform.GetOrient(), EndOrient; if( exit_mts.empty() ) { // leaving locators need to face in the opposite direction const matrix4x4f rot = matrix3x3f::Rotate(DEG2RAD(180.0f), orient.Back()); orient = orient * rot; orient.SetTranslate( locTransform.GetTranslate() ); EndOrient = approach2; EndOrient.SetRotationOnly(orient); } else { // leaving locators, use whatever orientation they have orient.SetTranslate( locTransform.GetTranslate() ); int exitport = 0; for( auto &exitIt : exit_mts ) { PiVerify(1 == sscanf( exitIt->GetName().c_str(), "exit_port%d", &exitport )); if( exitport == portId ) { EndOrient = exitIt->GetTransform(); break; } } if( exitport == 0 ) { EndOrient = approach2; } } // create the leaving locators m_portPaths[bay].m_leaving[1] = locTransform; // start - maintain the same orientation and position as when docked. m_portPaths[bay].m_leaving[2] = orient; // above the pad - reorient... m_portPaths[bay].m_leaving[2].SetTranslate( intersectionPos ); // ...and translate to new position m_portPaths[bay].m_leaving[3] = EndOrient; // end (on manual after here) numUndockStages = 3; } } numDockingPorts = m_portPaths.size(); // sanity assert(!m_portPaths.empty()); assert(numDockingStages > 0); assert(numUndockStages > 0); // insanity for (PortPathMap::const_iterator pIt = m_portPaths.begin(), pItEnd = m_portPaths.end(); pIt!=pItEnd; ++pIt) { if (Uint32(numDockingStages-1) < pIt->second.m_docking.size()) { Error( "(%s): numDockingStages (%d) vs number of docking stages (" SIZET_FMT ")\n" "Must have at least the same number of entries as the number of docking stages " "PLUS the docking timeout at the start of the array.", modelName.c_str(), (numDockingStages-1), pIt->second.m_docking.size()); } else if (Uint32(numDockingStages-1) != pIt->second.m_docking.size()) { Warning( "(%s): numDockingStages (%d) vs number of docking stages (" SIZET_FMT ")\n", modelName.c_str(), (numDockingStages-1), pIt->second.m_docking.size()); } if (0!=pIt->second.m_leaving.size() && Uint32(numUndockStages) < pIt->second.m_leaving.size()) { Error( "(%s): numUndockStages (%d) vs number of leaving stages (" SIZET_FMT ")\n" "Must have at least the same number of entries as the number of leaving stages.", modelName.c_str(), (numDockingStages-1), pIt->second.m_docking.size()); } else if(0!=pIt->second.m_leaving.size() && Uint32(numUndockStages) != pIt->second.m_leaving.size()) { Warning( "(%s): numUndockStages (%d) vs number of leaving stages (" SIZET_FMT ")\n", modelName.c_str(), numUndockStages, pIt->second.m_leaving.size()); } } }