Skip to content

Commit

Permalink
TradeShips hyperjump code change
Browse files Browse the repository at this point in the history
TradeShips now will check for distance(altitude) between orbital station(station's parent body) before making the jump. This should address accumulating hyperclouds around stations and rare illegal jumps. The algorithm will be:
For orbital stations:
1. Undock;
2. Fly to limits of current orbital station (AIFlyTo);
3. OnAICompleted event fires, tell ship to fly to current system's star;
4. Assign task to check distance between current orbital station and ship, if distance is large enough, make the jump.

For ground stations;
1. Undock;
2. Tell ship to fly to current system's star;
3. Assign task to check altitude between current orbital station's parent and ship, if altitude is high enough, make the jump.

Additionally:
1. Fixed lua error when hyperjumping with TradeShips debug tab opened;
2. Added function "PutShipIntoOrbit" in "LuaSpace.cpp" to put ship into orbit of the target body;
3. Added two new methods "setPlayerAsTraderDocked" and "setPlayerAsTraderInbound" in "Flow.lua".

Co-Authored-By: Gliese852 <[email protected]>
  • Loading branch information
Max5377 and Gliese852 committed Nov 18, 2023
1 parent 9ee3f29 commit 72f832e
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 93 deletions.
73 changes: 39 additions & 34 deletions data/modules/TradeShips/Debug.lua
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ debugView.registerTab('debug-trade-ships', function()
property("Total flow", string.format("%.2f ship/hour", Core.params.total_flow))
ui.sameLine()
property("Last spawn interval", ui.Format.Duration(Core.last_spawn_interval))
ui.sameLine()
property("Lawlessness", string.format("%.4f", Game.system.lawlessness))
if Game.system then
ui.sameLine()
property("Lawlessness", string.format("%.4f", Game.system.lawlessness))
end
ui.sameLine()
property("Total bodies in space", #Space.GetBodies())
end
Expand All @@ -126,38 +128,41 @@ debugView.registerTab('debug-trade-ships', function()
totals.label = "Total for " .. utils.count(Core.params.port_params) .. " ports"
local obj = Game.systemView:GetSelectedObject()
local sb_selected = obj.type == Engine.GetEnumValue("ProjectableTypes", "OBJECT") and obj.base == Engine.GetEnumValue("ProjectableBases", "SYSTEMBODY")
arrayTable.draw("tradeships_stationinfo2", Core.params.port_params, arrayTable.addKeys(pairs, {
port = function(k,_) return k end,
label = function(k,_) return k:GetLabel() end,
parent = function(k,_) return k:GetSystemBody().parent.name end,
dist = function(k,_) return k:DistanceTo(k:GetSystemBody().nearestJumpable.body) end,
docks = function(k,_) totals.docks = totals.docks + k.numDocks return k.numDocks end,
busy_s = function(k,_) totals.busy_s = totals.busy_s + k.numShipsDocked return k.numShipsDocked end,
inbound = function(k,_) return inbound[k] end,
landed = function(_,v) totals.landed = totals.landed + v.landed return v.landed end,
flow = function(_,v) totals.flow = totals.flow + v.flow return v.flow end
}),{
{ name = "Port", key = "label", string = true },
{ name = "Parent", key = "parent", string = true },
{ name = "Distance", key = "dist", fnc = distanceInAU },
{ name = "Docks", key = "docks" },
{ name = "Busy", key = "busy", fnc = format("%.2f") },
{ name = "Landed", key = "busy_s" },
{ name = "Calculated", key = "landed", fnc = format("%.2f") },
{ name = "Dock time", key = "time", fnc = format("%.2fh") },
{ name = "Inbound", key = "inbound" },
{ name = "Ship flow", key = "flow", fnc = format("%.2f ship/h") },
},{
totals = { totals },
callbacks = {
onClick = function(row)
Game.systemView:SetSelectedObject(Engine.GetEnumValue("ProjectableTypes", "OBJECT"),
Engine.GetEnumValue("ProjectableBases", "SYSTEMBODY"), row.port:GetSystemBody())
end,
isSelected = function(row)
return sb_selected and Game.systemView:GetSelectedObject().ref == row.port:GetSystemBody()
end
}})
if Game.system then
arrayTable.draw("tradeships_stationinfo2", Core.params.port_params, arrayTable.addKeys(pairs, {
port = function(k,_) return k end,
label = function(k,_) return k:GetLabel() end,
parent = function(k,_) return k:GetSystemBody().parent.name end,
dist = function(k,_) return k:DistanceTo(k:GetSystemBody().nearestJumpable.body) end,
docks = function(k,_) totals.docks = totals.docks + k.numDocks return k.numDocks end,
busy_s = function(k,_) totals.busy_s = totals.busy_s + k.numShipsDocked return k.numShipsDocked end,
inbound = function(k,_) return inbound[k] end,
landed = function(_,v) totals.landed = totals.landed + v.landed return v.landed end,
flow = function(_,v) totals.flow = totals.flow + v.flow return v.flow end
}),{
{ name = "Port", key = "label", string = true },
{ name = "Parent", key = "parent", string = true },
{ name = "Distance", key = "dist", fnc = distanceInAU },
{ name = "Docks", key = "docks" },
{ name = "Busy", key = "busy", fnc = format("%.2f") },
{ name = "Landed", key = "busy_s" },
{ name = "Calculated", key = "landed", fnc = format("%.2f") },
{ name = "Dock time", key = "time", fnc = format("%.2fh") },
{ name = "Inbound", key = "inbound" },
{ name = "Ship flow", key = "flow", fnc = format("%.2f ship/h") },
},{
totals = { totals },
callbacks = {
onClick = function(row)
Game.systemView:SetSelectedObject(Engine.GetEnumValue("ProjectableTypes", "OBJECT"),
Engine.GetEnumValue("ProjectableBases", "SYSTEMBODY"), row.port:GetSystemBody())
end,
isSelected = function(row)
return sb_selected and Game.systemView:GetSelectedObject().ref == row.port:GetSystemBody()
end
}
})
end
end

if ui.collapsingHeader("Local routes") then
Expand Down
41 changes: 8 additions & 33 deletions data/modules/TradeShips/Events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ local onEnterSystem = function (ship)
elseif Core.ships[ship] ~= nil then
local trader = Core.ships[ship]
Core.log:add(ship, 'Entered '..Game.system.name..' from '..trader.from_path:GetStarSystem().name)

if trader.route then
ship:AIDockWith(trader.route.to)
Core.ships[ship]['starport'] = trader.route.to
Expand Down Expand Up @@ -100,23 +99,6 @@ local onLeaveSystem = function (ship)
end
Event.Register("onLeaveSystem", onLeaveSystem)

local onFrameChanged = function (ship)
if not ship:isa("Ship") or Core.ships[ship] == nil then return end
local trader = Core.ships[ship]
Core.log:add(ship, "Entered frame " .. (ship.frameBody and ship.frameBody:GetLabel() or "unknown"))

if trader.status == 'outbound' then
-- the cloud inherits the ship velocity and vector
ship:CancelAI()
if Trader.getSystemAndJump(ship) ~= 'OK' then
ship:AIDockWith(trader.starport)
trader['status'] = 'inbound'
trader.ts_error = 'cnt_jump_frame'
end
end
end
Event.Register("onFrameChanged", onFrameChanged)

local onShipDocked = function (ship, starport)
if Core.ships[ship] == nil then return end
local trader = Core.ships[ship]
Expand Down Expand Up @@ -159,27 +141,20 @@ Event.Register("onShipDocked", onShipDocked)

local onShipUndocked = function (ship, starport)
if Core.ships[ship] == nil then return end

-- fly to the limit of the starport frame
ship:AIFlyTo(starport)

Core.ships[ship]['status'] = 'outbound'
local trader = Core.ships[ship]
ship:AIEnterLowOrbit(trader.starport:GetSystemBody().system:GetStars()[1].body)
Trader.assignTask(ship, Game.time + 10, 'hyperjumpAtDistance')
trader['status'] = 'outbound'
end
Event.Register("onShipUndocked", onShipUndocked)

local onAICompleted = function (ship, ai_error)
if Core.ships[ship] == nil then return end
local trader = Core.ships[ship]
if ai_error ~= 'NONE' then
Core.log:add(ship, 'AICompleted: Error: '..ai_error..' Status: '..trader.status) end

if trader.status == 'outbound' then
if Trader.getSystemAndJump(ship) ~= 'OK' then
ship:AIDockWith(trader.starport)
trader['status'] = 'inbound'
trader.ts_error = 'cnt_jump_aicomp'
end
elseif trader.status == 'orbit' then
Core.log:add(ship, 'AICompleted: Error: '..ai_error..' Status: '..trader.status)
end
if trader.status == 'orbit' then
if ai_error == 'NONE' then
trader.ts_error = "wait_6h"
Trader.assignTask(ship, Game.time + 21600, 'doRedock')
Expand Down Expand Up @@ -258,7 +233,7 @@ local onShipHit = function (ship, attacker)
elseif trader.starport and Engine.rand:Number(1) < trader.chance then
local distance = ship:DistanceTo(trader.starport)
if distance > Core.AU * (2 - trader.chance) then
if Trader.getSystemAndJump(ship) then
if Trader.getSystemAndJump(ship) == 'OK' then
return
else
trader['no_jump'] = true
Expand Down
41 changes: 41 additions & 0 deletions data/modules/TradeShips/Flow.lua
Original file line number Diff line number Diff line change
Expand Up @@ -494,6 +494,47 @@ Flow.spawnInitialShips = function()
return ships_in_space
end

Flow.setPlayerAsTraderDocked = function()
local ship = Game.player
--if player is not a trader
if Core.ships[ship] then
print("Flow.setPlayerAsTraderDocked: player is already a trader")
return
end
--if player is currently docked
if ship.flightState ~= 'DOCKED' then
print("Flow.setPlayerAsTraderDocked: can't set player as docked trader when player is not currently docked")
return
end
local dockedStation = ship:GetDockedWith()
Core.ships[ship] = { ts_error = "OK", status = 'docked', starport = dockedStation, ship_name = Game.player.shipId }
Trader.assignTask(ship, Game.time + utils.deviation(Core.params.port_params[Core.ships[ship].starport].time * 3600, 0.8), 'doUndock')
end

Flow.setPlayerAsTraderInbound = function()
local ship = Game.player
--if player is not a trader
if Core.ships[ship] then
print("Flow.setPlayerAsTraderInbound: player is already a trader")
return
end
-- Space.PutShipOnRoute will teleport player to star's surface when player is docked. We don't want that
if ship.flightState ~= 'FLYING' then
print("Flow.setPlayerAsTraderInbound: can't set player as inbound trader when player is not currently flying")
return
end
-- if there's any station in the system
local nearestStation = ship:FindNearestTo("SPACESTATION")
if not nearestStation then
print("Flow.setPlayerAsTraderInbound: no nearby station is found to set player as inbound trader")
return
end
Core.ships[ship] = { ts_error = "OK", status = 'inbound', starport = nearestStation, ship_name = Game.player.shipId }
Space.PutShipIntoOrbit(ship, Game.system:GetStars()[1].body)
Space.PutShipOnRoute(ship, Core.ships[ship].starport, Engine.rand:Number(0.0, 0.999))-- don't generate at the destination
ship:AIDockWith(Core.ships[ship].starport)
end

Flow.run = function()
local ship_name = utils.chooseEqual(Core.params.ship_names)
local cloud = utils.chooseEqual(Core.params.hyper_routes[ship_name])
Expand Down
47 changes: 43 additions & 4 deletions data/modules/TradeShips/Trader.lua
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,6 @@ Trader.getSystemAndJump = function (ship)
if Core.ships[ship].starport then
local body = Space.GetBody(Core.ships[ship].starport.path:GetSystemBody().parent.index)
local port = Core.ships[ship].starport
-- boost away from the starport before jumping if it is too close
if (ship:DistanceTo(port) < 20000) then
ship:AIEnterLowOrbit(body)
end
return jumpToSystem(ship, getSystem(ship))
end
end
Expand Down Expand Up @@ -275,6 +271,19 @@ Trader.removeFuel = function (ship, count)
return removed
end

Trader.checkDistBetweenStarport = function (ship)
local trader = Core.ships[ship]
if not trader then return nil end
local distance
if trader.starport.type == "STARPORT_ORBITAL" then
distance = ship:DistanceTo(trader.starport)
else
local stationsParent = trader.starport:GetSystemBody().parent.body
distance = ship:GetAltitudeRelTo(stationsParent)
end
return distance >= trader.hyperjumpDist
end

-- TRADER DEFERRED TASKS
--
-- call the passed function in a specified time, checking whether we are still
Expand All @@ -293,6 +302,36 @@ local trader_task = {}
-- the task function prototype should be:
-- function(ship)

trader_task.hyperjumpAtDistance = function(ship)
-- the player may have left the system
local trader = Core.ships[ship]
if not trader then return end
if trader.status == "outbound" and trader.ts_error ~= "HIT" then
-- if trader is not under attack and started to leave station
if trader.starport ~= nil then
-- if trader has not started to hyperjump
if trader.hyperjumpDist == nil then
trader.hyperjumpDist = Engine.rand:Integer(20000, 240000)
end
if Trader.checkDistBetweenStarport(ship) then
-- if distance is large enough attempt to hyperjump
local status = Trader.getSystemAndJump(ship)
if status ~= 'OK' then
ship:CancelAI()
ship:AIDockWith(trader.starport)
trader['status'] = 'inbound'
trader.ts_error = 'cnt_jump_aicomp'
end
trader.hyperjumpDist = nil
else
Trader.assignTask(ship, Game.time + 10, 'hyperjumpAtDistance')
end
end
else
trader.hyperjumpDist = nil
end
end

trader_task.doUndock = function(ship)
-- the player may have left the system or the ship may have already undocked
if ship:exists() and ship:GetDockedWith() then
Expand Down
Loading

0 comments on commit 72f832e

Please sign in to comment.