/* Method: GetShip * * Return the <Ship> that created this cloud, or nil. * * Returns: * * the <Ship> that created this cloud, or nil. * */ static int l_hyperspace_cloud_get_ship(lua_State *l) { HyperspaceCloud *cloud = LuaObject<HyperspaceCloud>::CheckFromLua(1); Ship *ship = cloud->GetShip(); if(ship == nullptr) lua_pushnil(l); else LuaPush(l, ship); return 1; }
void Game::SwitchToNormalSpace() { // remove the player from hyperspace m_space->RemoveBody(m_player.Get()); // create a new space for the system const SystemPath &dest = m_player->GetHyperspaceDest(); m_space.Reset(new Space(this, dest)); // put the player in it m_player->SetFrame(m_space->GetRootFrame()); m_space->AddBody(m_player.Get()); // place it m_player->SetPosition(m_space->GetHyperspaceExitPoint(m_hyperspaceSource)); m_player->SetVelocity(vector3d(0,0,-100.0)); m_player->SetRotMatrix(matrix4x4d::Identity()); // place the exit cloud HyperspaceCloud *cloud = new HyperspaceCloud(0, Pi::game->GetTime(), true); cloud->SetFrame(m_space->GetRootFrame()); cloud->SetPosition(m_player->GetPosition()); m_space->AddBody(cloud); for (std::list<HyperspaceCloud*>::iterator i = m_hyperspaceClouds.begin(); i != m_hyperspaceClouds.end(); ++i) { cloud = *i; cloud->SetFrame(m_space->GetRootFrame()); cloud->SetPosition(m_space->GetHyperspaceExitPoint(m_hyperspaceSource)); m_space->AddBody(cloud); if (cloud->GetDueDate() < Pi::game->GetTime()) { // they emerged from hyperspace some time ago Ship *ship = cloud->EvictShip(); ship->SetFrame(m_space->GetRootFrame()); ship->SetVelocity(vector3d(0,0,-100.0)); ship->SetRotMatrix(matrix4x4d::Identity()); ship->Enable(); ship->SetFlightState(Ship::FLYING); const SystemPath &sdest = ship->GetHyperspaceDest(); if (sdest.IsSystemPath()) { // travelling to the system as a whole, so just dump them on // the cloud - we can't do any better in this case ship->SetPosition(cloud->GetPosition()); } else { // on their way to a body. they're already in-system so we // want to simulate some travel to their destination. we // naively assume full accel for half the distance, flip and // full brake for the rest. Body *target_body = m_space->FindBodyForPath(&sdest); double dist_to_target = cloud->GetPositionRelTo(target_body).Length(); double half_dist_to_target = dist_to_target / 2.0; double accel = -(ship->GetShipType().linThrust[ShipType::THRUSTER_FORWARD] / ship->GetMass()); double travel_time = Pi::game->GetTime() - cloud->GetDueDate(); // I can't help but feel some actual math would do better here double speed = 0; double dist = 0; while (travel_time > 0 && dist <= half_dist_to_target) { speed += accel; dist += speed; travel_time--; } while (travel_time > 0 && dist < dist_to_target) { speed -= accel; dist += speed; travel_time--; } if (travel_time <= 0) { vector3d pos = target_body->GetPositionRelTo(m_space->GetRootFrame()) + cloud->GetPositionRelTo(target_body).Normalized() * (dist_to_target - dist); ship->SetPosition(pos); } else { // ship made it with time to spare. just put it somewhere // near the body. the script should be issuing a dock or // flyto command in onEnterSystem so it should sort it // itself out long before the player can get near SystemBody *sbody = m_space->GetStarSystem()->GetBodyByPath(&sdest); if (sbody->type == SystemBody::TYPE_STARPORT_ORBITAL) { ship->SetFrame(target_body->GetFrame()); ship->SetPosition(MathUtil::RandomPointOnSphere(1000.0)*1000.0); // somewhere 1000km out } else { if (sbody->type == SystemBody::TYPE_STARPORT_SURFACE) { sbody = sbody->parent; SystemPath path = m_space->GetStarSystem()->GetPathOf(sbody); target_body = m_space->FindBodyForPath(&path); } double sdist = sbody->GetRadius()*2.0; ship->SetFrame(target_body->GetFrame()); ship->SetPosition(MathUtil::RandomPointOnSphere(sdist)); } } } m_space->AddBody(ship); LuaEvent::Queue("onEnterSystem", ship); } } m_hyperspaceClouds.clear(); m_state = STATE_NORMAL; }
void Game::SwitchToHyperspace() { // remember where we came from so we can properly place the player on exit m_hyperspaceSource = m_space->GetStarSystem()->GetPath(); const SystemPath &dest = m_player->GetHyperspaceDest(); // find all the departure clouds, convert them to arrival clouds and store // them for the next system m_hyperspaceClouds.clear(); for (Space::BodyIterator i = m_space->BodiesBegin(); i != m_space->BodiesEnd(); ++i) { if (!(*i)->IsType(Object::HYPERSPACECLOUD)) continue; // only want departure clouds with ships in them HyperspaceCloud *cloud = static_cast<HyperspaceCloud*>(*i); if (cloud->IsArrival() || cloud->GetShip() == 0) continue; // make sure they're going to the same place as us if (!dest.IsSameSystem(cloud->GetShip()->GetHyperspaceDest())) continue; // remove it from space m_space->RemoveBody(cloud); // player and the clouds are coming to the next system, but we don't // want the player to have any memory of what they were (we're just // reusing them for convenience). tell the player it was deleted so it // can clean up m_player->NotifyRemoved(cloud); // turn the cloud arround cloud->GetShip()->SetHyperspaceDest(m_hyperspaceSource); cloud->SetIsArrival(true); // and remember it m_hyperspaceClouds.push_back(cloud); } printf(SIZET_FMT " clouds brought over\n", m_hyperspaceClouds.size()); // remove the player from space m_space->RemoveBody(m_player.Get()); // create hyperspace :) m_space.Reset(new Space(this)); // put the player in it m_player->SetFrame(m_space->GetRootFrame()); m_space->AddBody(m_player.Get()); // put player at the origin. kind of unnecessary since it won't be moving // but at least it gives some consistency m_player->SetPosition(vector3d(0,0,0)); m_player->SetVelocity(vector3d(0,0,0)); m_player->SetRotMatrix(matrix4x4d::Identity()); // animation and end time counters m_hyperspaceProgress = 0; m_hyperspaceDuration = m_player->GetHyperspaceDuration(); m_hyperspaceEndTime = Pi::game->GetTime() + m_hyperspaceDuration; m_state = STATE_HYPERSPACE; m_wantHyperspace = false; printf("Started hyperspacing...\n"); }
/* Method: GetDueDate * * Return the date when a ship has entered / will exit this cloud. * * Returns: * * the date when a ship has entered / will exit this cloud * */ static int l_hyperspace_cloud_get_due_date(lua_State *l) { HyperspaceCloud *cloud = LuaObject<HyperspaceCloud>::CheckFromLua(1); LuaPush(l, cloud->GetDueDate()); return 1; }
/* Method: IsArrival * * Return true if this is an arrival cloud. * * Returns: * * true if this is an arrival cloud. * */ static int l_hyperspace_cloud_is_arrival(lua_State *l) { HyperspaceCloud *cloud = LuaObject<HyperspaceCloud>::CheckFromLua(1); LuaPush(l, cloud->IsArrival()); return 1; }