From 19c2c9c3d0603bd9d944359142549571a56d5b87 Mon Sep 17 00:00:00 2001 From: Oznogon Date: Tue, 31 Mar 2026 15:44:16 -0700 Subject: [PATCH 1/4] Add radar ShortRange/LongRange check to mousewheel zoom --- src/screens/gm/gameMasterScreen.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/screens/gm/gameMasterScreen.cpp b/src/screens/gm/gameMasterScreen.cpp index d990b1b234..b28b2e9c92 100644 --- a/src/screens/gm/gameMasterScreen.cpp +++ b/src/screens/gm/gameMasterScreen.cpp @@ -341,7 +341,7 @@ void GameMasterScreen::update(float delta) { float view_distance = std::clamp(main_radar->getDistance() * (1.0f - (key_zoom_delta * 0.1f)), MIN_ZOOM_DISTANCE, MAX_ZOOM_DISTANCE); main_radar->setDistance(view_distance); - if (view_distance < SHORT_RANGE_DISTANCE) main_radar->shortRange(); + if (view_distance <= SHORT_RANGE_DISTANCE) main_radar->shortRange(); else main_radar->longRange(); } @@ -877,6 +877,8 @@ void GameMasterScreen::onMouseWheel(float value, glm::vec2 position) // Set the new zoom level. main_radar->setDistance(view_distance); zoom_slider->setValue(view_distance); + if (view_distance <= SHORT_RANGE_DISTANCE) main_radar->shortRange(); + else main_radar->longRange(); // Adjust the radar's view position to keep the world coordinates // under the pointer consistent. From 8c08759fa017ae83e9b8bbc497c4b34e8de2e29d Mon Sep 17 00:00:00 2001 From: Oznogon Date: Tue, 31 Mar 2026 18:24:22 -0700 Subject: [PATCH 2/4] Reimplement health bars on GM screen Bring the GM screen closer to parity with legacy by reimplementing health bars for any entity with a Hull component. Health bars default to always visible at ShortRange. This implementation expands on legacy by making smaller bars also visible at LongRange, but only if an entity's hull is < 90% of max. This also adds a GM screen keybind (default `H`) to toggle health bar visibility. --- src/gui/hotkeyConfig.cpp | 2 ++ src/gui/hotkeyConfig.h | 1 + src/screens/gm/gameMasterScreen.cpp | 47 +++++++++++++++++++++++++++++ src/screens/gm/gameMasterScreen.h | 1 + 4 files changed, 51 insertions(+) diff --git a/src/gui/hotkeyConfig.cpp b/src/gui/hotkeyConfig.cpp index 96981248db..5b7ec2e6b4 100644 --- a/src/gui/hotkeyConfig.cpp +++ b/src/gui/hotkeyConfig.cpp @@ -317,6 +317,7 @@ Keys::Keys() : gm_delete("GM_DELETE", "Delete"), gm_clipboardcopy("GM_CLIPBOARD_COPY", "F5"), gm_show_callsigns("GM_SHOW_CALLSIGNS", "C"), + gm_show_health_bars("GM_SHOW_HEALTH_BARS", "H"), // Spectator screen spectator_show_callsigns("SPECTATOR_SHOW_CALLSIGNS", "C") @@ -508,6 +509,7 @@ void Keys::init() gm_delete.setLabel(tr("hotkey_menu", "GM screen"), tr("hotkey_GM", "Delete")); gm_clipboardcopy.setLabel(tr("hotkey_menu", "GM screen"), tr("hotkey_GM", "Copy to clipboard")); gm_show_callsigns.setLabel(tr("hotkey_menu", "GM screen"), tr("hotkey_GM", "Show callsigns (GM)")); + gm_show_health_bars.setLabel(tr("hotkey_menu", "GM screen"), tr("hotkey_GM", "Show health bars (GM)")); // Spectator screen spectator_show_callsigns.setLabel(tr("hotkey_menu", "Spectator view"), tr("hotkey_Spectator", "Show callsigns (spectator)")); diff --git a/src/gui/hotkeyConfig.h b/src/gui/hotkeyConfig.h index 5fee57b9d4..ee3d151f11 100644 --- a/src/gui/hotkeyConfig.h +++ b/src/gui/hotkeyConfig.h @@ -199,6 +199,7 @@ class Keys sp::io::Keybinding gm_delete; sp::io::Keybinding gm_clipboardcopy; sp::io::Keybinding gm_show_callsigns; + sp::io::Keybinding gm_show_health_bars; // Spectator screen binds sp::io::Keybinding spectator_show_callsigns; diff --git a/src/screens/gm/gameMasterScreen.cpp b/src/screens/gm/gameMasterScreen.cpp index b28b2e9c92..0358794d23 100644 --- a/src/screens/gm/gameMasterScreen.cpp +++ b/src/screens/gm/gameMasterScreen.cpp @@ -86,6 +86,49 @@ GameMasterScreen::GameMasterScreen(RenderLayer* render_layer) ->setOverlayCallback( [this](sp::RenderTarget& renderer) { + const bool is_short_range = main_radar->getDistance() <= SHORT_RANGE_DISTANCE; + float bar_width = is_short_range ? 60.0f : 30.0f; + float bar_height = is_short_range ? 5.0f : 2.0f; + float bar_offset = bar_width * 0.5f; + float bar_distance = bar_height * 4.0f; + + // Draw hull health bars + if (show_health_bars) + { + for (auto [entity, hull, transform, trace] : sp::ecs::Query>()) + { + const float hull_norm = hull.current / hull.max; + if (trace) bar_distance = std::clamp(trace->radius * main_radar->getScale() * 2.0f, trace->min_size, trace->max_size) * 0.75f; + + if (hull_norm < 0.9f || is_short_range) + { + glm::vec2 screen_pos = main_radar->worldToScreen(transform.getPosition()); + const float health_bar_width = bar_width * hull_norm; + // Scale color from green to yellow to red with damage. + uint8_t bar_r, bar_g; + if (hull_norm >= 0.5f) + { + float t = (hull_norm - 0.5f) / 0.5f; + bar_r = static_cast(255.0f * (1.0f - t)); + bar_g = 255; + } + else if (hull_norm >= 0.2f) + { + float t = (hull_norm - 0.2f) / 0.3f; + bar_r = 255; + bar_g = static_cast(255.0f * t); + } + else + { + bar_r = 255; + bar_g = 0; + } + renderer.fillRect(sp::Rect(screen_pos.x - bar_offset, screen_pos.y + bar_distance, health_bar_width, bar_height), glm::u8vec4(bar_r, bar_g, 0, 192)); + renderer.outlineRect(sp::Rect(screen_pos.x - bar_offset, screen_pos.y + bar_distance, bar_width, bar_height), glm::u8vec4(255, 255, 255, 128)); + } + } + } + if (gm_cursor_mode != GMCursorMode::CreateEntity && gm_cursor_mode != GMCursorMode::SetDirection) return; if (!gameGlobalInfo->on_gm_preview_trace) return; const RadarTrace& trace = *gameGlobalInfo->on_gm_preview_trace; @@ -370,6 +413,10 @@ void GameMasterScreen::update(float delta) if (keys.gm_show_callsigns.getDown()) main_radar->showCallsigns(!main_radar->getCallsigns()); + // Toggle health bars. + if (keys.gm_show_health_bars.getDown()) + show_health_bars = !show_health_bars; + bool has_object = false; has_cpu_ship = false; bool has_player_ship = false; diff --git a/src/screens/gm/gameMasterScreen.h b/src/screens/gm/gameMasterScreen.h index a62c75ba0b..d2da1f1ab8 100644 --- a/src/screens/gm/gameMasterScreen.h +++ b/src/screens/gm/gameMasterScreen.h @@ -106,6 +106,7 @@ class GameMasterScreen : public GuiCanvas, public Updatable { return GMCursorMode(unsigned(a) & unsigned(b)); } bool has_cpu_ship = false; + bool show_health_bars = true; GuiButton* create_button; GuiButton* cancel_action_button; From 93ca2e9cbb8a4e96a7d7a3f0127431ef6e445cd8 Mon Sep 17 00:00:00 2001 From: Oznogon Date: Tue, 31 Mar 2026 18:26:56 -0700 Subject: [PATCH 3/4] Rescale Callsign distance from trace on radars --- src/systems/radar.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/systems/radar.cpp b/src/systems/radar.cpp index 47cb1d97c2..e0418b90b6 100644 --- a/src/systems/radar.cpp +++ b/src/systems/radar.cpp @@ -68,5 +68,8 @@ void BasicRadarRendering::renderOnRadar(sp::RenderTarget& renderer, sp::ecs::Ent { if (entity == my_spaceship || !(RadarRenderSystem::current_flags & RadarRenderSystem::FlagCallsigns)) return; - renderer.drawText(sp::Rect(screen_position.x, screen_position.y - 15, 0, 0), callsign.callsign, sp::Alignment::Center, 15, bold_font); + float text_distance = 15.0f; + if (auto trace = entity.getComponent()) text_distance = std::clamp(trace->radius * 1.5f * scale, trace->min_size, trace->max_size) + 15.0f * 1.5f * scale; + + renderer.drawText(sp::Rect(screen_position.x, screen_position.y - text_distance, 0, 0), callsign.callsign, sp::Alignment::Center, 15, bold_font); } From c26a9cf7cec4d546bfa157122448b821d4700970 Mon Sep 17 00:00:00 2001 From: oznogon Date: Sat, 11 Apr 2026 00:58:11 -0700 Subject: [PATCH 4/4] Move bar_distance default out of loop --- src/screens/gm/gameMasterScreen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/screens/gm/gameMasterScreen.cpp b/src/screens/gm/gameMasterScreen.cpp index 0358794d23..97d87c4142 100644 --- a/src/screens/gm/gameMasterScreen.cpp +++ b/src/screens/gm/gameMasterScreen.cpp @@ -90,7 +90,6 @@ GameMasterScreen::GameMasterScreen(RenderLayer* render_layer) float bar_width = is_short_range ? 60.0f : 30.0f; float bar_height = is_short_range ? 5.0f : 2.0f; float bar_offset = bar_width * 0.5f; - float bar_distance = bar_height * 4.0f; // Draw hull health bars if (show_health_bars) @@ -98,6 +97,7 @@ GameMasterScreen::GameMasterScreen(RenderLayer* render_layer) for (auto [entity, hull, transform, trace] : sp::ecs::Query>()) { const float hull_norm = hull.current / hull.max; + float bar_distance = bar_height * 4.0f; if (trace) bar_distance = std::clamp(trace->radius * main_radar->getScale() * 2.0f, trace->min_size, trace->max_size) * 0.75f; if (hull_norm < 0.9f || is_short_range)