/* * Method: GetStarSystem * * Get a <StarSystem> object for the system that this path points to * * > system = path:GetStarSystem() * * Return: * * system - the <StarSystem> * * Availability: * * alpha 10 * * Status: * * stable */ static int l_sbodypath_get_star_system(lua_State *l) { SystemPath *path = LuaObject<SystemPath>::CheckFromLua(1); RefCountedPtr<StarSystem> s = StarSystem::GetCached(path); // LuaObject<StarSystem> shares ownership of the StarSystem, // because LuaAcquirer<LuaObject<StarSystem>> uses IncRefCount and DecRefCount LuaObject<StarSystem>::PushToLua(s.Get()); return 1; }
/* * Method: GetStarSystem * * Get a <StarSystem> object for the system that this path points to * * > system = path:GetStarSystem() * * Return: * * system - the <StarSystem> * * Availability: * * alpha 10 * * Status: * * stable */ static int l_sbodypath_get_star_system(lua_State *l) { SystemPath *path = LuaObject<SystemPath>::CheckFromLua(1); if (path->IsSectorPath()) return luaL_error(l, "SystemPath:GetStarSystem() self argument does not refer to a system"); RefCountedPtr<StarSystem> s = Pi::game->GetGalaxy()->GetStarSystem(path); // LuaObject<StarSystem> shares ownership of the StarSystem, // because LuaAcquirer<LuaObject<StarSystem>> uses IncRefCount and DecRefCount LuaObject<StarSystem>::PushToLua(s.Get()); return 1; }
RefCountedPtr<T> GalaxyObjectCache<T,CompareT>::GetCached(const SystemPath& path) { PROFILE_SCOPED() RefCountedPtr<T> s = this->GetIfCached(path); if (!s) { ++m_cacheMisses; s = m_galaxyGenerator->Generate<T,GalaxyObjectCache<T,CompareT>>(path, this); m_attic.insert( std::make_pair(path, s.Get())); } else { ++m_cacheHits; } return s; }
bool SectorCustomSystemsGenerator::Apply(Random& rng, RefCountedPtr<Galaxy> galaxy, RefCountedPtr<Sector> sector, GalaxyGenerator::SectorConfig* config) { PROFILE_SCOPED() const int sx = sector->sx; const int sy = sector->sy; const int sz = sector->sz; if ((sx >= -m_customOnlyRadius) && (sx <= m_customOnlyRadius-1) && (sy >= -m_customOnlyRadius) && (sy <= m_customOnlyRadius-1) && (sz >= -m_customOnlyRadius) && (sz <= m_customOnlyRadius-1)) config->isCustomOnly = true; const std::vector<const CustomSystem*> &systems = galaxy->GetCustomSystems()->GetCustomSystemsForSector(sx, sy, sz); if (systems.size() == 0) return true; Uint32 sysIdx = 0; for (std::vector<const CustomSystem*>::const_iterator it = systems.begin(); it != systems.end(); ++it, ++sysIdx) { const CustomSystem *cs = *it; Sector::System s(sector.Get(), sx, sy, sz, sysIdx); s.m_pos = Sector::SIZE*cs->pos; s.m_name = cs->name; for (s.m_numStars=0; s.m_numStars<cs->numStars; s.m_numStars++) { if (cs->primaryType[s.m_numStars] == 0) break; s.m_starType[s.m_numStars] = cs->primaryType[s.m_numStars]; } s.m_customSys = cs; s.m_seed = cs->seed; if (cs->want_rand_explored) { /* * 0 - ~500ly from sol: explored * ~500ly - ~700ly (65-90 sectors): gradual * ~700ly+: unexplored */ int dist = isqrt(1 + sx*sx + sy*sy + sz*sz); if (((dist <= 90) && ( dist <= 65 || rng.Int32(dist) <= 40)) || galaxy->GetFactions()->IsHomeSystem(SystemPath(sx, sy, sz, sysIdx))) s.m_explored = StarSystem::eEXPLORED_AT_START; else s.m_explored = StarSystem::eUNEXPLORED; } else { if (cs->explored) s.m_explored = StarSystem::eEXPLORED_AT_START; else s.m_explored = StarSystem::eUNEXPLORED; } sector->m_systems.push_back(s); } return true; }
std::string LuaNameGen::Surname(RefCountedPtr<Random> &rng) { lua_State *l = m_luaManager->GetLuaState(); if (!GetNameGenFunc(l, "Surname")) return DEFAULT_SURNAME; LuaObject<Random>::PushToLua(rng.Get()); pi_lua_protected_call(l, 1, 1); std::string surname = luaL_checkstring(l, -1); lua_pop(l, 1); return surname; }
std::string LuaNameGen::BodyName(SystemBody *body, RefCountedPtr<Random> &rng) { lua_State *l = m_luaManager->GetLuaState(); if (!GetNameGenFunc(l, "BodyName")) return DEFAULT_BODY_NAME; LuaObject<SystemBody>::PushToLua(body); LuaObject<Random>::PushToLua(rng.Get()); pi_lua_protected_call(l, 2, 1); std::string bodyname = luaL_checkstring(l, -1); lua_pop(l, 1); return bodyname; }
std::string LuaNameGen::FullName(bool isFemale, RefCountedPtr<Random> &rng) { lua_State *l = m_luaManager->GetLuaState(); if (!GetNameGenFunc(l, "FullName")) return isFemale ? DEFAULT_FULL_NAME_FEMALE : DEFAULT_FULL_NAME_MALE; lua_pushboolean(l, isFemale); LuaObject<Random>::PushToLua(rng.Get()); pi_lua_protected_call(l, 2, 1); std::string fullname = luaL_checkstring(l, -1); lua_pop(l, 1); return fullname; }
void StaticGeometry::DrawBoundingBox(const Aabb &bb) { const vector3f min(bb.min.x, bb.min.y, bb.min.z); const vector3f max(bb.max.x, bb.max.y, bb.max.z); const vector3f fbl(min.x, min.y, min.z); //front bottom left const vector3f fbr(max.x, min.y, min.z); //front bottom right const vector3f ftl(min.x, max.y, min.z); //front top left const vector3f ftr(max.x, max.y, min.z); //front top right const vector3f rtl(min.x, max.y, max.z); //rear top left const vector3f rtr(max.x, max.y, max.z); //rear top right const vector3f rbl(min.x, min.y, max.z); //rear bottom left const vector3f rbr(max.x, min.y, max.z); //rear bottom right const Color c(Color::WHITE); std::unique_ptr<Graphics::VertexArray> vts(new Graphics::VertexArray(Graphics::ATTRIB_POSITION | Graphics::ATTRIB_DIFFUSE)); //Front face vts->Add(ftr, c); //3 vts->Add(fbr, c); //1 vts->Add(fbl, c); //0 vts->Add(fbl, c); //0 vts->Add(ftl, c); //2 vts->Add(ftr, c); //3 //Rear face vts->Add(rbr, c); //7 vts->Add(rtr, c); //5 vts->Add(rbl, c); //6 vts->Add(rbl, c); //6 vts->Add(rtr, c); //5 vts->Add(rtl, c); //4 //Top face vts->Add(rtl, c); //4 vts->Add(rtr, c); //5 vts->Add(ftr, c); //3 vts->Add(ftr, c); //3 vts->Add(ftl, c); //2 vts->Add(rtl, c); //4 //bottom face vts->Add(fbr, c); //1 vts->Add(rbr, c); //7 vts->Add(rbl, c); //6 vts->Add(rbl, c); //6 vts->Add(fbl, c); //0 vts->Add(fbr, c); //1 //left face vts->Add(fbl, c); //0 vts->Add(rbl, c); //6 vts->Add(rtl, c); //4 vts->Add(rtl, c); //4 vts->Add(ftl, c); //2 vts->Add(fbl, c); //0 //right face vts->Add(rtr, c); //5 vts->Add(rbr, c); //7 vts->Add(fbr, c); //1 vts->Add(fbr, c); //1 vts->Add(ftr, c); //3 vts->Add(rtr, c); //5 Graphics::Renderer *r = GetRenderer(); Graphics::RenderStateDesc rsd; rsd.cullMode = Graphics::CULL_NONE; RefCountedPtr<Graphics::VertexBuffer> vb; //create buffer and upload data Graphics::VertexBufferDesc vbd; vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION; vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3; vbd.attrib[1].semantic = Graphics::ATTRIB_DIFFUSE; vbd.attrib[1].format = Graphics::ATTRIB_FORMAT_UBYTE4; vbd.numVertices = vts->GetNumVerts(); vbd.usage = Graphics::BUFFER_USAGE_STATIC; vb.Reset( m_renderer->CreateVertexBuffer(vbd) ); vb->Populate( *vts ); r->SetWireFrameMode(true); r->DrawBuffer(vb.Get(), r->CreateRenderState(rsd), Graphics::vtxColorMaterial); r->SetWireFrameMode(false); }
bool SectorRandomSystemsGenerator::Apply(Random& rng, RefCountedPtr<Galaxy> galaxy, RefCountedPtr<Sector> sector, GalaxyGenerator::SectorConfig* config) { /* Always place random systems outside the core custom-only region */ if (config->isCustomOnly) return true; const int sx = sector->sx; const int sy = sector->sy; const int sz = sector->sz; const int customCount = static_cast<Uint32>(sector->m_systems.size()); const Sint64 dist = (1 + sx*sx + sy*sy + sz*sz); const Sint64 freq = (1 + sx * sx + sy * sy); const int numSystems = (rng.Int32(4,20) * galaxy->GetSectorDensity(sx, sy, sz)) >> 8; sector->m_systems.reserve(numSystems); for (int i=0; i<numSystems; i++) { Sector::System s(sector.Get(), sx, sy, sz, customCount + i); switch (rng.Int32(15)) { case 0: s.m_numStars = 4; break; case 1: case 2: s.m_numStars = 3; break; case 3: case 4: case 5: case 6: s.m_numStars = 2; break; default: s.m_numStars = 1; break; } s.m_pos.x = rng.Double(Sector::SIZE); s.m_pos.y = rng.Double(Sector::SIZE); s.m_pos.z = rng.Double(Sector::SIZE); /* * 0 - ~500ly from sol: explored * ~500ly - ~700ly (65-90 sectors): gradual * ~700ly+: unexplored */ if (((dist <= Square(90)) && ( dist <= Square(65) || rng.Int32(dist) <= Square(40))) || galaxy->GetFactions()->IsHomeSystem(SystemPath(sx, sy, sz, customCount + i))) s.m_explored = StarSystem::eEXPLORED_AT_START; else s.m_explored = StarSystem::eUNEXPLORED; // Frequencies are low enough that we probably don't need this anymore. if (freq > Square(10)) { const Uint32 weight = rng.Int32(1000000); if (weight < 1) { s.m_starType[0] = SystemBody::TYPE_STAR_IM_BH; // These frequencies are made up } else if (weight < 3) { s.m_starType[0] = SystemBody::TYPE_STAR_S_BH; } else if (weight < 5) { s.m_starType[0] = SystemBody::TYPE_STAR_O_WF; } else if (weight < 8) { s.m_starType[0] = SystemBody::TYPE_STAR_B_WF; } else if (weight < 12) { s.m_starType[0] = SystemBody::TYPE_STAR_M_WF; } else if (weight < 15) { s.m_starType[0] = SystemBody::TYPE_STAR_K_HYPER_GIANT; } else if (weight < 18) { s.m_starType[0] = SystemBody::TYPE_STAR_G_HYPER_GIANT; } else if (weight < 23) { s.m_starType[0] = SystemBody::TYPE_STAR_O_HYPER_GIANT; } else if (weight < 28) { s.m_starType[0] = SystemBody::TYPE_STAR_A_HYPER_GIANT; } else if (weight < 33) { s.m_starType[0] = SystemBody::TYPE_STAR_F_HYPER_GIANT; } else if (weight < 41) { s.m_starType[0] = SystemBody::TYPE_STAR_B_HYPER_GIANT; } else if (weight < 48) { s.m_starType[0] = SystemBody::TYPE_STAR_M_HYPER_GIANT; } else if (weight < 58) { s.m_starType[0] = SystemBody::TYPE_STAR_K_SUPER_GIANT; } else if (weight < 68) { s.m_starType[0] = SystemBody::TYPE_STAR_G_SUPER_GIANT; } else if (weight < 78) { s.m_starType[0] = SystemBody::TYPE_STAR_O_SUPER_GIANT; } else if (weight < 88) { s.m_starType[0] = SystemBody::TYPE_STAR_A_SUPER_GIANT; } else if (weight < 98) { s.m_starType[0] = SystemBody::TYPE_STAR_F_SUPER_GIANT; } else if (weight < 108) { s.m_starType[0] = SystemBody::TYPE_STAR_B_SUPER_GIANT; } else if (weight < 158) { s.m_starType[0] = SystemBody::TYPE_STAR_M_SUPER_GIANT; } else if (weight < 208) { s.m_starType[0] = SystemBody::TYPE_STAR_K_GIANT; } else if (weight < 250) { s.m_starType[0] = SystemBody::TYPE_STAR_G_GIANT; } else if (weight < 300) { s.m_starType[0] = SystemBody::TYPE_STAR_O_GIANT; } else if (weight < 350) { s.m_starType[0] = SystemBody::TYPE_STAR_A_GIANT; } else if (weight < 400) { s.m_starType[0] = SystemBody::TYPE_STAR_F_GIANT; } else if (weight < 500) { s.m_starType[0] = SystemBody::TYPE_STAR_B_GIANT; } else if (weight < 700) { s.m_starType[0] = SystemBody::TYPE_STAR_M_GIANT; } else if (weight < 800) { s.m_starType[0] = SystemBody::TYPE_STAR_O; // should be 1 but that is boring } else if (weight < 2000) { // weight < 1300 / 20500 s.m_starType[0] = SystemBody::TYPE_STAR_B; } else if (weight < 8000) { // weight < 7300 s.m_starType[0] = SystemBody::TYPE_STAR_A; } else if (weight < 37300) { // weight < 37300 s.m_starType[0] = SystemBody::TYPE_STAR_F; } else if (weight < 113300) { // weight < 113300 s.m_starType[0] = SystemBody::TYPE_STAR_G; } else if (weight < 234300) { // weight < 234300 s.m_starType[0] = SystemBody::TYPE_STAR_K; } else if (weight < 250000) { // weight < 250000 s.m_starType[0] = SystemBody::TYPE_WHITE_DWARF; } else if (weight < 900000) { //weight < 900000 s.m_starType[0] = SystemBody::TYPE_STAR_M; } else { s.m_starType[0] = SystemBody::TYPE_BROWN_DWARF; } } else { const Uint32 weight = rng.Int32(1000000); if (weight < 100) { // should be 1 but that is boring s.m_starType[0] = SystemBody::TYPE_STAR_O; } else if (weight < 1300) { s.m_starType[0] = SystemBody::TYPE_STAR_B; } else if (weight < 7300) { s.m_starType[0] = SystemBody::TYPE_STAR_A; } else if (weight < 37300) { s.m_starType[0] = SystemBody::TYPE_STAR_F; } else if (weight < 113300) { s.m_starType[0] = SystemBody::TYPE_STAR_G; } else if (weight < 234300) { s.m_starType[0] = SystemBody::TYPE_STAR_K; } else if (weight < 250000) { s.m_starType[0] = SystemBody::TYPE_WHITE_DWARF; } else if (weight < 900000) { s.m_starType[0] = SystemBody::TYPE_STAR_M; } else { s.m_starType[0] = SystemBody::TYPE_BROWN_DWARF; } } //Output("%d: %d%\n", sx, sy); if (s.m_numStars > 1) { s.m_starType[1] = SystemBody::BodyType(rng.Int32(SystemBody::TYPE_STAR_MIN, s.m_starType[0])); if (s.m_numStars > 2) { s.m_starType[2] = SystemBody::BodyType(rng.Int32(SystemBody::TYPE_STAR_MIN, s.m_starType[0])); s.m_starType[3] = SystemBody::BodyType(rng.Int32(SystemBody::TYPE_STAR_MIN, s.m_starType[2])); } } if ((s.m_starType[0] <= SystemBody::TYPE_STAR_A) && (rng.Int32(10)==0)) { // make primary a giant. never more than one giant in a system if (freq > Square(10)) { const Uint32 weight = rng.Int32(1000); if (weight >= 999) { s.m_starType[0] = SystemBody::TYPE_STAR_B_HYPER_GIANT; } else if (weight >= 998) { s.m_starType[0] = SystemBody::TYPE_STAR_O_HYPER_GIANT; } else if (weight >= 997) { s.m_starType[0] = SystemBody::TYPE_STAR_K_HYPER_GIANT; } else if (weight >= 995) { s.m_starType[0] = SystemBody::TYPE_STAR_B_SUPER_GIANT; } else if (weight >= 993) { s.m_starType[0] = SystemBody::TYPE_STAR_O_SUPER_GIANT; } else if (weight >= 990) { s.m_starType[0] = SystemBody::TYPE_STAR_K_SUPER_GIANT; } else if (weight >= 985) { s.m_starType[0] = SystemBody::TYPE_STAR_B_GIANT; } else if (weight >= 980) { s.m_starType[0] = SystemBody::TYPE_STAR_O_GIANT; } else if (weight >= 975) { s.m_starType[0] = SystemBody::TYPE_STAR_K_GIANT; } else if (weight >= 950) { s.m_starType[0] = SystemBody::TYPE_STAR_M_HYPER_GIANT; } else if (weight >= 875) { s.m_starType[0] = SystemBody::TYPE_STAR_M_SUPER_GIANT; } else { s.m_starType[0] = SystemBody::TYPE_STAR_M_GIANT; } } else if (freq > Square(5)) s.m_starType[0] = SystemBody::TYPE_STAR_M_GIANT; else s.m_starType[0] = SystemBody::TYPE_STAR_M; //Output("%d: %d%\n", sx, sy); } s.m_name = GenName(galaxy, *sector, s, customCount + i, rng); //Output("%s: \n", s.m_name.c_str()); sector->m_systems.push_back(s); } return true; }
/* * Method: GetNearbySystems * * Get a list of nearby <StarSystems> that match some criteria * * > systems = system:GetNearbySystems(range, filter) * * Parameters: * * range - distance from this system to search, in light years * * filter - an optional function. If specified the function will be called * once for each candidate system with the <StarSystem> object * passed as the only parameter. If the filter function returns * true then the system will be included in the array returned by * <GetNearbySystems>, otherwise it will be omitted. If no filter * function is specified then all systems in range are returned. * * Return: * * systems - an array of systems in range that matched the filter * * Availability: * * alpha 10 * * Status: * * experimental */ static int l_starsystem_get_nearby_systems(lua_State *l) { PROFILE_SCOPED() LUA_DEBUG_START(l); const StarSystem *s = LuaObject<StarSystem>::CheckFromLua(1); const double dist_ly = luaL_checknumber(l, 2); bool filter = false; if (lua_gettop(l) >= 3) { luaL_checktype(l, 3, LUA_TFUNCTION); // any type of function filter = true; } lua_newtable(l); const SystemPath &here = s->GetPath(); const int here_x = here.sectorX; const int here_y = here.sectorY; const int here_z = here.sectorZ; const Uint32 here_idx = here.systemIndex; RefCountedPtr<const Sector> here_sec = Pi::GetGalaxy()->GetSector(here); const int diff_sec = int(ceil(dist_ly/Sector::SIZE)); for (int x = here_x-diff_sec; x <= here_x+diff_sec; x++) { for (int y = here_y-diff_sec; y <= here_y+diff_sec; y++) { for (int z = here_z-diff_sec; z <= here_z+diff_sec; z++) { RefCountedPtr<const Sector> sec = Pi::GetGalaxy()->GetSector(SystemPath(x, y, z)); for (unsigned int idx = 0; idx < sec->m_systems.size(); idx++) { if (x == here_x && y == here_y && z == here_z && idx == here_idx) continue; if (Sector::DistanceBetween(here_sec, here_idx, sec, idx) > dist_ly) continue; RefCountedPtr<StarSystem> sys = Pi::GetGalaxy()->GetStarSystem(SystemPath(x, y, z, idx)); if (filter) { lua_pushvalue(l, 3); LuaObject<StarSystem>::PushToLua(sys.Get()); lua_call(l, 1, 1); if (!lua_toboolean(l, -1)) { lua_pop(l, 1); continue; } lua_pop(l, 1); } lua_pushinteger(l, lua_rawlen(l, -1)+1); LuaObject<StarSystem>::PushToLua(sys.Get()); lua_rawset(l, -3); } } } } LUA_DEBUG_END(l, 1); return 1; }
void DrawOutdent(const float size[2], Graphics::RenderState *state) { PROFILE_SCOPED() // locals RefCountedPtr<Graphics::VertexBuffer> vb; RefCountedPtr<Graphics::IndexBuffer> ib[3]; // see if we have this size of indent in the cache already const vector2f vsize(size[0], size[1]); MapOutdentBuffers::iterator bufIt = s_outdentBuffers.find(vsize); if (bufIt != s_outdentBuffers.end()) { // found it vb = bufIt->second.vb; ib[0] = bufIt->second.ib[0]; ib[1] = bufIt->second.ib[1]; ib[2] = bufIt->second.ib[2]; } else { // generate it const vector3f vertices[] = { /* 0 */ vector3f(0, 0, 0), /* 1 */ vector3f(0, size[1], 0), /* 2 */ vector3f(size[0], size[1], 0), /* 3 */ vector3f(size[0], 0, 0), /* 4 */ vector3f(BORDER_WIDTH, BORDER_WIDTH, 0), /* 5 */ vector3f(BORDER_WIDTH, size[1] - BORDER_WIDTH, 0), /* 6 */ vector3f(size[0] - BORDER_WIDTH, size[1] - BORDER_WIDTH, 0), /* 7 */ vector3f(size[0] - BORDER_WIDTH, BORDER_WIDTH, 0) }; const Uint32 indices[] = { 0, 1, 5, 0, 5, 4, 0, 4, 7, 0, 7, 3, 3, 7, 6, 3, 6, 2, 1, 2, 6, 1, 6, 5, 4, 5, 6, 4, 6, 7 }; // create buffer Graphics::VertexBufferDesc vbd; vbd.attrib[0].semantic = Graphics::ATTRIB_POSITION; vbd.attrib[0].format = Graphics::ATTRIB_FORMAT_FLOAT3; vbd.numVertices = 8; vbd.usage = Graphics::BUFFER_USAGE_STATIC; // Upload data vb.Reset(Screen::GetRenderer()->CreateVertexBuffer(vbd)); TPos* vtxPtr = vb->Map<TPos>(Graphics::BUFFER_MAP_WRITE); assert(vb->GetDesc().stride == sizeof(TPos)); for (Uint32 i = 0; i < 8; i++) { vtxPtr[i].pos = vertices[i]; } vb->Unmap(); // indices Uint32 IndexStart = 0; Uint32 IndexEnd = 12; Uint32 NumIndices = 12; ib[0].Reset(CreateIndexBuffer(indices, IndexStart, IndexEnd, NumIndices)); IndexStart += NumIndices; NumIndices = 12; IndexEnd += NumIndices; ib[1].Reset(CreateIndexBuffer(indices, IndexStart, IndexEnd, NumIndices)); IndexStart += NumIndices; NumIndices = 6; IndexEnd += NumIndices; ib[2].Reset(CreateIndexBuffer(indices, IndexStart, IndexEnd, NumIndices)); TOutdentBuffers tib; tib.vb = vb; tib.ib[0] = ib[0]; tib.ib[1] = ib[1]; tib.ib[2] = ib[2]; s_outdentBuffers[vsize] = tib; } // Draw it! Screen::flatColorMaterial->diffuse = Color(153,153,153,255); Screen::GetRenderer()->DrawBufferIndexed(vb.Get(), ib[0].Get(), state, Screen::flatColorMaterial); Screen::flatColorMaterial->diffuse = Colors::bgShadow; Screen::GetRenderer()->DrawBufferIndexed(vb.Get(), ib[1].Get(), state, Screen::flatColorMaterial); Screen::flatColorMaterial->diffuse = Colors::bg; Screen::GetRenderer()->DrawBufferIndexed(vb.Get(), ib[2].Get(), state, Screen::flatColorMaterial); }
/* * Method: GetNearbySystems * * Get a list of nearby <StarSystems> that match some criteria * * > systems = system:GetNearbySystems(range, filter) * * Parameters: * * range - distance from this system to search, in light years * * filter - an optional function. If specified the function will be called * once for each candidate system with the <StarSystem> object * passed as the only parameter. If the filter function returns * true then the system will be included in the array returned by * <GetNearbySystems>, otherwise it will be omitted. If no filter * function is specified then all systems in range are returned. * * Return: * * systems - an array of systems in range that matched the filter * * Availability: * * alpha 10 * * Status: * * experimental */ static int l_starsystem_get_nearby_systems(lua_State *l) { LUA_DEBUG_START(l); StarSystem *s = LuaStarSystem::GetFromLua(1); double dist_ly = luaL_checknumber(l, 2); bool filter = false; if (lua_gettop(l) >= 3) { luaL_checktype(l, 3, LUA_TFUNCTION); // any type of function filter = true; } lua_newtable(l); pi_lua_table_ro(l); SystemPath here = s->GetPath(); int here_x = here.sectorX; int here_y = here.sectorY; int here_z = here.sectorZ; Uint32 here_idx = here.systemIndex; Sector here_sec(here_x, here_y, here_z); int diff_sec = int(ceil(dist_ly/Sector::SIZE)); for (int x = here_x-diff_sec; x <= here_x+diff_sec; x++) { for (int y = here_y-diff_sec; y <= here_y+diff_sec; y++) { for (int z = here_z-diff_sec; z <= here_z+diff_sec; z++) { Sector sec(x, y, z); for (unsigned int idx = 0; idx < sec.m_systems.size(); idx++) { if (x == here_x && y == here_y && z == here_z && idx == here_idx) continue; if (Sector::DistanceBetween(&here_sec, here_idx, &sec, idx) > dist_ly) continue; RefCountedPtr<StarSystem> sys = StarSystem::GetCached(SystemPath(x, y, z, idx)); if (filter) { lua_pushvalue(l, 3); LuaStarSystem::PushToLua(sys.Get()); lua_call(l, 1, 1); if (!lua_toboolean(l, -1)) { lua_pop(l, 1); continue; } lua_pop(l, 1); } lua_pushinteger(l, lua_rawlen(l, -1)+1); LuaStarSystem::PushToLua(sys.Get()); lua_rawset(l, -3); } } } } LUA_DEBUG_END(l, 1); return 1; }