diff options
Diffstat (limited to 'games')
-rw-r--r-- | games/pioneer/README | 10 | ||||
-rw-r--r-- | games/pioneer/alignment.patch | 22 | ||||
-rw-r--r-- | games/pioneer/fix-build.patch | 41 | ||||
-rw-r--r-- | games/pioneer/pioneer.SlackBuild | 17 | ||||
-rw-r--r-- | games/pioneer/pioneer.info | 10 | ||||
-rw-r--r-- | games/pioneer/ship-ai.patch | 447 |
6 files changed, 508 insertions, 39 deletions
diff --git a/games/pioneer/README b/games/pioneer/README index 389b6706afd2..68ed72ee23ad 100644 --- a/games/pioneer/README +++ b/games/pioneer/README @@ -11,13 +11,17 @@ 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. -OpenGL core profile version 3.1 or newer is a runtime dependency, to -determine what version of OpenGL is installed use: +OpenGL core profile version 3.1 or newer is a runtime dependency. To +determine what version of OpenGL is installed, use: glxinfo | grep "core profile version" lua52 is an optional dependency. -To build with debugging support use: +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/alignment.patch b/games/pioneer/alignment.patch deleted file mode 100644 index 10ad31ed08c5..000000000000 --- a/games/pioneer/alignment.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/src/scenegraph/Serializer.orig.h 2019-10-09 13:49:04.000000000 +0200 -+++ b/src/scenegraph/Serializer.h 2019-10-09 18:47:05.238671730 +0200 -@@ -23,14 +23,14 @@ - // where possible, prefer serializing state information via JSON instead. - namespace Serializer { - static_assert((sizeof(Uint32) == 4 && alignof(Uint32) == 4), "Int32 is sized differently on this platform and will not serialize properly."); -- static_assert((sizeof(Uint64) == 8 && alignof(Uint64) == 8), "Int64 is sized differently on this platform and will not serialize properly."); -+ static_assert((sizeof(Uint64) == 8 && alignof(Uint64) <= 8), "Int64 is sized differently on this platform and will not serialize properly."); - static_assert((sizeof(Color) == 4 && alignof(Color) == 1), "Color is padded differently on this platform and will not serialize properly."); - static_assert((sizeof(vector2f) == 8 && alignof(vector2f) == 4), "Vector2f is padded differently on this platform and will not serialize properly."); -- static_assert((sizeof(vector2d) == 16 && alignof(vector2d) == 8), "Vector2d is padded differently on this platform and will not serialize properly."); -+ static_assert((sizeof(vector2d) == 16 && alignof(vector2d) <= 8), "Vector2d is padded differently on this platform and will not serialize properly."); - static_assert((sizeof(vector3f) == 12 && alignof(vector3f) == 4), "Vector3f is padded differently on this platform and will not serialize properly."); -- static_assert((sizeof(vector3d) == 24 && alignof(vector3d) == 8), "Vector3d is padded differently on this platform and will not serialize properly."); -+ static_assert((sizeof(vector3d) == 24 && alignof(vector3d) <= 8), "Vector3d is padded differently on this platform and will not serialize properly."); - static_assert((sizeof(Quaternionf) == 16 && alignof(Quaternionf) == 4), "Quaternionf is padded differently on this platform and will not serialize properly."); -- static_assert((sizeof(Aabb) == 56 && alignof(Aabb) == 8), "Aabb is padded differently on this platform and will not serialize properly."); -+ static_assert((sizeof(Aabb) == 56 && alignof(Aabb) <= 8), "Aabb is padded differently on this platform and will not serialize properly."); - - class Writer { - public: - diff --git a/games/pioneer/fix-build.patch b/games/pioneer/fix-build.patch new file mode 100644 index 000000000000..35afdec062b8 --- /dev/null +++ b/games/pioneer/fix-build.patch @@ -0,0 +1,41 @@ +--- 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 83daea8051e8..1e08159da2fc 100644 --- a/games/pioneer/pioneer.SlackBuild +++ b/games/pioneer/pioneer.SlackBuild @@ -3,6 +3,7 @@ # Slackware build script for pioneer # Copyright 2015-2019 Hunter Sezen California, USA +# Copyright 2023 K. Eugene Carlson Tsukuba, JP # All rights reserved. # # Redistribution and use of this script, with or without modification, is @@ -25,8 +26,7 @@ cd $(dirname $0) ; CWD=$(pwd) PRGNAM=pioneer -SRCNAM=$(printf %s $PRGNAM | tr [a-z] [A-Z]) -VERSION=${VERSION:-20191117} +VERSION=${VERSION:-20230203} BUILD=${BUILD:-1} TAG=${TAG:-_SBo} PKGTYPE=${PKGTYPE:-tgz} @@ -53,16 +53,12 @@ OUTPUT=${OUTPUT:-/tmp} if [ "$ARCH" = "i586" ]; then SLKCFLAGS="-O2 -march=i586 -mtune=i686" - LIBDIRSUFFIX="" elif [ "$ARCH" = "i686" ]; then SLKCFLAGS="-O2 -march=i686 -mtune=i686" - LIBDIRSUFFIX="" elif [ "$ARCH" = "x86_64" ]; then SLKCFLAGS="-O2 -fPIC" - LIBDIRSUFFIX="64" else SLKCFLAGS="-O2" - LIBDIRSUFFIX="" fi set -eu @@ -98,9 +94,10 @@ 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 -# Workaround 32-bit build failure -# https://github.com/pioneerspacesim/pioneer/issues/4691 -patch -p1 < $CWD/alignment.patch +# 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. @@ -121,6 +118,7 @@ cd build -DCMAKE_BUILD_TYPE=$RELEASE .. make make install DESTDIR=$PKG + make -C . build-data install DESTDIR=$PKG cd .. if [ "$DEBUG" = 0 ]; then @@ -130,6 +128,7 @@ fi 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 cat $CWD/$PRGNAM.SlackBuild > $PKG/usr/doc/$PRGNAM-$VERSION/$PRGNAM.SlackBuild mkdir -p $PKG/install diff --git a/games/pioneer/pioneer.info b/games/pioneer/pioneer.info index 81cb877e8d33..dc36db10b9a3 100644 --- a/games/pioneer/pioneer.info +++ b/games/pioneer/pioneer.info @@ -1,10 +1,10 @@ PRGNAM="pioneer" -VERSION="20191117" +VERSION="20230203" HOMEPAGE="https://pioneerspacesim.net/" -DOWNLOAD="https://github.com/pioneerspacesim/pioneer/archive/20191117/pioneer-20191117.tar.gz" -MD5SUM="4b7b7e5119b371b65cd61f45c6747dad" +DOWNLOAD="https://github.com/pioneerspacesim/pioneer/archive/20230203/pioneer-20230203.tar.gz" +MD5SUM="15f3e74303a098bb198f15c8674c43d4" DOWNLOAD_x86_64="" MD5SUM_x86_64="" REQUIRES="assimp" -MAINTAINER="Hunter Sezen" -EMAIL="orbea@riseup.net" +MAINTAINER="K. Eugene Carlson" +EMAIL="kvngncrlsn@gmail.com" diff --git a/games/pioneer/ship-ai.patch b/games/pioneer/ship-ai.patch new file mode 100644 index 000000000000..834788155461 --- /dev/null +++ b/games/pioneer/ship-ai.patch @@ -0,0 +1,447 @@ +--- 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; + } + |