From 01566dbbdec7fd072c24f29d839091d589a40095 Mon Sep 17 00:00:00 2001 From: Oleg Solovyov Date: Tue, 22 Aug 2023 14:14:47 +0300 Subject: [PATCH 1/4] fuel scooping: improve algorithm Surprisingly, time acceleration did not affect fuel scooping rate. But if it was, scooping rate should be less than 1.0f to keep it efficient since we have a random [0, 1) number compared with it. In case of fuel_scoop_cap == 3, time acceleration == 10, (speed * density > 10000) will bring scooping rate > 1.0f. Enforcing time acceleration even further makes scooping much worse. --- data/modules/FuelScoop.lua | 4 ++-- src/Ship.cpp | 7 +++++-- src/Ship.h | 2 ++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/data/modules/FuelScoop.lua b/data/modules/FuelScoop.lua index 2e1d6b6cde8..ee752ff861e 100644 --- a/data/modules/FuelScoop.lua +++ b/data/modules/FuelScoop.lua @@ -12,11 +12,11 @@ local lc = Lang.GetResource("core") -- These callbacks are triggered from C++ or Lua and are responsible for -- providing UI feedback about the scooping process. -Event.Register("onShipScoopFuel", function(ship, body) +Event.Register("onShipScoopFuel", function(ship, body, amount) ---@type CargoManager local cargoMgr = ship:GetComponent('CargoManager') - cargoMgr:AddCommodity(Commodities.hydrogen, 1) + cargoMgr:AddCommodity(Commodities.hydrogen, amount) if ship == Game.player then Game.AddCommsLogLine(lc.FUEL_SCOOP_ACTIVE_N_TONNES_H_COLLECTED:gsub('%%quantity', diff --git a/src/Ship.cpp b/src/Ship.cpp index f86aa5b8f08..7e2c9ffb939 100644 --- a/src/Ship.cpp +++ b/src/Ship.cpp @@ -1258,8 +1258,11 @@ void Ship::StaticUpdate(const float timeStep) const double dot = vdir.Dot(pdir); if ((m_stats.free_capacity) && (dot > 0.90) && (speed > 100.0) && (density > 0.3)) { const double rate = speed * density * 0.00000333 * double(m_stats.fuel_scoop_cap); - if (Pi::rng.Double() < rate) { - LuaEvent::Queue("onShipScoopFuel", this, p); + m_hydrogenScoopedAccumulator += rate * Pi::game->GetTimeAccelRate(); + if (m_hydrogenScoopedAccumulator > 1) { + const double scoopedTons = floor(m_hydrogenScoopedAccumulator); + LuaEvent::Queue("onShipScoopFuel", this, p, scoopedTons); + m_hydrogenScoopedAccumulator -= scoopedTons; } } } diff --git a/src/Ship.h b/src/Ship.h index a1b2ffea78b..c021bc372ab 100644 --- a/src/Ship.h +++ b/src/Ship.h @@ -330,6 +330,8 @@ class Ship : public DynamicBody { std::string m_shipName; + double m_hydrogenScoopedAccumulator = 0; + public: // FIXME: these methods are deprecated; all calls should use the propulsion object directly. void ClearAngThrusterState() { m_propulsion->ClearAngThrusterState(); } From 3aa66cb528380673d276fc631401c838110526e1 Mon Sep 17 00:00:00 2001 From: Oleg Solovyov Date: Tue, 22 Aug 2023 14:33:49 +0300 Subject: [PATCH 2/4] fuel scooping: do not restrict both speed and density It is likely you will scoop successfully if: 1) flying faster through sparse layers of atmosphere 2) flying in dense atmospheres no matter how slow --- src/Ship.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Ship.cpp b/src/Ship.cpp index 7e2c9ffb939..b221487be08 100644 --- a/src/Ship.cpp +++ b/src/Ship.cpp @@ -1256,8 +1256,10 @@ void Ship::StaticUpdate(const float timeStep) const vector3d vdir = GetVelocity().Normalized(); const vector3d pdir = -GetOrient().VectorZ(); const double dot = vdir.Dot(pdir); - if ((m_stats.free_capacity) && (dot > 0.90) && (speed > 100.0) && (density > 0.3)) { - const double rate = speed * density * 0.00000333 * double(m_stats.fuel_scoop_cap); + const double speed_times_density = speed * density; + // reference: speed > 100.0, density > 0.3 + if ((m_stats.free_capacity) && (dot > 0.90) && speed_times_density > (100.0 * 0.3)) { + const double rate = speed_times_density * 0.00000333 * double(m_stats.fuel_scoop_cap); m_hydrogenScoopedAccumulator += rate * Pi::game->GetTimeAccelRate(); if (m_hydrogenScoopedAccumulator > 1) { const double scoopedTons = floor(m_hydrogenScoopedAccumulator); From 17015219959dbc908c380a341027596af968f434 Mon Sep 17 00:00:00 2001 From: Oleg Solovyov Date: Sat, 9 Sep 2023 15:20:57 +0300 Subject: [PATCH 3/4] fuel scooping: use variable for standard hydrogen density --- src/Ship.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Ship.cpp b/src/Ship.cpp index b221487be08..e1314331cb2 100644 --- a/src/Ship.cpp +++ b/src/Ship.cpp @@ -1257,9 +1257,17 @@ void Ship::StaticUpdate(const float timeStep) const vector3d pdir = -GetOrient().VectorZ(); const double dot = vdir.Dot(pdir); const double speed_times_density = speed * density; - // reference: speed > 100.0, density > 0.3 + /* + * speed = m/s, density = g/cm^3 -> T/m^3, pressure = Pa -> N/m^2 -> kg/(m*s^2) + * m T kg m*kg^2 kg^2 + * - * --- * ----- = 1000 ------- = 1000 ------- + * s m^3 m*s^2 m^4*s^3 m^3*s^3 + * + * fuel_scoop_cap = area, m^2. rate = kg^2/(m*s^3) = (Pa*kg)/s^2 + */ + const double hydrogen_density = 0.00000333; if ((m_stats.free_capacity) && (dot > 0.90) && speed_times_density > (100.0 * 0.3)) { - const double rate = speed_times_density * 0.00000333 * double(m_stats.fuel_scoop_cap); + const double rate = speed_times_density * hydrogen_density * double(m_stats.fuel_scoop_cap); m_hydrogenScoopedAccumulator += rate * Pi::game->GetTimeAccelRate(); if (m_hydrogenScoopedAccumulator > 1) { const double scoopedTons = floor(m_hydrogenScoopedAccumulator); From e7cdf3afcdde301b4c9a26145217064f5133420b Mon Sep 17 00:00:00 2001 From: Oleg Solovyov Date: Wed, 27 Sep 2023 10:20:37 +0300 Subject: [PATCH 4/4] fuel scooping: multiply by timeStep instead multiply density by 60 to keep the rate unchanged --- src/Ship.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Ship.cpp b/src/Ship.cpp index e1314331cb2..c2ec5ffb5d3 100644 --- a/src/Ship.cpp +++ b/src/Ship.cpp @@ -1265,10 +1265,10 @@ void Ship::StaticUpdate(const float timeStep) * * fuel_scoop_cap = area, m^2. rate = kg^2/(m*s^3) = (Pa*kg)/s^2 */ - const double hydrogen_density = 0.00000333; + const double hydrogen_density = 0.0002; if ((m_stats.free_capacity) && (dot > 0.90) && speed_times_density > (100.0 * 0.3)) { const double rate = speed_times_density * hydrogen_density * double(m_stats.fuel_scoop_cap); - m_hydrogenScoopedAccumulator += rate * Pi::game->GetTimeAccelRate(); + m_hydrogenScoopedAccumulator += rate * timeStep; if (m_hydrogenScoopedAccumulator > 1) { const double scoopedTons = floor(m_hydrogenScoopedAccumulator); LuaEvent::Queue("onShipScoopFuel", this, p, scoopedTons);