From 4b3d986b7546ece2e38d8c34079f2bf34b146463 Mon Sep 17 00:00:00 2001 From: Oznogon Date: Thu, 9 Apr 2026 16:32:24 -0700 Subject: [PATCH 1/2] Fix radar staying centered on old ship after transferPlayersToShip() GuiRadarView initializes auto_center_target from my_spaceship at construction but never updates it. After transferPlayersToShip() moves a player to a new ship, radar views remained centered on the old ship until the player logs out and back in. Add a track_my_spaceship flag that keeps auto_center_target in sync with my_spaceship each frame when true (default). Calling setAutoCenterTarget() clears the flag, preserving behaviours that temporarily lock onto an arbitrary target, like Spectator. --- src/screenComponents/radarView.cpp | 6 ++++++ src/screenComponents/radarView.h | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/screenComponents/radarView.cpp b/src/screenComponents/radarView.cpp index def1c8912d..b2f05f7ecd 100644 --- a/src/screenComponents/radarView.cpp +++ b/src/screenComponents/radarView.cpp @@ -56,6 +56,7 @@ GuiRadarView::GuiRadarView(GuiContainer* owner, string id, TargetsContainer* tar view_position(0.0f,0.0f), view_rotation(0), auto_center_target(my_spaceship), + track_my_spaceship(true), auto_center_on_ship(true), auto_rotate_on_ship(false), auto_distance(true), @@ -93,6 +94,7 @@ GuiRadarView::GuiRadarView(GuiContainer* owner, string id, float distance, Targe view_position(0.0f, 0.0f), view_rotation(0), auto_center_target(my_spaceship), + track_my_spaceship(true), auto_center_on_ship(true), auto_rotate_on_ship(false), distance(distance), @@ -123,6 +125,10 @@ GuiRadarView::GuiRadarView(GuiContainer* owner, string id, float distance, Targe void GuiRadarView::onDraw(sp::RenderTarget& renderer) { + // Keep centered on my_spaceship when the player's assigned ship changes. + if (track_my_spaceship && my_spaceship) + auto_center_target = my_spaceship; + // Auto-center on the target, defaulting to my_spaceship on creation. auto transform = auto_center_target.getComponent(); diff --git a/src/screenComponents/radarView.h b/src/screenComponents/radarView.h index 28cb3afa83..06d255edcb 100644 --- a/src/screenComponents/radarView.h +++ b/src/screenComponents/radarView.h @@ -46,6 +46,7 @@ class GuiRadarView : public GuiElement glm::vec2 view_position{0, 0}; float view_rotation; sp::ecs::Entity auto_center_target; + bool track_my_spaceship; bool auto_center_on_ship; bool auto_rotate_on_ship; bool auto_distance = false; @@ -108,7 +109,7 @@ class GuiRadarView : public GuiElement bool getAutoCentering() { return auto_center_on_ship; } GuiRadarView* setAutoCentering(bool value) { this->auto_center_on_ship = value; return this; } sp::ecs::Entity getAutoCenterTarget() { return auto_center_target; } - GuiRadarView* setAutoCenterTarget(sp::ecs::Entity target) { this->auto_center_target = target; return this; } + GuiRadarView* setAutoCenterTarget(sp::ecs::Entity target) { this->auto_center_target = target; this->track_my_spaceship = false; return this; } bool getAutoRotating() { return auto_rotate_on_ship; } GuiRadarView* setAutoRotating(bool value) { this->auto_rotate_on_ship = value; return this; } GuiRadarView* setCallbacks(bpfunc_t mouse_down_func, pfunc_t mouse_drag_func, pfunc_t mouse_up_func, fpfunc_t mouse_wheel_func) { this->mouse_down_func = mouse_down_func; this->mouse_drag_func = mouse_drag_func; this->mouse_up_func = mouse_up_func; this->mouse_wheel_func = mouse_wheel_func; return this; } From 51472634252fc9c60ec0790cb877e1e48c9bcb05 Mon Sep 17 00:00:00 2001 From: Oznogon Date: Thu, 9 Apr 2026 17:04:31 -0700 Subject: [PATCH 2/2] Handle player transfer edge cases - If transferring a player in a position prohibited on the destination entity, move the player to an allowed position and log a warning. If the destination has no allowed positions, log an error and reset the destination's allowed positions to any. - If transferring to a ship that lacks a PlayerControl component, add it. - If transferring to a ship that has an AIController component, remove it. --- src/script.cpp | 71 ++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 14 deletions(-) diff --git a/src/script.cpp b/src/script.cpp index 1d153a9e65..8990bf7d11 100644 --- a/src/script.cpp +++ b/src/script.cpp @@ -464,18 +464,63 @@ static int luaGetEnemiesInRadiusFor(lua_State* L) static void luaTransferPlayers(sp::ecs::Entity source, sp::ecs::Entity target, std::optional station) { - if (!target.getComponent()) return; - // For each player, move them to the same station on the target. - for(auto i : player_info_list) - if (i->ship == source && (!station.has_value() || i->hasPosition(station.value()))) - i->ship = target; + // Relevant only to player-controlled entities. + auto target_pc = target.getOrAddComponent(); + if (target.hasComponent()) target.removeComponent(); + + if (!target_pc.allowed_positions.mask) + { + LOG(Error, "transferPlayersToShip: destination ship has no allowed crew positions. Resetting to Any."); + target_pc.allowed_positions = CrewPositions::all(); + } + + // For each matching player, reassign their ship, filter crew positions + // against the new ship's allowed positions, and clear their cached ship + // password. + for (auto i : player_info_list) + { + if (i->ship != source || (station.has_value() && !i->hasPosition(station.value()))) + continue; + + // Move player to new ship. + i->ship = target; + + // Check against the destination's allowed crew positions. If a player's + // in a position prohibited by the new ship, log a warning for the + // scenario author and drop the player into the next allowed position. + for (auto& cps : i->crew_positions) + { + CrewPositions lost{cps.mask & ~target_pc.allowed_positions.mask}; + if (lost.mask) + { + // This is probably not what the script user intended, so log + // it. + for (auto cp : lost) + LOG(Warning, "transferPlayersToShip: player ", i->name, " held the ", crewPositionToString(cp), " crew position, which is prohibited on the destination ship. Reassigning to next allowed position."); + // Assign the first allowed position not already held on this + // monitor. + for (int n = 0; n < static_cast(CrewPosition::MAX); n++) + { + auto cp = static_cast(n); + if (target_pc.allowed_positions.has(cp) && !cps.has(cp)) + { + cps.add(cp); + break; + } + } + } + cps.mask &= target_pc.allowed_positions.mask; + } + + // Clear last ship password. + i->last_ship_password = ""; + } } static bool luaHasPlayerAtPosition(sp::ecs::Entity source, CrewPosition station) { - for(auto i : player_info_list) - if (i->ship == source && i->hasPosition(station)) - return true; + for (auto i : player_info_list) + if (i->ship == source && i->hasPosition(station)) return true; return false; } @@ -484,16 +529,14 @@ static int luaGetPlayersInfo(lua_State* L) auto source = sp::script::Convert::fromLua(L, 1); lua_newtable(L); int index = 1; - for(auto i : player_info_list) { - if (i->ship != source) - continue; + for (auto i : player_info_list) + { + if (i->ship != source) continue; lua_newtable(L); lua_pushstring(L, i->name.c_str()); lua_setfield(L, -2, "name"); CrewPositions positions; - for(auto cp : i->crew_positions) { - positions.mask |= cp.mask; - } + for (auto cp : i->crew_positions) positions.mask |= cp.mask; sp::script::Convert::toLua(L, positions); lua_setfield(L, -2, "positions"); lua_seti(L, -2, index);