aboutsummaryrefslogtreecommitdiff
path: root/games
diff options
context:
space:
mode:
authorGene Carlson <kvngncrlsn@gmail.com>2024-02-04 16:04:29 +0900
committerWilly Sudiarto Raharjo <willysr@slackbuilds.org>2024-02-07 18:39:59 +0700
commit9df1f6a26986cf377aa025146bf989b132a48ec6 (patch)
tree11f3eb86134ee60d6c8d34cf19a536036efdbbd2 /games
parent08be6aa64c2b65ec6182e5fd7a7b642af7b3b5c2 (diff)
games/pioneer: Updated for version 20240203.
Signed-off-by: Willy Sudiarto Raharjo <willysr@slackbuilds.org>
Diffstat (limited to 'games')
-rw-r--r--games/pioneer/README13
-rw-r--r--games/pioneer/fix-build.patch41
-rw-r--r--games/pioneer/pioneer.SlackBuild29
-rw-r--r--games/pioneer/pioneer.info6
-rw-r--r--games/pioneer/ship-ai.patch447
5 files changed, 26 insertions, 510 deletions
diff --git a/games/pioneer/README b/games/pioneer/README
index 68ed72ee23add..e19fd95e46173 100644
--- a/games/pioneer/README
+++ b/games/pioneer/README
@@ -8,8 +8,9 @@ try your hand at piracy, make your fortune trading between systems, or
do missions for the various factions fighting for power, freedom or
self-determination.
-WARNING: If pioneer is already installed, uninstall it before compiling
-or important game data may be missing and pioneer will fail to start.
+To build with debugging support, use:
+
+ DEBUG="yes" ./pioneer.SlackBuild
OpenGL core profile version 3.1 or newer is a runtime dependency. To
determine what version of OpenGL is installed, use:
@@ -17,11 +18,3 @@ determine what version of OpenGL is installed, use:
glxinfo | grep "core profile version"
lua52 is an optional dependency.
-
-To build with debugging support, use:
-
- DEBUG="yes" ./pioneer.SlackBuild
-
-If building in a graphical session, a popup window about a failure to
-write to a log file will likely appear and stop the build. This is
-harmless, and the build proceeds normally after clicking "OK."
diff --git a/games/pioneer/fix-build.patch b/games/pioneer/fix-build.patch
deleted file mode 100644
index 35afdec062b8d..0000000000000
--- a/games/pioneer/fix-build.patch
+++ /dev/null
@@ -1,41 +0,0 @@
---- src/lua/LuaPushPull.h.orig 2023-09-18 14:23:51.229000000 +0900
-+++ src/lua/LuaPushPull.h 2023-09-18 14:32:10.777000000 +0900
-@@ -12,10 +12,10 @@
- #include <tuple>
-
- inline void pi_lua_generic_push(lua_State *l, bool value) { lua_pushboolean(l, value); }
--inline void pi_lua_generic_push(lua_State *l, int value) { lua_pushinteger(l, value); }
-+inline void pi_lua_generic_push(lua_State *l, int32_t value) { lua_pushinteger(l, value); }
- inline void pi_lua_generic_push(lua_State *l, int64_t value) { lua_pushinteger(l, value); }
--inline void pi_lua_generic_push(lua_State *l, unsigned int value) { lua_pushinteger(l, value); }
--inline void pi_lua_generic_push(lua_State *l, size_t value) { lua_pushinteger(l, value); }
-+inline void pi_lua_generic_push(lua_State *l, uint32_t value) { lua_pushinteger(l, value); }
-+inline void pi_lua_generic_push(lua_State *l, uint64_t value) { lua_pushinteger(l, value); }
- inline void pi_lua_generic_push(lua_State *l, double value) { lua_pushnumber(l, value); }
- inline void pi_lua_generic_push(lua_State *l, const char *value) { lua_pushstring(l, value); }
- inline void pi_lua_generic_push(lua_State *l, const std::string &value)
-@@ -29,10 +29,10 @@
- inline void pi_lua_generic_push(lua_State *l, const std::nullptr_t &value) { lua_pushnil(l); }
-
- inline void pi_lua_generic_pull(lua_State *l, int index, bool &out) { out = lua_toboolean(l, index); }
--inline void pi_lua_generic_pull(lua_State *l, int index, int &out) { out = luaL_checkinteger(l, index); }
-+inline void pi_lua_generic_pull(lua_State *l, int index, int32_t &out) { out = luaL_checkinteger(l, index); }
- inline void pi_lua_generic_pull(lua_State *l, int index, int64_t &out) { out = luaL_checkinteger(l, index); }
--inline void pi_lua_generic_pull(lua_State *l, int index, unsigned int &out) { out = luaL_checkunsigned(l, index); }
--inline void pi_lua_generic_pull(lua_State *l, int index, size_t &out) { out = luaL_checkunsigned(l, index); }
-+inline void pi_lua_generic_pull(lua_State *l, int index, uint32_t &out) { out = luaL_checkinteger(l, index); }
-+inline void pi_lua_generic_pull(lua_State *l, int index, uint64_t &out) { out = luaL_checkinteger(l, index); }
- inline void pi_lua_generic_pull(lua_State *l, int index, float &out) { out = luaL_checknumber(l, index); }
- inline void pi_lua_generic_pull(lua_State *l, int index, double &out) { out = luaL_checknumber(l, index); }
- inline void pi_lua_generic_pull(lua_State *l, int index, const char *&out) { out = luaL_checkstring(l, index); }
---- src/lua/LuaShip.cpp.orig 2023-09-18 14:42:08.048000000 +0900
-+++ src/lua/LuaShip.cpp 2023-09-18 14:42:20.781000000 +0900
-@@ -19,7 +19,7 @@
- #include "SpaceStation.h"
- #include "ship/PlayerShipController.h"
- #include "ship/PrecalcPath.h"
--#include "src/lua.h"
-+#include "lua.h"
-
- /*
- * Class: Ship
diff --git a/games/pioneer/pioneer.SlackBuild b/games/pioneer/pioneer.SlackBuild
index 1e08159da2fcf..4ed508daefa70 100644
--- a/games/pioneer/pioneer.SlackBuild
+++ b/games/pioneer/pioneer.SlackBuild
@@ -3,7 +3,7 @@
# Slackware build script for pioneer
# Copyright 2015-2019 Hunter Sezen California, USA
-# Copyright 2023 K. Eugene Carlson Tsukuba, JP
+# Copyright 2023-2024 K. Eugene Carlson Tsukuba, JP
# All rights reserved.
#
# Redistribution and use of this script, with or without modification, is
@@ -26,7 +26,7 @@
cd $(dirname $0) ; CWD=$(pwd)
PRGNAM=pioneer
-VERSION=${VERSION:-20230203}
+VERSION=${VERSION:-20240203}
BUILD=${BUILD:-1}
TAG=${TAG:-_SBo}
PKGTYPE=${PKGTYPE:-tgz}
@@ -94,17 +94,19 @@ pkg-config --exists glew && GLEW=ON
# as cmake seems to search for them in order.
pkg-config --exists lua5.2 && ! pkg-config --exists lua && LUA=ON
-# Fix 32-bit build (PR 5538) and system lua build (PR 5526).
-patch -p0 < $CWD/fix-build.patch
-# Post-release autopilot fixes (PR 5481, 5551).
-patch -p1 < $CWD/ship-ai.patch
-
# 20210214 bkw: prevent the build from writing to /root/, without
# breaking ccache if it's in use.
-mkdir -p tmphome
+mkdir -p tmphome/.local/share/pioneer
export CCACHE_DIR=${CCACHE_DIR:-$HOME/.ccache}
export HOME=$( pwd )/tmphome
+OSNAME="$(awk -F= '/^ID=/{print $2}' /etc/os-release)"
+OSVER="$(awk -F= '/^VERSION_ID=/{print $2}' /etc/os-release)"
+OSCODENAME="$(awk -F= '/^VERSION_CODENAME=/{print $2}' /etc/os-release)"
+# This version information string can be included when reporting issues
+# upstream.
+INFOSTRING="$OSNAME-$OSVER-$OSCODENAME-$PRGNAM-$VERSION-$ARCH-$BUILD$TAG"
+
mkdir -p build
cd build
cmake \
@@ -112,9 +114,10 @@ cd build
-DCMAKE_CXX_FLAGS:STRING="$SLKCFLAGS" \
-DCMAKE_INSTALL_PREFIX=/usr \
-DCMAKE_INSTALL_BINDIR=games \
- -DPIONEER_DATA_DIR=/usr/share/games/$PRGNAM \
+ -DCMAKE_INSTALL_DATADIR=/usr/share/games \
-DUSE_SYSTEM_LIBGLEW=$GLEW \
-DUSE_SYSTEM_LIBLUA=$LUA \
+ -DPROJECT_VERSION_INFO="$INFOSTRING" \
-DCMAKE_BUILD_TYPE=$RELEASE ..
make
make install DESTDIR=$PKG
@@ -126,6 +129,14 @@ if [ "$DEBUG" = 0 ]; then
grep ELF | cut -f 1 -d : | xargs strip --strip-unneeded 2> /dev/null || true
fi
+# Clean up the data directory, put icons and files where they are
+# supposed to be and install an SVG icon.
+rm -rf $PKG/usr/share/games/$PRGNAM/{licenses,*txt,*md}
+mv $PKG/usr/share/games/{icons,applications,metainfo} $PKG/usr/share
+mkdir -p $PKG/usr/share/icons/hicolor/scalable/apps
+install -m 0644 application-icon/badge-full.svg \
+ $PKG/usr/share/icons/hicolor/scalable/apps/net.pioneerspacesim.Pioneer.svg
+
mkdir -p $PKG/usr/doc/$PRGNAM-$VERSION
cp -a licenses *.txt README.md $PKG/usr/doc/$PRGNAM-$VERSION
rm -f $PKG/usr/doc/$PRGNAM-$VERSION/{CMakeLists,SAVEBUMP}.txt
diff --git a/games/pioneer/pioneer.info b/games/pioneer/pioneer.info
index dc36db10b9a38..0b43c1f9fecc5 100644
--- a/games/pioneer/pioneer.info
+++ b/games/pioneer/pioneer.info
@@ -1,8 +1,8 @@
PRGNAM="pioneer"
-VERSION="20230203"
+VERSION="20240203"
HOMEPAGE="https://pioneerspacesim.net/"
-DOWNLOAD="https://github.com/pioneerspacesim/pioneer/archive/20230203/pioneer-20230203.tar.gz"
-MD5SUM="15f3e74303a098bb198f15c8674c43d4"
+DOWNLOAD="https://github.com/pioneerspacesim/pioneer/archive/20240203/pioneer-20240203.tar.gz"
+MD5SUM="0404c477b33d428f7b48686c71569b52"
DOWNLOAD_x86_64=""
MD5SUM_x86_64=""
REQUIRES="assimp"
diff --git a/games/pioneer/ship-ai.patch b/games/pioneer/ship-ai.patch
deleted file mode 100644
index 834788155461b..0000000000000
--- a/games/pioneer/ship-ai.patch
+++ /dev/null
@@ -1,447 +0,0 @@
---- pioneer-20230203.orig/src/ShipAICmd.cpp 2023-07-19 23:54:00.245824921 +0900
-+++ pioneer-20230203/src/ShipAICmd.cpp 2023-07-19 23:54:15.061778840 +0900
-@@ -731,7 +731,7 @@
- //2 - unsafe escape from effect radius
- //3 - unsafe entry to effect radius
- //4 - probable path intercept
--int CheckCollision(DynamicBody *dBody, const vector3d &pathdir, double pathdist, const vector3d &tpos, double endvel, double r)
-+int CheckCollision(DynamicBody *dBody, const vector3d &pathdir, double pathdist, double tlen, double endvel, double r)
- {
- Propulsion *prop = dBody->GetComponent<Propulsion>();
- if (!prop) // This body doesn't have any propulsion to avoid collision
-@@ -742,24 +742,35 @@
- Body *body = Frame::GetFrame(dBody->GetFrame())->GetBody();
- if (!body) return 0;
- vector3d spos = dBody->GetPosition();
-- double tlen = tpos.Length(), slen = spos.Length();
-+ double slen = spos.Length();
- double fr = MaxFeatureRad(body);
-
-- // if target inside, check if direct entry is safe (30 degree)
-+ // find closest point to obstructor
-+ double distToTangent = -spos.Dot(pathdir);
-+
-+ // if target inside, check if direct entry is safe
-+ // no 30 deg aproach anymore as after FlyAround this couses overshoot
- if (tlen < r) {
-- double af = (tlen > fr) ? 0.5 * (1 - (tlen - fr) / (r - fr)) : 0.5;
-- if (pathdir.Dot(tpos) > -af * tlen)
-- if (slen < fr)
-+
-+ vector3d tangent = spos + distToTangent * pathdir;
-+
-+ //The target is obscured
-+ if(distToTangent < pathdist && tangent.LengthSqr() < fr * fr) {
-+ if (slen < fr )
- return 1;
-- else
-- return 3;
-- else
-- return 0;
-+
-+ return 3;
-+ }
-+
-+ //The speed checks are now done in the CheckSuicide function
-+ return 0;
- }
-
-- // if ship inside, check for max feature height and direct escape (30 degree)
-+ // if ship inside, target outside, check for max feature height and direct escape (30 degree)
- if (slen < r) {
-- if (slen < fr) return 1;
-+ if (slen < fr)
-+ return 1;
-+
- double af = (slen > fr) ? 0.5 * (1 - (slen - fr) / (r - fr)) : 0.5;
- if (pathdir.Dot(spos) < af * slen)
- return 2;
-@@ -768,25 +779,15 @@
- }
-
- // now for the intercept calc
-- // find closest point to obstructor
-- double tanlen = -spos.Dot(pathdir);
-- if (tanlen < 0 || tanlen > pathdist) return 0; // closest point outside path
-+ if (distToTangent < 0 || distToTangent > pathdist) return 0; // closest point to obstructor outside path
-+
-+
-+ vector3d sidePos = spos - pathdir * spos.Dot(pathdir);
-+
-+ //Check if the path goes through the obstructor effective radious
-+ if(sidePos.LengthSqr() < r * r) return 4;
-
-- vector3d perpdir = (tanlen * pathdir + spos).Normalized();
-- double perpspeed = dBody->GetVelocity().Dot(perpdir);
-- double parspeed = dBody->GetVelocity().Dot(pathdir);
-- if (parspeed < 0) parspeed = 0; // shouldn't break any important case
-- if (perpspeed > 0) perpspeed = 0; // prevent attempts to speculatively fly through planets
--
-- // find time that dBody will pass through that point
-- // get velocity as if accelerating from start or end, pick smallest
-- double ivelsqr = endvel * endvel + 2 * prop->GetAccelFwd() * (pathdist - tanlen); // could put endvel in here
-- double fvelsqr = parspeed * parspeed + 2 * prop->GetAccelFwd() * tanlen;
-- double tanspeed = sqrt(ivelsqr < fvelsqr ? ivelsqr : fvelsqr);
-- double time = tanlen / (0.5 * (parspeed + tanspeed)); // actually correct?
-
-- double dist = spos.Dot(perpdir) + perpspeed * time; // spos.perpdir should be positive
-- if (dist < r) return 4;
- return 0;
- }
-
-@@ -828,20 +829,57 @@
- return true;
- }
-
-+
- // check for collision course with frame body
--// tandir is normal vector from planet to target pos or dir
--static bool CheckSuicide(DynamicBody *dBody, const vector3d &tandir)
-+//#define DEBUG_CHECK_SUICIDE
-+static bool CheckSuicide(DynamicBody *dBody, const vector3d &obspos, double obsMass, double safeAlt, double targetAlt, bool recovering)
- {
-- Body *body = Frame::GetFrame(dBody->GetFrame())->GetBody();
- if (!dBody->HasComponent<Propulsion>()) return false;
- Propulsion *prop = dBody->GetComponent<Propulsion>();
- assert(prop != nullptr);
-- if (!body || !body->IsType(ObjectType::TERRAINBODY)) return false;
-
-- double vel = dBody->GetVelocity().Dot(tandir); // vel towards is negative
-- double dist = dBody->GetPosition().Length() - MaxFeatureRad(body);
-- if (vel < -1.0 && vel * vel > 2.0 * prop->GetAccelMin() * dist)
-+ double obsDist = obspos.Length();
-+
-+ //sanity check
-+ if(obsDist > 100 * safeAlt)
-+ return false;
-+
-+ vector3d velDir = dBody->GetVelocity().NormalizedSafe();
-+ double tangDist = obspos.Dot(velDir);
-+
-+ //ship passed the planet
-+ if(tangDist < 0) return false;
-+
-+ double tangLenSqr = (obspos - velDir * tangDist).LengthSqr();
-+
-+ //or pitched speed vector above the safty horizon
-+ if(tangLenSqr > safeAlt * safeAlt) return false;
-+
-+ //Ignore speed check -> continue the recovery until speed vector is over horizon
-+ if(recovering) return true;
-+ //below are more strict speed conditions to enter the recovery
-+
-+ //for final apreach the targetAlt must be used for safe speed check
-+ double zeroSpeedAlt = std::min(safeAlt, targetAlt);
-+
-+ if(zeroSpeedAlt*zeroSpeedAlt < tangLenSqr) return false;
-+
-+ //distance to point of pircing of planet surface or sefe alt sphere by speed vector
-+ double breakingDist = tangDist - sqrt(zeroSpeedAlt*zeroSpeedAlt - tangLenSqr);
-+
-+#ifdef DEBUG_CHECK_SUICIDE
-+ if (dBody->IsType(ObjectType::PLAYER)) {
-+ std::cout << "CheckSuicide breakingDist=" << breakingDist << std::endl;
-+ std::cout << "Speed Check v^2 vs maxV^2: " << dBody->GetVelocity().LengthSqr() << "\t"
-+ << 2*(prop->GetAccelFwd()*breakingDist - G*obsMass*(obsDist-zeroSpeedAlt)/(obsDist*zeroSpeedAlt)) << std::endl;
-+ }
-+#endif
-+
-+ //Energy equation with planet gravity taken into account
-+ if (breakingDist > 100
-+ && dBody->GetVelocity().LengthSqr() > 2*(prop->GetAccelFwd()*breakingDist - G*obsMass*(obsDist-zeroSpeedAlt)/(obsDist*zeroSpeedAlt)))
- return true;
-+
- return false;
- }
-
-@@ -869,7 +907,6 @@
- {
- AICommand::PostLoadFixup(space);
- m_target = space->GetBodyByIndex(m_targetIndex);
-- m_lockhead = true;
- m_frameId = m_target ? m_target->GetFrame() : FrameId();
- // Ensure needed sub-system:
- m_prop = m_dBody->GetComponent<Propulsion>();
-@@ -884,10 +921,11 @@
- assert(m_prop != nullptr);
- m_frameId = FrameId::Invalid;
- m_state = -6;
-- m_lockhead = true;
- m_endvel = 0;
- m_tangent = false;
- m_is_flyto = true;
-+ m_suicideRecovery = false;
-+
- if (!target->IsType(ObjectType::TERRAINBODY))
- m_dist = VICINITY_MIN;
- else
-@@ -915,8 +953,8 @@
- m_endvel(endvel),
- m_tangent(tangent),
- m_state(-6),
-- m_lockhead(true),
-- m_frameId(FrameId::Invalid)
-+ m_frameId(FrameId::Invalid),
-+ m_suicideRecovery(false)
- {
- m_prop = dBody->GetComponent<Propulsion>();
- assert(m_prop != nullptr);
-@@ -933,6 +971,10 @@
- m_endvel = jsonObj["end_vel"];
- m_tangent = jsonObj["tangent"];
- m_state = jsonObj["state"];
-+ if(jsonObj.find("suicide_recovery") != jsonObj.end())
-+ m_suicideRecovery = jsonObj["suicide_recovery"];
-+ else
-+ m_suicideRecovery = false;
- } catch (Json::type_error &) {
- throw SavedGameCorruptException();
- }
-@@ -952,6 +994,7 @@
- aiCommandObj["end_vel"] = m_endvel;
- aiCommandObj["tangent"] = m_tangent;
- aiCommandObj["state"] = m_state;
-+ aiCommandObj["suicide_recovery"] = m_suicideRecovery;
- jsonObj["ai_command"] = aiCommandObj; // Add ai command object to supplied object.
- }
-
-@@ -992,9 +1035,51 @@
- FrameId targframeId = m_target ? m_target->GetFrame() : m_targframeId;
- ParentSafetyAdjust(m_dBody, targframeId, targpos, targvel);
- vector3d relpos = targpos - m_dBody->GetPosition();
-+ double targdist = relpos.Length();
-+
-+ Body* planetNear = Frame::GetFrame(m_dBody->GetFrame())->GetBody();
-+ double targetAlt = targpos.Length();
-+
-+ if(planetNear) {
-+ double M = planetNear->IsType(ObjectType::TERRAINBODY) ? planetNear->GetMass() : 0;
-+ double safeAlt = MaxEffectRad(planetNear, m_prop);
-+ vector3d obspos = -m_dBody->GetPosition();
-+
-+
-+ if ((m_suicideRecovery = CheckSuicide(m_dBody, obspos, M, safeAlt, targetAlt, m_suicideRecovery))) {
-+
-+ //find best orientationg to get to horizon
-+ vector3d sidedir = obspos.Cross(m_dBody->GetVelocity()).NormalizedSafe();
-+ vector3d updir = sidedir.Cross(m_dBody->GetVelocity()).NormalizedSafe();
-+
-+ //clamped tangent of Yaw mismatch to target - for driving side trust
-+ constexpr double cSideDriveRange = 0.02;
-+ double targetSideTan = Clamp(targdist > 1 ? relpos.Dot(sidedir)/targdist : 0, -cSideDriveRange, cSideDriveRange);
-+
-+ //Bellow safe alt (gravity too big for thrusters) breaking will kill the ship eventually
-+ //so in this case ship accelerates along speed vector otherwise it is safe to break
-+ float sign = G*M/obspos.LengthSqr() > 0.9 * m_prop->GetAccelUp() ? 1.0 : -1.0;
-+
-+ double ang = m_prop->AIFaceDirection(m_dBody->GetVelocity() * sign);
-+ m_prop->AIFaceUpdir(updir);
-+#ifdef DEBUG_CHECK_SUICIDE
-+ if (m_dBody->IsType(ObjectType::PLAYER)) {
-+ std::cout << "SUICIDE recovery! ang=" << ang << " targetSideTan=" << targetSideTan << std::endl;
-+ std::cout << "safeAlt=" << safeAlt << " obsdist=" << obspos.Length() << " targetpos.Length()=" << targpos.Length() << std::endl;
-+ }
-+#endif
-+
-+ //Full Up and Forward thruster.
-+ //Side thrust depends on relative pos of the target - not relevant for recovery but it is nice
-+ //to be aligned with the target after surviving.
-+ m_prop->SetLinThrusterState(ang < 0.05 ? vector3d(sign * targetSideTan * (1/cSideDriveRange), 1, -1) : vector3d(0.0));
-+
-+ return false;
-+ }
-+ }
-+
- vector3d reldir = relpos.NormalizedSafe();
- vector3d relvel = targvel - m_dBody->GetVelocity();
-- double targdist = relpos.Length();
-
- #ifdef DEBUG_AUTOPILOT
- if (m_ship->IsType(ObjectType::PLAYER))
-@@ -1018,7 +1103,7 @@
- double erad = MaxEffectRad(body, m_prop);
- Frame *targframe = Frame::GetFrame(targframeId);
- if ((m_target && body != m_target) || (targframe && (!m_tangent || body != targframe->GetBody()))) {
-- int coll = CheckCollision(m_dBody, reldir, targdist, targpos, m_endvel, erad);
-+ int coll = CheckCollision(m_dBody, reldir, targdist, targetAlt, m_endvel, erad);
- if (coll == 0) { // no collision
- if (m_child) {
- m_child.reset();
-@@ -1027,7 +1112,7 @@
- double ang = m_prop->AIFaceDirection(m_dBody->GetPosition());
- m_prop->AIMatchVel(ang < 0.05 ? 1000.0 * m_dBody->GetPosition().Normalized() : vector3d(0.0));
- } else { // same thing for 2/3/4
-- if (!m_child) m_child.reset(new AICmdFlyAround(m_dBody, Frame::GetFrame(m_frameId)->GetBody(), erad * 1.05, 0.0));
-+ if (!m_child) m_child.reset(new AICmdFlyAround(m_dBody, body, erad * 1.05, 0.0));
- static_cast<AICmdFlyAround *>(m_child.get())->SetTargPos(targpos);
- ProcessChild();
- }
-@@ -1068,7 +1153,7 @@
- const vector3d perpdir = (perpspeed > 1e-30) ? perpvel / perpspeed : vector3d(0, 0, 1);
-
- double sidefactor = perpspeed / (tt * 0.5);
-- if (curspeed > (tt + timestep) * maxdecel || maxdecel < sidefactor) {
-+ if (curspeed - m_endvel > (tt + timestep) * maxdecel || maxdecel < sidefactor) {
- m_prop->AIFaceDirection(relvel);
- m_prop->AIMatchVel(targvel);
- m_state = -5;
-@@ -1118,7 +1203,11 @@
- // then flip the ship so we can use our main thrusters to decelerate
- if (m_state && !is_zero_exact(sdiff) && sdiff < maxdecel * timestep * 60) head = -head;
- if (!m_state && decel) sidefactor = -sidefactor;
-- head = head * maxdecel + perpdir * sidefactor;
-+
-+ // check that head does not become zero length
-+ if (maxdecel > 0.001 || abs(sidefactor) > 0.001) {
-+ head = head * maxdecel + perpdir * sidefactor;
-+ }
-
- // face appropriate direction
- if (m_state >= 3) {
-@@ -1410,7 +1499,6 @@
- assert(!std::isnan(alt));
- assert(!std::isnan(vel));
- m_obstructor = obstructor;
-- m_alt = alt;
- m_vel = vel;
- m_targmode = mode;
-
-@@ -1423,6 +1511,8 @@
- Frame *nonRot = Frame::GetFrame(obsFrame->GetNonRotFrame());
- alt = std::min(alt, 0.95 * nonRot->GetRadius());
-
-+ m_alt = alt;
-+
- // generate suitable velocity if none provided
- double minacc = (mode == 2) ? 0 : m_prop->GetAccelMin();
- double mass = obstructor->IsType(ObjectType::TERRAINBODY) ? obstructor->GetMass() : 0;
-@@ -1484,8 +1574,8 @@
- assert(prop != 0);
-
- if (targalt > m_alt) return m_vel;
-- double t = sqrt(2.0 * targdist / prop->GetAccelFwd());
-- double vmaxprox = prop->GetAccelMin() * t; // limit by target proximity
-+ //either use reverse accel or implement dir flipping in FlyAround
-+ double vmaxprox = sqrt(2 * prop->GetAccelRev() * targdist);
- double vmaxstep = std::max(m_alt * 0.05, m_alt - targalt);
- vmaxstep /= Pi::game->GetTimeStep(); // limit by distance covered per timestep
- return std::min(m_vel, std::min(vmaxprox, vmaxstep));
-@@ -1514,22 +1604,16 @@
- }
-
- double timestep = Pi::game->GetTimeStep();
-- vector3d targpos = (!m_targmode) ? m_targpos :
-- m_dBody->GetVelocity().NormalizedSafe() * m_dBody->GetPosition().LengthSqr();
-+ vector3d targpos = (!m_targmode) ? m_targpos : m_dBody->GetVelocity().NormalizedSafe() * m_dBody->GetPosition().LengthSqr();
- vector3d obspos = m_obstructor->GetPositionRelTo(m_dBody);
- double obsdist = obspos.Length();
- vector3d obsdir = obspos / obsdist;
- vector3d relpos = targpos - m_dBody->GetPosition();
-+ double targetDist = relpos.Length();
-+ vector3d shipToTargDir = relpos / targetDist;
-
-- // frame body suicide check, response
-- if (CheckSuicide(m_dBody, -obsdir)) {
-- m_prop->AIFaceDirection(m_dBody->GetPosition()); // face away from planet
-- m_prop->AIMatchVel(vector3d(0.0));
-- return false;
-- }
--
-- // if too far away, fly to tangent
-- if (obsdist > 1.1 * m_alt) {
-+ // if too far away or overshoot -> fly to tangent
-+ if (obsdist > 1.1 * m_alt || m_dBody->GetVelocity().Dot(shipToTargDir) < 0) {
- double v;
- FrameId obsframeId = Frame::GetFrame(m_obstructor->GetFrame())->GetNonRotFrame();
- vector3d tangent = GenerateTangent(m_dBody, obsframeId, targpos, m_alt);
-@@ -1546,7 +1630,7 @@
- }
-
- // limit m_vel by target proximity & distance covered per frame
-- double vel = (m_targmode) ? m_vel : MaxVel(relpos.Length(), targpos.Length());
-+ double vel = (m_targmode) ? m_vel : MaxVel(targetDist, targpos.Length());
-
- // all calculations in ship's frame
- vector3d fwddir = (obsdir.Cross(relpos).Cross(obsdir)).NormalizedSafe();
---- pioneer-20230203.orig/src/ShipAICmd.h 2023-07-19 23:54:00.245824921 +0900
-+++ pioneer-20230203/src/ShipAICmd.h 2023-07-20 00:09:55.718866370 +0900
-@@ -137,10 +137,10 @@
- bool m_tangent; // true if path is to a tangent of the target frame's body
- int m_state;
-
-- bool m_lockhead;
- int m_targetIndex; // used during deserialisation
- vector3d m_reldir; // target direction relative to ship at last frame change
- FrameId m_frameId; // last frame of ship
-+ bool m_suicideRecovery;
- };
-
- class AICmdFlyAround : public AICommand {
---- pioneer-20230203.orig/src/lua/LuaSpace.cpp 2023-07-19 23:54:00.250824905 +0900
-+++ pioneer-20230203/src/lua/LuaSpace.cpp 2023-07-20 00:12:51.625324432 +0900
-@@ -187,7 +187,7 @@
- }
-
- // functions from ShipAiCmd.cpp
--extern int CheckCollision(DynamicBody *dBody, const vector3d &pathdir, double pathdist, const vector3d &tpos, double endvel, double r);
-+extern int CheckCollision(DynamicBody *dBody, const vector3d &pathdir, double pathdist, double targAlt, double endvel, double r);
- extern double MaxEffectRad(const Body *body, Propulsion *prop);
-
- /*
-@@ -256,19 +256,20 @@
- // check for collision at spawn position
- const vector3d shippos = ship->GetPosition();
- const vector3d targpos = targetbody->GetPositionRelTo(ship->GetFrame());
-+ double targAlt = targpos.Length();
- const vector3d relpos = targpos - shippos;
- const vector3d reldir = relpos.NormalizedSafe();
- const double targdist = relpos.Length();
- Body *body = Frame::GetFrame(ship->GetFrame())->GetBody();
- const double erad = MaxEffectRad(body, ship->GetPropulsion());
-- const int coll = CheckCollision(ship, reldir, targdist, targpos, 0, erad);
-+ const int coll = CheckCollision(ship, reldir, targdist, targAlt, 0, erad);
- if (coll) {
- // need to correct positon, to avoid collision
-- if (targpos.Length() > erad) {
-+ if (targAlt > erad) {
- // 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.Normalized();
-+ 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
-@@ -276,7 +277,7 @@
-
- // this is the basis in which the position of the ship will rotate
- const matrix3x3d corrCS = matrix3x3d::FromVectors(x, y, z).Transpose();
-- const double len = targpos.Length();
-+ const double len = targAlt;
- // two possible positions of the ship, when flying around the obstructor to the right or left
- // rotate (in the given basis) the direction from the target to the obstructor, so that it passes tangentially to the obstructor
- const vector3d safe1 = corrCS.Transpose() * (matrix3x3d::RotateY(+asin(erad / len)) * corrCS * -targpos).Normalized() * targdist;
-@@ -288,7 +289,7 @@
- ship->SetPosition(safe2 + targpos);
- } else {
- // target below the effective radius of obstructor. Position the ship direct above the target
-- ship->SetPosition(targpos + targpos.Normalized() * targdist);
-+ ship->SetPosition(targpos + targpos/targAlt * targdist);
- }
- // update velocity direction
- ship->SetVelocity((targpos - ship->GetPosition()).Normalized() * pp.getVel() + targetbody->GetVelocityRelTo(ship->GetFrame()));
---- pioneer-20230203.orig/src/ship/Propulsion.cpp 2023-07-19 23:54:00.252824899 +0900
-+++ pioneer-20230203/src/ship/Propulsion.cpp 2023-07-20 00:14:14.857068275 +0900
-@@ -185,9 +185,9 @@
- double Propulsion::GetThrustMin() const
- {
- // These are the weakest thrusters in a ship
-- double val = static_cast<double>(m_linThrust[THRUSTER_UP]);
-- val = std::min(val, static_cast<double>(m_linThrust[THRUSTER_RIGHT]));
-- val = std::min(val, static_cast<double>(m_linThrust[THRUSTER_LEFT]));
-+ double val = GetThrust(THRUSTER_UP);
-+ val = std::min(val, GetThrust(THRUSTER_RIGHT));
-+ val = std::min(val, GetThrust(THRUSTER_LEFT));
- return val;
- }
-