Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ScanManager improvements and ship properties fixes #5635

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions data/libs/CargoManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,14 @@ function CargoManager:Constructor(ship)
self.usedCargoMass = 0

-- Initialize property variables on owning ship for backwards compatibility
ship:setprop("totalCargo", self:GetTotalSpace())
ship:setprop("usedCargo", 0)
-- don't initialize them if they're already created after first save
if not self.ship:hasprop("totalCargo") then
ship:setprop("totalCargo", self:GetTotalSpace())
end

if not self.ship:hasprop("usedCargo") then
ship:setprop("usedCargo", 0)
end

-- TODO: stored commodities should be represented as array of { name, count, meta } entries
-- to allow for e.g. tracking stolen/scooped cargo, or special mission-related cargoes
Expand Down Expand Up @@ -99,7 +105,7 @@ end
function CargoManager:AddCommodity(type, count)
-- TODO: use a cargo volume metric with variable mass instead of fixed 1m^3 == 1t
local required_space = (type.mass or 1) * (count or 1)

if self:GetFreeSpace() < required_space then
return false
end
Expand Down Expand Up @@ -245,6 +251,7 @@ end
function CargoManager:Unserialize()
setmetatable(self, CargoManager.meta)
self.listeners = {}

return self
end

Expand Down
5 changes: 3 additions & 2 deletions data/modules/Scout/ScanDisplay.lua
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ function scanDisplay:drawDebug()
minRes = ui.dragFloat("MinRes", minRes, 1.0, 0.1, 100, "%f")
coverage = ui.dragFloat("Coverage", coverage, 0.5, 0.5, 100, "%fkm^2")

if scanMgr:GetActiveScan() then
local altitude, resolution = scanMgr:GetBodyState(self.ship.frameBody)
local activeScan = scanMgr:GetActiveScan()
if activeScan then
local altitude, resolution = scanMgr:GetBodyState(scanMgr:GetScanBodyByType())

ui.text("Current Alt: " .. altitude)
ui.text("Current Res: " .. resolution)
Expand Down
61 changes: 47 additions & 14 deletions data/modules/Scout/ScanManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -221,17 +221,29 @@ function ScanManager:UpdateSensorEquipInfo()

end

---@param ScanData scan
---@return Body
function ScanManager:GetScanBodyByType(scan)
scan = scan or self.activeScan
assert(scan, "ScanManager:GetScanBodyByType: Error: scan was nil")
assert(self.scanMap[scan.id], "ScanManager:GetScanBodyByType: Error: scan doesn't belong to current ScanManager")
return scan.orbital and scan.bodyPath:GetSystemBody().body or self.ship.frameBody
end

---@param body Body
---@param ScanData scan
---@return number altitude
---@return number resolution
function ScanManager:GetBodyState(body)
assert(self.activeScan)
function ScanManager:GetBodyState(body, scan)
scan = scan or self.activeScan
assert(scan, "ScanManager:GetBodyState: Error: scan was nil")
assert(self.scanMap[scan.id], "ScanManager:GetBodyState: Error: scan doesn't belong to current ScanManager")

local altitude
local radius = body:GetSystemBody().radius
local sensor = self.activeSensor

if self.activeScan.orbital then
if scan.orbital then
-- altitude above sea-level
altitude = self.ship:GetPositionRelTo(body):length() - radius
else
Expand Down Expand Up @@ -261,7 +273,8 @@ function ScanManager:GetState()
end

if self.activeScan then
local altitude, resolution = self:GetBodyState(self.ship.frameBody)
local body = self:GetScanBodyByType()
local altitude, resolution = self:GetBodyState(body)
local isInRange = resolution <= self.activeScan.minResolution

if altitude > self.activeSensor.minAltitude then
Expand Down Expand Up @@ -425,12 +438,19 @@ function ScanManager:CanScanBeActivated(id)

if scan.complete then return false end

local frameBody = self.ship.frameBody
if not frameBody then return false end
local body = self:GetScanBodyByType(scan)
if not body then return false end

if frameBody.path ~= scan.bodyPath then
if body.path ~= scan.bodyPath then
return false
end

if scan.orbital then
local altitude, resolution = self:GetBodyState(body, scan)
if(resolution > (scan.minResolution * 1.10)) then
return false
end
end

if scan.orbital ~= self.activeSensor.orbital then
return false
Expand Down Expand Up @@ -490,7 +510,9 @@ end
---@package
function ScanManager:OnEnteredFrame(body)
if self.activeScan then

if self.activeScan.orbital then
return
end
local frameBody = body.frameBody

if not frameBody or frameBody.path ~= self.activeScan.bodyPath then
Expand All @@ -501,22 +523,24 @@ function ScanManager:OnEnteredFrame(body)
end

-- Start the scanner callback
---@param force boolean
---@package
function ScanManager:StartScanCallback()
function ScanManager:StartScanCallback(force)
local updateRate = self.activeScan.orbital and ORBITAL_SCAN_UPDATE_RATE or SURFACE_SCAN_UPDATE_RATE

