diff --git a/data/lang/lore/en.json b/data/lang/lore/en.json index 6531943a9b2..d3928e04d80 100644 --- a/data/lang/lore/en.json +++ b/data/lang/lore/en.json @@ -22,5 +22,9 @@ "SOL_MARS_OLYMPUS" : { "description" : "", "message" : "Dont forget to enjoy the longest ski slope within a hundred lightyears!" + }, + "SOL_MERCURY_CALORIS" : { + "description" : "", + "message" : "Located in Caloris Planitia, one of the largest impact craters in the system. Mercury being so close to the sun has lead to most things around here being named accordingly, 'Calor' even means 'heat' in latin and here there is a surplus of it. The almost unlimited solar power has been put to good use in the recycling business." } } \ No newline at end of file diff --git a/data/libs/SpaceStation.lua b/data/libs/SpaceStation.lua index adb712ad2a0..f28f6411f08 100644 --- a/data/libs/SpaceStation.lua +++ b/data/libs/SpaceStation.lua @@ -25,7 +25,7 @@ local l = Lang.GetResource("ui-core") function SpaceStation:Constructor() -- Use a variation of the space station seed itself to ensure consistency - local rand = Rand.New(self.seed .. '-techLevel') + local rand = Rand.New(self.seed .. 'techLevel') local techLevel = rand:Integer(1, 6) + rand:Integer(0,6) local isHomeworld = 0 if Game.system.faction ~= nil and Game.system.faction.hasHomeworld and self.path:IsSameSystem(Game.system.faction.homeworld) then @@ -37,13 +37,16 @@ function SpaceStation:Constructor() self:setprop("techLevel", techLevel) self:setprop("isHomeworld", isHomeworld) local props = self:GetPropertyDefaults() - if props then - for k,v in pairs(props) do - if k and v then - self:setprop(k, v) - end + if props == nil then return end + for k,v in pairs(props) do + if k and v then + self:setprop(k, v) end end + if self.techModifier then + local tmp = self.techLevel + self.techModifier + self:setprop("techLevel", (tmp <= 10) and tmp or 10) -- maximum adjusted level: 10 + end end local equipmentStock = {} diff --git a/data/pigui/views/mainmenu.lua b/data/pigui/views/mainmenu.lua index 0d63a96cd5f..7560bb28dba 100644 --- a/data/pigui/views/mainmenu.lua +++ b/data/pigui/views/mainmenu.lua @@ -42,7 +42,7 @@ local max_flavours = 22 local startLocations = { {['name']=lui.START_AT_MARS, ['desc']=lui.START_AT_MARS_DESC, - ['location']=SystemPath.New(0,0,0,0,18), + ['location']=SystemPath.New(0,0,0,0,22), ['logmsg']=lui.START_LOG_ENTRY_1, ['shipType']='sinonatrix',['money']=100,['hyperdrive']=true, ['equipment']={ diff --git a/data/world/WORLD.txt b/data/world/WORLD.txt index 1e748d4e421..bc5900ff36c 100644 --- a/data/world/WORLD.txt +++ b/data/world/WORLD.txt @@ -12,11 +12,15 @@ world/systems/<##_Name>.lua ## determines order of precedence when loading Name filename only. faction name is determined by contents of the file -world/stations/.json -world/stations//.json +world/stations/.json +world/stations/.json +world/stations/.json +world/stations//.json Contains patch properties for individual stations. - System subdirectories is checked first. + Faction is the first to be loaded, then system, then both (or either) system+station files. + Any attribute in earlier files that reoccur in later loaded files will be overridden by the + last loaded. For example, faction values can be overridden by specific station files. Stations Json format: { @@ -35,6 +39,8 @@ world/stations//.json techLevel Override stations randomly generated techLevel + techModifier Alter the randomly generated techLevel by this number, up to a max of 10 or a minimum of 1 + lore Use this key, translated from lang/lore/*.json, as station lore text nolanglore Use this text as-is, as station lore text diff --git a/data/world/stations/00000000-Sol/Caloris.json b/data/world/stations/00000000-Sol/Caloris.json new file mode 100644 index 00000000000..b5b175e4c35 --- /dev/null +++ b/data/world/stations/00000000-Sol/Caloris.json @@ -0,0 +1,8 @@ +{ + "techLevel" : { + "value" : "10" + }, + "lore" : { + "value" : "SOL_MERCURY_CYDONIA" + } +} \ No newline at end of file diff --git a/data/world/stations/00000000/SCC0000000012-Cydonia.json b/data/world/stations/00000000-Sol/Cydonia.json similarity index 100% rename from data/world/stations/00000000/SCC0000000012-Cydonia.json rename to data/world/stations/00000000-Sol/Cydonia.json diff --git a/data/world/stations/00000000/SCC0000000006-London.json b/data/world/stations/00000000-Sol/London.json similarity index 100% rename from data/world/stations/00000000/SCC0000000006-London.json rename to data/world/stations/00000000-Sol/London.json diff --git a/data/world/stations/00000000/SCC0000000007-Moscow.json b/data/world/stations/00000000-Sol/Moscow.json similarity index 100% rename from data/world/stations/00000000/SCC0000000007-Moscow.json rename to data/world/stations/00000000-Sol/Moscow.json diff --git a/data/world/stations/00000000/SCC0000000013-OlympusMons.json b/data/world/stations/00000000-Sol/OlympusMons.json similarity index 100% rename from data/world/stations/00000000/SCC0000000013-OlympusMons.json rename to data/world/stations/00000000-Sol/OlympusMons.json diff --git a/data/world/stations/00000000/SCC0000000004-Shanghai.json b/data/world/stations/00000000-Sol/Shanghai.json similarity index 100% rename from data/world/stations/00000000/SCC0000000004-Shanghai.json rename to data/world/stations/00000000-Sol/Shanghai.json diff --git a/data/world/stations/SolarFederation.json b/data/world/stations/SolarFederation.json new file mode 100644 index 00000000000..7f5d34f18c3 --- /dev/null +++ b/data/world/stations/SolarFederation.json @@ -0,0 +1,6 @@ +{ + "techModifier" : { + "comment" : "added to the techLevel of all Solar Federation stations, up to 10 max", + "value" : "1" + } +} \ No newline at end of file diff --git a/data/world/systems/00_sol.lua b/data/world/systems/00_sol.lua index 0bbb74e976f..580c53a4fd1 100644 --- a/data/world/systems/00_sol.lua +++ b/data/world/systems/00_sol.lua @@ -32,6 +32,20 @@ local mercury = CustomSystemBody:new('Mercury', 'PLANET_TERRESTRIAL') :orbital_phase_at_start(fixed.deg2rad(f(286,1))) :rings(false) +local mercury_starports = { + CustomSystemBody:new('Furiosa', 'STARPORT_SURFACE') + :latitude(math.deg2rad(89)) + :longitude(5), + CustomSystemBody:new('Caloris', 'STARPORT_SURFACE') + :latitude(math.deg2rad(189)) + :longitude(30), + CustomSystemBody:new('Fenix', 'STARPORT_ORBITAL') + -- can orbital station be made to stay in sun synchronous orbit? + :seed(666) + :semi_major_axis(f(1,25680)) + :inclination(math.deg2rad(90)) +} + local venus = CustomSystemBody:new('Venus', 'PLANET_TERRESTRIAL') :radius(f(95,100)) :mass(f(815,1000)) @@ -51,6 +65,13 @@ local venus = CustomSystemBody:new('Venus', 'PLANET_TERRESTRIAL') :orbital_phase_at_start(fixed.deg2rad(f(248,1))) :rings(false) +local venus_starports = { + CustomSystemBody:new('Cloud Nine', 'STARPORT_ORBITAL') + :seed(6734) + :semi_major_axis(f(100,100000)) + :rotation_period(f(1,24*60*3)) +} + local earth = CustomSystemBody:new('Earth', 'PLANET_TERRESTRIAL') :radius(f(1,1)) :mass(f(1,1)) @@ -92,15 +113,15 @@ local earth_starports = { :latitude(math.deg2rad(34)) :longitude(math.deg2rad(118)), CustomSystemBody:new('Gates Spaceport', 'STARPORT_ORBITAL') - :seed(1) + :seed(8088) :semi_major_axis(f(100,100000)) :rotation_period(f(1,24*60*3)), CustomSystemBody:new('Jobs Pad', 'STARPORT_ORBITAL') - :seed(13) + :seed(6502) :semi_major_axis(f(100,100000)) :rotation_period(f(1,24*60*3)), CustomSystemBody:new('Torvalds Platform', 'STARPORT_ORBITAL') - :seed(0) + :seed(80386) :semi_major_axis(f(5.0,100000)) :rotation_period(f(1,24*60*3)) :orbital_phase_at_start(fixed.deg2rad(f(0,1))) @@ -724,7 +745,9 @@ local charon = { s:bodies(sol, { mercury, + mercury_starports, venus, + venus_starports, earth, earth_starports, moon, diff --git a/src/lua/LuaSpaceStation.cpp b/src/lua/LuaSpaceStation.cpp index a7f17efef11..47e5aa78117 100644 --- a/src/lua/LuaSpaceStation.cpp +++ b/src/lua/LuaSpaceStation.cpp @@ -1,10 +1,12 @@ // Copyright © 2008-2021 Pioneer Developers. See AUTHORS.txt for details // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt +#include "Game.h" #include "Json.h" #include "LuaConstants.h" #include "LuaObject.h" #include "LuaUtils.h" +#include "Pi.h" #include "Ship.h" #include "SpaceStation.h" #include "galaxy/SystemBody.h" @@ -170,51 +172,12 @@ static int l_spacestation_get_nearby_traffic(lua_State *l) * * experimental */ -static int l_spacestation_get_property_defaults(lua_State *l) +static void storeprops(const char *propFile, std::map &keyvalues) { - SpaceStation *station = static_cast(LuaObject::CheckFromLua(1)); - const SystemBody *body = station->GetSystemBody(); - const SystemPath sp = body->GetPath(); - - lua_newtable(l); - - /* No known (or licensed) human settlements further out than 100 sectors outwards, - a single byte (or hex FF) for each dimension is enough for a license number */ - std::string stationID(100, '\0'); - std::snprintf(&stationID[0], 100, "SCC%02X%02X%02X%02X%02X", sp.sectorX, sp.sectorY, sp.sectorZ, sp.systemIndex, sp.bodyIndex); - - pi_lua_settable(l, "stationID", stationID.c_str()); - pi_lua_settable(l, "visualID", stationID.c_str()); - - const char *src = station->GetLabel().c_str(); - std::string sysstr(100, '\0'); - std::snprintf(&sysstr[0], 100, "%02X%02X%02X%02X", sp.sectorX, sp.sectorY, sp.sectorZ, sp.systemIndex); - char stationname[100], *dst = stationname; - - /* remove non [A-Za-z] chars from the station name */ - for (; *src; src++) { - if (*src >= 'A' && *src <= 'Z') - *dst++ = *src; - else if (*src >= 'a' && *src <= 'z') - *dst++ = *src; - } - *dst = '\0'; - - /* try to load moar attributes from world station predefinitions - values from json may override default values */ Json preset; - std::string propFile(100, '\0'); - std::snprintf(&propFile[0], 100, "world/stations/%s/%s-%s.json", sysstr.c_str(), stationID.c_str(), stationname); - Output("Looking for station presets for '%s' in '%s'\n", station->GetLabel().c_str(), propFile.c_str()); preset = JsonUtils::LoadJsonDataFile(propFile); - if (preset.is_null()) { - std::snprintf(&propFile[0], 100, "world/stations/%s-%s.json", stationID.c_str(), stationname); - Output("Looking for station presets for '%s' in '%s'\n", station->GetLabel().c_str(), propFile.c_str()); - preset = JsonUtils::LoadJsonDataFile(propFile); - if (preset.is_null()) { - return 1; - } - } + if (preset.is_null()) + return; for (Json::iterator prop = preset.begin(); prop != preset.end(); ++prop) { const std::string token = prop.key(); @@ -224,14 +187,80 @@ static int l_spacestation_get_property_defaults(lua_State *l) /* if (!valid_token(token)) { continue; } */ Json val = prop.value()["value"]; - if (val.is_null()) { - continue; - } - if (!val.is_string()) { + if (val.is_null() || val.is_string() == false) { continue; } - pi_lua_settable(l, token.c_str(), std::string(val).c_str()); + // will overwrite existing keys + keyvalues[token] = val; + } +} + +static inline void stripnonalpha(const char *src, char *dst, const char *end) +{ + for (; *src && dst < end; src++) { + if ((*src >= 'A' && *src <= 'Z') || (*src >= 'a' && *src <= 'z')) + *dst++ = *src; + } + *dst = '\0'; +} + +// try to load attributes from world station predefinitions +// values from json may override default values +static int l_spacestation_get_property_defaults(lua_State *l) +{ + SpaceStation *station = static_cast(LuaObject::CheckFromLua(1)); + const SystemBody *body = station->GetSystemBody(); + const SystemPath sp = body->GetPath(); + std::map keyvalues; + + char propFile[100]; + char stationname[100]; + char sysname[100]; + char stationID[20]; // No known (or licensed) human settlements further out than 100 sectors outwards, + // a single byte (-128..127, or hex FF) for each dimension is enough for a license number + char sysstr[10]; + std::snprintf(stationID, 20, "SCC%02X%02X%02X%02X%02X", sp.sectorX, sp.sectorY, sp.sectorZ, sp.systemIndex, sp.bodyIndex); + std::strncpy(sysstr, &stationID[3], 9); + sysstr[8] = 0; + + keyvalues["stationID"] = stationID; + keyvalues["visualID"] = stationID; + + const char *stationlabel = station->GetLabel().c_str(); + stripnonalpha(stationlabel, stationname, &stationname[99]); + + RefCountedPtr s = Pi::game->GetGalaxy()->GetStarSystem(sp); + stripnonalpha(s->GetName().c_str(), sysname, &sysname[99]); + + if (s->GetFaction()->IsValid()) { + char facname[100]; + + stripnonalpha(s->GetFaction()->name.c_str(), facname, &facname[99]); + + std::snprintf(propFile, 100, "world/stations/%s.json", facname); + Output("Looking for station presets for '%s' in '%s'\n", stationlabel, propFile); + storeprops(propFile, keyvalues); + } + + // settings for the whole system + std::snprintf(propFile, 100, "world/stations/%s-%s.json", sysstr, sysname); + Output("Looking for station presets for '%s' in '%s'\n", stationlabel, propFile); + storeprops(propFile, keyvalues); + + // in the system specific directory, station names are unique enough + std::snprintf(propFile, 100, "world/stations/%s-%s/%s.json", sysstr, sysname, stationname); + Output("Looking for station presets for '%s' in '%s'\n", stationlabel, propFile); + storeprops(propFile, keyvalues); + + std::snprintf(&propFile[0], 100, "world/stations/%s-%s.json", stationID, stationname); + Output("Looking for station presets for '%s' in '%s'\n", stationlabel, propFile); + storeprops(propFile, keyvalues); + + // push whatever we collected into a lua table and return it + lua_newtable(l); + for (auto kv : keyvalues) { + pi_lua_settable(l, kv.first.c_str(), kv.second.c_str()); } return 1; }