Example #1
0
void SpaceStation::StaticUpdate(const float timeStep)
{
	bool update = false;

	// if there's no BB and there are ships here, make one
	if (!m_bbCreated && GetFreeDockingPort() != 0) {
		CreateBB();
		update = true;
	}

	// if there is and it hasn't had an update for a while, update it
	else if (Pi::game->GetTime() > m_lastUpdatedShipyard) {
		LuaEvent::Queue("onUpdateBB", this);
		update = true;
	}

	if (update) {
		UpdateShipyard();
		// update again in an hour or two
		m_lastUpdatedShipyard = Pi::game->GetTime() + 3600.0 + 3600.0*Pi::rng.Double();
	}

	DoLawAndOrder(timeStep);
	DockingUpdate(timeStep);
	m_navLights->Update(timeStep);
}
Example #2
0
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->SetFlightState(Ship::DOCKING);
				} else {
					s->SetDockedWith(this, port);
					CreateBB();
					Pi::luaOnShipDocked.Queue(s, this);
				}
			}
		}
		return false;
	} else {
		return true;
	}
}
Example #3
0
void SpaceStation::DoDockingAnimation(const double timeStep)
{
	matrix4x4d rot, wantRot;
	vector3d p1, p2, zaxis;
	for (int i=0; i<MAX_DOCKING_PORTS; i++) {
		shipDocking_t &dt = m_shipDocking[i];
		if (!dt.ship) continue;
		if (!dt.stage) continue;
		// docked stage is m_type->numDockingPorts + 1
		if (dt.stage > m_type->numDockingStages) continue;
		GetRotMatrix(rot);

		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_openAnimState[i] += 0.3*timeStep;
			m_dockAnimState[i] -= 0.3*timeStep;

			if (dt.stagePos >= 1.0) {
				if (dt.ship == static_cast<Ship*>(Pi::player)) Pi::onDockingClearanceExpired.emit(this);
				dt.ship = 0;
				dt.stage = 0;
			}
			continue;
		}
	
		if (dt.stagePos > 1.0) {
			dt.stagePos = 0;
			if (dt.stage >= 0) dt.stage++;
			else dt.stage--;
			dt.fromPos = rot.InverseOf() * (dt.ship->GetPosition() - GetPosition());
			matrix4x4d temp;
			dt.ship->GetRotMatrix(temp);
			dt.fromRot = Quaterniond::FromMatrix4x4(temp);
		}

		SpaceStationType::positionOrient_t shipOrient;
		bool onRails = m_type->GetDockAnimPositionOrient(i, dt.stage, dt.stagePos, dt.fromPos, shipOrient, dt.ship);
		
		if (onRails) {
			dt.ship->SetPosition(GetPosition() + rot*shipOrient.pos);
			wantRot = matrix4x4d::MakeRotMatrix(
					shipOrient.xaxis, shipOrient.yaxis,
					shipOrient.xaxis.Cross(shipOrient.yaxis)) * rot;
			// use quaternion spherical linear interpolation to do
			// rotation smoothly
			Quaterniond wantQuat = Quaterniond::FromMatrix4x4(wantRot);
			Quaterniond q = Quaterniond::Nlerp(dt.fromRot, wantQuat, dt.stagePos);
			wantRot = q.ToMatrix4x4<double>();
		//	wantRot.Renormalize();
			dt.ship->SetRotMatrix(wantRot);
		} else {
			if (dt.stage >= 0) {
				// set docked
				dt.ship->SetDockedWith(this, i);
				CreateBB();
				Pi::luaOnShipDocked.Queue(dt.ship, this);
			} else {
				if (!dt.ship->IsEnabled()) {
					// launch ship
					dt.ship->Enable();
					dt.ship->SetFlightState(Ship::FLYING);
					dt.ship->SetAngVelocity(GetFrame()->GetAngVelocity());
					dt.ship->SetForce(vector3d(0,0,0));
					dt.ship->SetTorque(vector3d(0,0,0));
					if (m_type->dockMethod == SpaceStationType::SURFACE) {
						dt.ship->SetThrusterState(1, 1.0);		// up
					} else {
						dt.ship->SetVelocity(GetFrame()->GetStasisVelocityAtPosition(dt.ship->GetPosition()));
						dt.ship->SetThrusterState(2, -1.0);		// forward
					}
					Pi::luaOnShipUndocked.Queue(dt.ship, this);
				}
			}
		}
		if ((dt.stage < 0) && ((-dt.stage) > m_type->numUndockStages)) {
		       dt.stage = 0;
		       dt.ship = 0;
		}
	}
	for (int i=0; i<MAX_DOCKING_PORTS; i++) {
		m_openAnimState[i] = Clamp(m_openAnimState[i], 0.0, 1.0);
		m_dockAnimState[i] = Clamp(m_dockAnimState[i], 0.0, 1.0);
	}
}