static int l_sbody_attr_children(lua_State *l) { SystemBody * sbody = LuaObject<SystemBody>::CheckFromLua(1); LuaTable children(l); int i = 1; for (auto child : sbody->GetChildren()) { LuaPush(l, i++); LuaObject<SystemBody>::PushToLua(child); lua_settable(l, -3); } return 1; }
/* * Attribute: parent * * The parent of the body, as a <SystemBody>. A body orbits its parent. * * Availability: * * alpha 14 * * Status: * * stable */ static int l_sbody_attr_parent(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); // sbody->parent is 0 as it was cleared by the acquirer. we need to go // back to the starsystem proper to get what we need. RefCountedPtr<StarSystem> s = Pi::game->GetGalaxy()->GetStarSystem(sbody->GetPath()); SystemBody *live_sbody = s->GetBodyByPath(sbody->GetPath()); if (!live_sbody->GetParent()) return 0; LuaObject<SystemBody>::PushToLua(live_sbody->GetParent()); return 1; }
static int l_sbody_attr_body(lua_State *l) { SystemBody * sbody = LuaObject<SystemBody>::CheckFromLua(1); if(Pi::game) { Space *space = Pi::game->GetSpace(); if(space) { const SystemPath &path = sbody->GetPath(); Body *body = space->FindBodyForPath(&path); if(body) { LuaObject<Body>::PushToLua(body); } else { lua_pushnil(l); } } } else { lua_pushnil(l); } return 1; }
vector3d Space::GetHyperspaceExitPoint(const SystemPath &source, const SystemPath &dest) const { assert(m_starSystem); assert(source.IsSystemPath()); assert(dest.IsSameSystem(m_starSystem->GetPath())); RefCountedPtr<const Sector> source_sec = m_sectorCache->GetCached(source); RefCountedPtr<const Sector> dest_sec = m_sectorCache->GetCached(dest); Sector::System source_sys = source_sec->m_systems[source.systemIndex]; Sector::System dest_sys = dest_sec->m_systems[dest.systemIndex]; const vector3d sourcePos = vector3d(source_sys.GetPosition()) + vector3d(source.sectorX, source.sectorY, source.sectorZ); const vector3d destPos = vector3d(dest_sys.GetPosition()) + vector3d(dest.sectorX, dest.sectorY, dest.sectorZ); Body *primary = 0; if (dest.IsBodyPath()) { assert(dest.bodyIndex < m_starSystem->GetNumBodies()); primary = FindBodyForPath(&dest); while (primary && primary->GetSystemBody()->GetSuperType() != SystemBody::SUPERTYPE_STAR) { SystemBody* parent = primary->GetSystemBody()->GetParent(); primary = parent ? FindBodyForPath(&parent->GetPath()) : 0; } } if (!primary) { // find the first non-gravpoint. should be the primary star for (Body* b : GetBodies()) if (b->GetSystemBody()->GetType() != SystemBody::TYPE_GRAVPOINT) { primary = b; break; } } assert(primary); // point along the line between source and dest, a reasonable distance // away based on the radius (don't want to end up inside black holes, and // then mix it up so that ships don't end up on top of each other vector3d pos = (sourcePos - destPos).Normalized() * (primary->GetSystemBody()->GetRadius()/AU+1.0)*11.0*AU*Pi::rng.Double(0.95,1.2) + MathUtil::RandomPointOnSphere(5.0,20.0)*1000.0; assert(pos.Length() > primary->GetSystemBody()->GetRadius()); return pos + primary->GetPositionRelTo(GetRootFrame()); }
static void position_system_lights(Frame *camFrame, Frame *frame, std::vector<Camera::LightSource> &lights) { if (lights.size() > 3) return; SystemBody *body = frame->GetSystemBody(); // IsRotFrame check prevents double counting if (body && !frame->IsRotFrame() && (body->GetSuperType() == SystemBody::SUPERTYPE_STAR)) { vector3d lpos = frame->GetPositionRelTo(camFrame); const double dist = lpos.Length() / AU; lpos *= 1.0/dist; // normalize const float *col = StarSystem::starRealColors[body->type]; const Color lightCol(col[0], col[1], col[2], 0.f); vector3f lightpos(lpos.x, lpos.y, lpos.z); lights.push_back(Camera::LightSource(frame->GetBody(), Graphics::Light(Graphics::Light::LIGHT_DIRECTIONAL, lightpos, lightCol, lightCol))); } for (Frame::ChildIterator it = frame->BeginChildren(); it != frame->EndChildren(); ++it) { position_system_lights(camFrame, *it, lights); } }
static int l_set_hyperspace_target(lua_State *l) { LuaObject<Player>::CheckFromLua(1); if (Pi::game->IsNormalSpace()) { const SystemPath path = *LuaObject<SystemPath>::CheckFromLua(2); if (!path.IsSystemPath()) { if (!path.IsBodyPath()) { return luaL_error(l, "Player:SetHyperspaceTarget() -- second parameter is not a system path or the path of a star"); } RefCountedPtr<StarSystem> sys = Pi::game->GetGalaxy()->GetStarSystem(path); // Lua should never be able to get an invalid SystemPath // (note: this may change if it becomes possible to remove systems during the game) assert(path.bodyIndex < sys->GetNumBodies()); SystemBody *sbody = sys->GetBodyByPath(path); if (!sbody->GetSuperType() == SystemBody::SUPERTYPE_STAR) return luaL_error(l, "Player:SetHyperspaceTarget() -- second parameter is not a system path or the path of a star"); } Pi::game->GetSectorView()->SetHyperspaceTarget(path); return 0; } else return luaL_error(l, "Player:SetHyperspaceTarget() cannot be used while in hyperspace"); }
/* * Function: SpawnShipLandedNear * * Create a ship and place it on the surface near the given <Body>. * * > ship = Space.SpawnShipLandedNear(type, body, min, max) * * Parameters: * * type - the name of the ship * * body - the <Body> near which the ship should be spawned. It must be on the ground or close to it, * i.e. it must be in the rotating frame of the planetary body. * * min - minimum distance from the surface point below the body to place the ship, in Km * * max - maximum distance to place the ship * * Return: * * ship - a <Ship> object for the new ship * * Example: * * > -- spawn a ship 10km from the player * > local ship = Ship.SpawnShipLandedNear("viper_police", Game.player, 10, 10) * * Availability: * * July 2013 * * Status: * * experimental */ static int l_space_spawn_ship_landed_near(lua_State *l) { if (!Pi::game) luaL_error(l, "Game is not started"); LUA_DEBUG_START(l); const char *type = luaL_checkstring(l, 1); if (! ShipType::Get(type)) luaL_error(l, "Unknown ship type '%s'", type); Body *nearbody = LuaObject<Body>::CheckFromLua(2); const float min_dist = luaL_checknumber(l, 3); const float max_dist = luaL_checknumber(l, 4); if (min_dist > max_dist) luaL_error(l, "min_dist must not be larger than max_dist"); Ship *ship = new Ship(type); assert(ship); // XXX protect against spawning inside the body Frame * newframe = nearbody->GetFrame()->GetRotFrame(); if (!newframe->IsRotFrame()) luaL_error(l, "Body must be in rotating frame"); SystemBody *sbody = newframe->GetSystemBody(); if (sbody->GetSuperType() != SystemBody::SUPERTYPE_ROCKY_PLANET) luaL_error(l, "Body is not on a rocky planet"); if (max_dist > sbody->GetRadius()) luaL_error(l, "max_dist too large for planet radius"); // We assume that max_dist is much smaller than the planet radius, i.e. that our area is reasonably flat // So, we const vector3d up = nearbody->GetPosition().Normalized(); vector3d x; vector3d y; // Calculate a orthonormal basis for a horizontal plane. For numerical reasons we do that determining the smallest // coordinate and take the cross product with (1,0,0), (0,1,0) or (0,0,1) respectively to calculate the first vector. // The second vector is just the cross product of the up-vector and out first vector. if (up.x <= up.y && up.x <= up.z) { x = vector3d(0.0, up.z, -up.y).Normalized(); y = vector3d(-up.y*up.y - up.z*up.z, up.x*up.y, up.x*up.z).Normalized(); } else if (up.y <= up.x && up.y <= up.z) { x = vector3d(-up.z, 0.0, up.x).Normalized(); y = vector3d(up.x*up.y, -up.x*up.x - up.z*up.z, up.y*up.z).Normalized(); } else { x = vector3d(up.y, -up.x, 0.0).Normalized(); y = vector3d(up.x*up.z, up.y*up.z, -up.x*up.x - up.y*up.y).Normalized(); } Planet *planet = static_cast<Planet*>(newframe->GetBody()); const double radius = planet->GetSystemBody()->GetRadius(); const vector3d planar = MathUtil::RandomPointInCircle(min_dist * 1000.0, max_dist * 1000.0); vector3d pos = (radius * up + x * planar.x + y * planar.y).Normalized(); float latitude = atan2(pos.y, sqrt(pos.x*pos.x + pos.z * pos.z)); float longitude = atan2(pos.x, pos.z); Pi::game->GetSpace()->AddBody(ship); ship->SetLandedOn(planet, latitude, longitude); LuaObject<Ship>::PushToLua(ship); LUA_DEBUG_END(l, 1); return 1; }
/* * Attribute: apoapsis * * The apoapsis of the body's orbit, in metres (m). * * Availability: * * alpha 16 * * Status: * * experimental */ static int l_sbody_attr_apoapsis(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetOrbMax()*AU); return 1; }
/* * Attribute: superType * * The supertype of the body, as a <Constants.BodySuperType> constant * * Availability: * * alpha 10 * * Status: * * stable */ static int l_sbody_attr_super_type(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushstring(l, EnumStrings::GetString("BodySuperType", sbody->GetSuperType())); return 1; }
static int l_sbody_attr_astro_description(lua_State *l) { SystemBody * sbody = LuaObject<SystemBody>::CheckFromLua(1); LuaPush(l, sbody->GetAstroDescription()); return 1; }
/* * Attribute: orbitPeriod * * The orbit of the body, around its parent, in days, as a float * * Availability: * * 201708 * * Status: * * experimental */ static int l_sbody_attr_orbital_period(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetOrbit().Period() / float(60*60*24)); return 1; }
/* * Attribute: eccentricity * * The orbital eccentricity of the body * * Availability: * * alpha 16 * * Status: * * experimental */ static int l_sbody_attr_eccentricty(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetEccentricity()); return 1; }
static int l_sbody_attr_path(lua_State *l) { SystemBody * sbody = LuaObject<SystemBody>::CheckFromLua(1); LuaObject<SystemPath>::PushToLua(sbody->GetPath()); return 1; }
/* * Attribute: gravity * * The gravity on the surface of the body (m/s). * * Availability: * * alpha 21 * * Status: * * experimental */ static int l_sbody_attr_gravity(lua_State *l) { SystemBody *sbody = LuaSystemBody::CheckFromLua(1); lua_pushnumber(l, sbody->CalcSurfaceGravity()); return 1; }
static int l_sbody_attr_is_scoopable(lua_State *l) { SystemBody * sbody = LuaSystemBody::CheckFromLua(1); lua_pushboolean(l, sbody->IsScoopable()); return 1; }
/* * Attribute: atmosOxidizing * * Returns the compositional value of any atmospheric gasses in the bodys atmosphere (if any) * 0.0 = reducing (H2, NH3, etc), 1.0 = oxidising (CO2, O2, etc) * * Availability: * * January 2018 * * Status: * * experimental */ static int l_sbody_attr_atmosOxidizing(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetAtmosOxidizing()); return 1; }
/* * Attribute: rotationPeriod * * The rotation period of the body, in days * * Availability: * * alpha 16 * * Status: * * experimental */ static int l_sbody_attr_rotation_period(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetRotationPeriodInDays()); return 1; }
/* * Attribute: averageTemp * * The average surface temperature of the body, in degrees kelvin * * Availability: * * alpha 16 * * Status: * * experimental */ static int l_sbody_attr_average_temp(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushinteger(l, sbody->GetAverageTemp()); return 1; }
/* * Attribute: axialTilt * * The axial tilt of the body, in radians * * Availability: * * alpha 16 * * Status: * * experimental */ static int l_sbody_attr_axial_tilt(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetAxialTilt()); return 1; }
/* * Attribute: index * * The body index of the body in its system * * Availability: * * alpha 10 * * Status: * * stable */ static int l_sbody_attr_index(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushinteger(l, sbody->GetPath().bodyIndex); 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; }
/* * Attribute: seed * * The random seed used to generate this <SystemBody>. This is guaranteed to * be the same for this body across runs of the same build of the game, and * should be used to seed a <Rand> object when you want to ensure the same * random numbers come out each time. * * This value is the same is the one available via <Body.seed> once you enter * this system. * * Availability: * * alpha 10 * * Status: * * stable */ static int l_sbody_attr_seed(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushinteger(l, sbody->GetSeed()); return 1; }
/* * Attribute: volatileIces * * Returns the measure of volatile ices present on the body * 0.0 = none, 1.0 = total ice cover (earth = 3%) * * Availability: * * January 2018 * * Status: * * experimental */ static int l_sbody_attr_volatileIces(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetVolatileIces()); return 1; }
/* * Attribute: semiMajorAxis * * The semi-major axis of the orbit, in metres (m). * * Availability: * * alpha 16 * * Status: * * experimental */ static int l_sbody_attr_semi_major_axis(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetSemiMajorAxis()*AU); return 1; }
/* * Attribute: mass * * The mass of the body, in kilograms (kg). * * Availability: * * alpha 16 * * Status: * * experimental */ static int l_sbody_attr_mass(lua_State *l) { SystemBody *sbody = LuaSystemBody::CheckFromLua(1); lua_pushnumber(l, sbody->GetMass()); return 1; }
/* * Attribute: life * * Returns the measure of life present on the body * 0.0 = dead, 1.0 = teeming (~= pandora) * * Availability: * * January 2018 * * Status: * * experimental */ static int l_sbody_attr_life(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushnumber(l, sbody->GetLife()); return 1; }
static int l_sbody_attr_has_atmosphere(lua_State *l) { SystemBody * sbody = LuaSystemBody::CheckFromLua(1); lua_pushboolean(l, sbody->HasAtmosphere()); return 1; }
/* * Attribute: name * * The name of the body * * Availability: * * alpha 10 * * Status: * * stable */ static int l_sbody_attr_name(lua_State *l) { SystemBody *sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushstring(l, sbody->GetName().c_str()); return 1; }
/* * Attribute: superType * * The supertype of the body, as a <Constants.BodySuperType> constant * * Availability: * * alpha 10 * * Status: * * stable */ static int l_sbody_attr_super_type(lua_State *l) { SystemBody *sbody = LuaSystemBody::CheckFromLua(1); lua_pushstring(l, LuaConstants::GetConstantString(l, "BodySuperType", sbody->GetSuperType())); return 1; }
static int l_sbody_attr_has_rings(lua_State *l) { SystemBody * sbody = LuaObject<SystemBody>::CheckFromLua(1); lua_pushboolean(l, sbody->HasRings()); return 1; }