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

TradeShips hyperjump code change #5647

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
2 changes: 1 addition & 1 deletion data/modules/TradeShips/Debug.lua
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ local statuses = {
}

debugView.registerTab('debug-trade-ships', function()
if not Core.ships and not Core.params then return end
if not Core.ships and not Core.params or not Game.system then return end
if not ui.beginTabItem("Tradeships") then return end

local function property(key, value)
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
107 changes: 82 additions & 25 deletions src/lua/LuaSpace.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@

#include "LuaSpace.h"
#include "Body.h"
#include "LuaBody.h"
#include "CargoBody.h"
#include "EnumStrings.h"
#include "Frame.h"
#include "Game.h"
#include "HyperspaceCloud.h"
#include "LuaBody.h"
#include "LuaManager.h"
#include "LuaObject.h"
#include "LuaUtils.h"
Expand Down Expand Up @@ -99,6 +100,27 @@ static Body *_maybe_wrap_ship_with_cloud(Ship *ship, SystemPath *path, double du
return cloud;
}

// sb - central systembody, pos - absolute coordinates of given object
static vector3d _orbital_velocity_random_direction(const SystemBody *sb, const vector3d &pos)
{
// If we got a zero mass of central body - there is no orbit
if (sb->GetMass() < 0.01)
return vector3d(0.0);
// calculating basis from radius - vector
vector3d k = pos.Normalized();
vector3d i;
if (std::fabs(k.z) > 0.999999) // very vertical = z
i = vector3d(1.0, 0.0, 0.0); // second ort = x
else
i = k.Cross(vector3d(0.0, 0.0, 1.0)).Normalized();
vector3d j = k.Cross(i);
// generating random 2d direction and putting it into basis
vector3d randomOrthoDirection = MathUtil::RandomPointOnCircle(1.0) * matrix3x3d::FromVectors(i, j, k).Transpose();
// calculate the value of the orbital velocity
double orbitalVelocity = sqrt(G * sb->GetMass() / pos.Length());
return randomOrthoDirection * orbitalVelocity;
}

/*
* Function: SpawnShip
*
Expand Down Expand Up @@ -230,7 +252,6 @@ extern double MaxEffectRad(const Body *body, Propulsion *prop);
*
* experimental
*/

static int l_space_put_ship_on_route(lua_State *l)
{
LUA_DEBUG_START(l);
Expand Down Expand Up @@ -272,7 +293,7 @@ static int l_space_put_ship_on_route(lua_State *l)
// target is above the effective radius of obstructor - rotate the ship's position
// around the target position, so that the obstructor's "effective radius" does not cross the path
// direction obstructor -> target
const vector3d z = targpos/targAlt;
const vector3d z = targpos / targAlt;
// the axis around which the position of the ship will rotate
const vector3d y = z.Cross(shippos).NormalizedSafe();
// just the third axis of this basis
Expand All @@ -292,7 +313,7 @@ static int l_space_put_ship_on_route(lua_State *l)
ship->SetPosition(safe2 + targpos);
} else {
// target below the effective radius of obstructor. Position the ship direct above the target
ship->SetPosition(targpos + targpos/targAlt * targdist);
ship->SetPosition(targpos + targpos / targAlt * targdist);
}
// update velocity direction
ship->SetVelocity((targpos - ship->GetPosition()).Normalized() * pp.getVel() + targetbody->GetVelocityRelTo(ship->GetFrame()));
Expand All @@ -301,6 +322,62 @@ static int l_space_put_ship_on_route(lua_State *l)
return 0;
}

/*
* Method: PutShipIntoOrbit
*
* Puts ship into orbit of target body with SystemBody.
*
* > Space.PutShipIntoOrbit(ship, target)
*
* Parameters:
*
* ship - a <Ship> object to be moved
*
* target - the <Star> or <Planet> to orbit
*
* Availability:
*
* October 2023
*
* Status:
*
* experimental
*/
static int l_put_ship_into_orbit(lua_State *l)
{
Ship *s = LuaObject<Ship>::CheckFromLua(1);
Body *b = LuaObject<Body>::CheckFromLua(2);
const SystemBody *sbody = b->GetSystemBody();
if (!sbody) {
return luaL_error(l, "the target body doesn't have a system body");
}
if (!sbody->GetMass()) {
return luaL_error(l, "the target body has zero mass");
}
if (!b->GetPhysRadius()) {
return luaL_error(l, "the target body has a zero physical radius");
}
Ship::FlightState currentState = s->GetFlightState();
if (currentState != Ship::FlightState::FLYING) {
return luaL_error(l, "the ship is not in the \"FLYING\" state. Current state: \"%s\"",
EnumStrings::GetString("ShipFlightState", currentState));
}
// calculations are borrowed from Space::GetHyperspaceExitParams
// calculate distance to primary body relative to body's mass and radius
const double max_orbit_vel = 100e3;
double dist = G * sbody->GetMass() / (max_orbit_vel * max_orbit_vel);
// ensure an absolute minimum and an absolute maximum distance
// the minimum distance from the center of the body should not be less than the radius of the body
// use physical radius, because radius of sbody can be a lot less than physical radius
double radius = b->GetPhysRadius();
dist = Clamp(dist, radius * 1.1, std::max(radius * 1.1, 100 * AU));
vector3d pos{ MathUtil::RandomPointOnSphere(dist) };
s->SetFrame(b->GetFrame());
s->SetPosition(pos);
s->SetVelocity(_orbital_velocity_random_direction(sbody, s->GetPosition()));
return 0;
}

/*
* Function: SpawnShipNear
*
Expand Down Expand Up @@ -701,27 +778,6 @@ static int l_space_spawn_ship_landed_near(lua_State *l)
return 1;
}

// sb - central systembody, pos - absolute coordinates of given object
static vector3d _orbital_velocity_random_direction(const SystemBody *sb, const vector3d &pos)
{
// If we got a zero mass of central body - there is no orbit
if (sb->GetMass() < 0.01)
return vector3d(0.0);
// calculating basis from radius - vector
vector3d k = pos.Normalized();
vector3d i;
if (std::fabs(k.z) > 0.999999) // very vertical = z
i = vector3d(1.0, 0.0, 0.0); // second ort = x
else
i = k.Cross(vector3d(0.0, 0.0, 1.0)).Normalized();
vector3d j = k.Cross(i);
// generating random 2d direction and putting it into basis
vector3d randomOrthoDirection = MathUtil::RandomPointOnCircle(1.0) * matrix3x3d::FromVectors(i, j, k).Transpose();
// calculate the value of the orbital velocity
double orbitalVelocity = sqrt(G * sb->GetMass() / pos.Length());
return randomOrthoDirection * orbitalVelocity;
}

/*
* Function: SpawnCargoNear
*
Expand Down Expand Up @@ -1118,6 +1174,7 @@ void LuaSpace::Register()
{ "SpawnCargoNear", l_space_spawn_cargo_near },
{ "SpawnShipOrbit", l_space_spawn_ship_orbit },
{ "PutShipOnRoute", l_space_put_ship_on_route },
{ "PutShipIntoOrbit", l_put_ship_into_orbit },

{ "GetBody", l_space_get_body },
{ "GetNumBodies", l_space_get_num_bodies },
Expand Down