-- Immediately trigger a scan update for responsiveness
self:OnUpdateScan(self.activeScan)

-- Don't queue a new scan callback if we're already running one at the right frequency
if updateRate == self.activeCallback then
-- Force this check if this function was called from ScanManager:Unserialize() because
-- callback is not yet setted up
if updateRate == self.activeCallback and not force then
return
end

self.activeCallback = updateRate

Timer:CallEvery(updateRate, function()

-- cancel this callback if the parameters have changed (it's been orphaned)
if not self.activeScan or not self.activeSensor or self.activeCallback ~= updateRate then
return true
Expand All @@ -532,21 +556,30 @@ end
---@return boolean cancel
---@package
function ScanManager:OnUpdateScan(scan)
local body = self.ship.frameBody
local body = self:GetScanBodyByType(scan)

-- Somehow we don't have a valid body to be scanning
if not body then
logWarning("ScanManager: owning ship does not have a frameBody to scan!")
logWarning("ScanManager: owning ship does not have a system body to scan!")
self:ClearActiveScan()
return true
end

local radius = body:GetSystemBody().radius
local altitude, resolution = self:GetBodyState(body)
local currentScanPos = self.ship:GetPositionRelTo(body):normalized()

if scan.orbital then
if(resolution > (scan.minResolution * 1.10)) then
self:ClearActiveScan()
return true
end
end

-- Determine if we're currently in range to record scan data
local withinParams = resolution <= scan.minResolution and altitude > self.activeSensor.minAltitude



-- Use great-arc distance to calculate the amount of scan coverage in square meters
-- distance = Δσ * radius = arctan( |n1 ⨯ n2| / n1 · n2 ) * radius
Expand Down Expand Up @@ -610,7 +643,7 @@ function ScanManager:Unserialize()

-- Restore the scanning callback on loading a saved game
if self.activeCallback then
self:StartScanCallback()
self:StartScanCallback(true)
end

return self
Expand Down
8 changes: 4 additions & 4 deletions src/Game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -375,17 +375,17 @@ bool Game::UpdateTimeAccel()

vector3d toBody = m_player->GetPosition() - b->GetPositionRelTo(m_player->GetFrame());
double dist = toBody.Length();
double rad = b->GetPhysRadius();
double rad = std::max(b->GetPhysRadius(), 10000.0);

if (dist < 1000.0) {
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_1X);
} else if (dist < std::min(rad + 0.0001 * AU, rad * 1.1)) {
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_10X);
} else if (dist < std::min(rad + 0.001 * AU, rad * 5.0)) {
} else if (dist < std::min(rad + 0.001 * AU, rad * 2.5)) {
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_100X);
} else if (dist < std::min(rad + 0.01 * AU, rad * 10.0)) {
} else if (dist < std::min(rad + 0.01 * AU, rad * 5.0)) {
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_1000X);
} else if (dist < std::min(rad + 0.1 * AU, rad * 1000.0)) {
} else if (dist < std::min(rad + 0.1 * AU, rad * 500.0)) {
newTimeAccel = std::min(newTimeAccel, Game::TIMEACCEL_10000X);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Ship.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -677,7 +677,7 @@ void Ship::UpdateLuaStats()
m_stats.hyperspace_range = m_stats.hyperspace_range_max = 0;
int hyperclass = p.Get("hyperclass_cap");
if (hyperclass) {
std::tie(m_stats.hyperspace_range_max, m_stats.hyperspace_range) =
std::tie(m_stats.hyperspace_range, m_stats.hyperspace_range_max) =
LuaObject<Ship>::CallMethod<double, double>(this, "GetHyperspaceRange");
}

Expand Down
6 changes: 4 additions & 2 deletions src/Space.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -756,9 +756,11 @@ static FrameId MakeFramesFor(const double at_time, SystemBody *sbody, Body *b, F

if ((supertype == SystemBody::SUPERTYPE_GAS_GIANT) ||
(supertype == SystemBody::SUPERTYPE_ROCKY_PLANET)) {
// for planets we want an non-rotating frame for a few radii
// for planets we want an non-rotating frame covering its Hill radius
// and a rotating frame with no radius to contain attached objects
double frameRadius = std::max(4.0 * sbody->GetRadius(), sbody->GetMaxChildOrbitalDistance() * 1.05);
double hillRadius = sbody->GetSemiMajorAxis() * (1.0 - sbody->GetEccentricity()) * pow(sbody->GetMass() / (3.0 * sbody->GetParent()->GetMass()), 1.0 / 3.0);
double frameRadius = std::max(hillRadius, sbody->GetMaxChildOrbitalDistance() * 1.05);
frameRadius = std::max(sbody->GetRadius() * 4.0, frameRadius);
FrameId orbFrameId = Frame::CreateFrame(fId,
sbody->GetName().c_str(),
Frame::FLAG_HAS_ROT,
Expand Down