From c51233424842a4f080d2ddfa94c0a71c5911f83f Mon Sep 17 00:00:00 2001 From: Architector #4 <23612841+Architector4@users.noreply.github.com> Date: Tue, 28 Oct 2025 02:10:37 +0300 Subject: [PATCH] Actor - use fallbacks in GetMovePathEnd() Not doing this causes a crash when a full scene save is done and the move path happens to be empty. Happened to me multiple times over in Conquest mode (yes i know it's broken, doesn't *have* to be) when I set my brain robot on a path to dig a tunnel. Here's a gdb backtrace of the crash: ``` [Detaching after fork from child process 73767] /usr/include/c++/15.2.1/bits/stl_list.h:1688: std::__cxx11::list<_Tp, _Allocator>::const_reference std::__cxx11::list<_Tp, _Allocator>::back() const [with _Tp = RTE::Vector; _Alloc = std::allocator; const_reference = const RTE::Vector&]: Assertion '!this->empty()' failed. Thread 1 "CortexCommand" received signal SIGABRT, Aborted. 0x00007ffff6aaa0db in pthread_kill () from /usr/lib/libc.so.6 (gdb) lay src (gdb) bt #0 0x00007ffff6aaa0db in pthread_kill () from /usr/lib/libc.so.6 #1 0x00007ffff6a447c8 in raise () from /usr/lib/libc.so.6 #2 0x00007ffff6a2560d in abort () from /usr/lib/libc.so.6 #3 0x00007ffff6e9870f in std::__glibcxx_assert_fail (file=, line=, function=, condition=) at /usr/src/debug/gcc/gcc/libstdc++-v3/src/c++11/assert_fail.cc:41 #4 0x00005555556b7ff8 in std::__cxx11::list >::back (this=0x555583892728) at /usr/include/c++/15.2.1/bits/stl_list.h:1688 #5 0x0000555555890712 in RTE::Actor::GetMovePathEnd (this=0x555583891900) at ../Source/Entities/Actor.h:450 #6 0x000055555588470c in RTE::Scene::SaveSceneObject (this=0x7ffe82e4bb90, writer=..., sceneObjectToSave=0x555583891900, isChildAttachable=false, saveFullData=true) at ../Source/Entities/Scene.cpp:1369 #7 0x0000555555880abc in RTE::Scene::Save (this=0x7ffe82e4bb90, writer=...) at ../Source/Entities/Scene.cpp:1097 #8 0x0000555555d9afca in RTE::operator<< (writer=..., operand=0x7ffe82e4bb90) at ../Source/System/Serializable.cpp:53 #9 0x0000555555ad13ab in RTE::Writer::NewPropertyWithValue (this=0x7fffffffcab0, propName="AddScene", propValue=@0x7fffffffc810: 0x7ffe82e4bb90) at ../Source/System/Writer.h:103 #10 0x0000555555acc865 in RTE::MetaMan::Save (this=0x555557448710, writer=...) at ../Source/Managers/MetaMan.cpp:287 #11 0x0000555555beb237 in RTE::MetagameGUI::SaveGame (this=0x55555ba82b20, saveName="AutoSave", savePath="Userdata/UserSavesConquest.rte/AutoSave.ini", resaveSceneData=false) at ../Source/Menus/MetagameGUI.cpp:1109 #12 0x0000555555c02cbb in RTE::MetagameGUI::FinalizeOffensive (this=0x55555ba82b20) at ../Source/Menus/MetagameGUI.cpp:4458 #13 0x0000555555c018d5 in RTE::MetagameGUI::UpdateOffensives (this=0x55555ba82b20) at ../Source/Menus/MetagameGUI.cpp:4321 #14 0x0000555555bee37e in RTE::MetagameGUI::Update (this=0x55555ba82b20) at ../Source/Menus/MetagameGUI.cpp:1492 #15 0x0000555555acf7a0 in RTE::MetaMan::Update (this=0x555557448710) at ../Source/Managers/MetaMan.cpp:892 #16 0x0000555555ac2e84 in RTE::MenuMan::UpdateMetaGameMenu (this=0x55555740f4e0) at ../Source/Managers/MenuMan.cpp:221 #17 0x0000555555ac2ab8 in RTE::MenuMan::Update (this=0x55555740f4e0) at ../Source/Managers/MenuMan.cpp:146 #18 0x0000555555674e81 in RunMenuLoop () at ../Source/Main.cpp:272 #19 0x0000555555675a55 in RunGameLoop () at ../Source/Main.cpp:374 #20 0x000055555567658a in main (argc=1, argv=0x7fffffffdc88) at ../Source/Main.cpp:468 ``` Doesn't crash with this applied. --- Source/Entities/Actor.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Source/Entities/Actor.h b/Source/Entities/Actor.h index f37c7b9cd7..3da398ddc0 100644 --- a/Source/Entities/Actor.h +++ b/Source/Entities/Actor.h @@ -445,9 +445,19 @@ namespace RTE { /// @param m_MovePath.push_back(newCoordinate The new coordinate to add to the end of the MovePath. void AddToMovePathEnd(Vector newCoordinate) { m_MovePath.push_back(newCoordinate); } - /// Gets the last position in this Actor's move path. - /// @return The last position in this Actor's move path. - Vector GetMovePathEnd() const { return m_MovePath.back(); } + /// Gets the last position in this Actor's move path, or otherwise the current move target. + /// @return The last position in this Actor's move path, or otherwise the current move target. + Vector GetMovePathEnd() const { + if (!m_MovePath.empty()) { + return m_MovePath.back(); + } + // In case move path is empty, check our own path request. + if (m_PathRequest) { + return const_cast(m_PathRequest->targetPos); + } + // In case *that* is empty, just return the move target. + return m_MoveTarget; + } /// Removes a coordinate from the beginning of the MovePath, meaning the /// one closest to this Actor.