diff --git a/CHANGELOG.md b/CHANGELOG.md index 48db4a6..7b89084 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Changelog -Latest published Workshop version: **0.0.111** +Latest published Workshop version: **0.0.112** + +## 2026-10-17 — Mission status readability + +- Fixed clipped status and journal text so long reports can be scrolled. +- Fixed duplicated Šárka wave details and restored the hunting-patrol summary. ## 2026-10-17 — Mission menu navigation diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c index 1b364d6..fc94db5 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeAdminMenuProbe.c @@ -180,6 +180,36 @@ modded class ERR_AdminMenu } ERR_ProbePage(0); return true; } + bool ERR_ProbeReportOverflow(string textName, string scrollName) + { + TextWidget text = TextWidget.Cast(GetRootWidget().FindAnyWidget(textName)); + ScrollLayoutWidget scroll = ScrollLayoutWidget.Cast(GetRootWidget().FindAnyWidget(scrollName)); + if (!text || !scroll) return false; + string saved = text.GetText(); + string report; + for (int i = 0; i < 80; i++) report += "Report line " + i.ToString() + ": a long mission report must remain readable.\n"; + report += "FINAL REPORT LINE"; + text.SetText(report); GetRootWidget().Update(); + float width, height, textWidth, textHeight, viewWidth, viewHeight; + text.GetScreenSize(width, height); text.GetTextSize(textWidth, textHeight); + scroll.GetScreenSize(viewWidth, viewHeight); + bool fits = GetGame().GetWorkspace().DPIUnscale(height) >= textHeight - 2 && height > viewHeight; + scroll.SetSliderPos(0, 1); GetRootWidget().Update(); + float x, y, viewX, viewY, sliderX, sliderY; + text.GetScreenPos(x, y); scroll.GetScreenPos(viewX, viewY); scroll.GetSliderPos(sliderX, sliderY); + bool reachable = sliderY >= 0.98 && y + height <= viewY + viewHeight + 2 && y + height > viewY; + PrintFormat("ERR REPORT OVERFLOW: widget=%1 height=%2 textHeight=%3 viewport=%4 slider=%5 fits=%6 reachable=%7", textName, height, textHeight, viewHeight, sliderY, fits, reachable); + text.SetText(saved); scroll.SetSliderPos(0, 0); GetRootWidget().Update(); + return fits && reachable; + } + bool ERR_ProbeHunterSummary() + { + TextWidget text = TextWidget.Cast(GetRootWidget().FindAnyWidget("Status")); + if (!text) return false; + string report = text.GetText(); + array parts = {}; report.Split("Sarka waves:", parts, false); + return report.Contains("HQ hunting patrols:") && parts.Count() == 2 && report.Contains("cars per anger point"); + } bool ERR_ProbeJournalVisible() { TextWidget text = TextWidget.Cast(GetRootWidget().FindAnyWidget("JournalText")); diff --git a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSarkaProbe.c b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSarkaProbe.c index dfe3db1..75ed4f9 100644 --- a/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSarkaProbe.c +++ b/addons/core/Scripts/Game/ERR/00_Core/ERR_NativeSarkaProbe.c @@ -79,6 +79,13 @@ modded class ERR_GameMode { ERR_AdminMenu menu = ERR_AdminMenu.GetOpenMenu(); if (!ERR_SarkaProbeCheck(menu && menu.ERR_ProbeNavigation(m_ERRSarkaMenuPage), "top main tabs and left sidebar reach page " + m_ERRSarkaMenuPage.ToString())) return; + if (m_ERRSarkaMenuPage == ERR_AdminPage.STATUS) + { + if (!ERR_SarkaProbeCheck(menu.ERR_ProbeHunterSummary(), "patrol summary and exactly one Sarka wave summary")) return; + if (!ERR_SarkaProbeCheck(menu.ERR_ProbeReportOverflow("Status", "StatusScroll"), "long status grows and last line scrolls into view")) return; + } + if (m_ERRSarkaMenuPage == ERR_AdminPage.JOURNAL) + if (!ERR_SarkaProbeCheck(menu.ERR_ProbeReportOverflow("JournalText", "JournalScroll"), "long journal grows and last line scrolls into view")) return; System.MakeScreenshot("$logs:err-menu-sidebar-" + m_ERRSarkaMenuPage.ToString()); m_ERRSarkaStage = 91; return; } diff --git a/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c b/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c index 3b35da3..b4e631e 100644 --- a/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c +++ b/addons/core/Scripts/Game/ERR/10_AI/ERR_HunterService.c @@ -149,7 +149,7 @@ class ERR_HunterService : ERR_ConvoyService } string SarkaStatus() { - return string.Format(" Sarka waves: %1 deployed, %2/%3 pending in wave %4; %5.", m_SarkaWaves.Spawned, m_SarkaWaves.Pending, m_SarkaWaves.Target, m_SarkaWaves.Wave, m_SarkaStatus) + string.Format(" %1 cars per anger point (30 per wave maximum).", m_SarkaWaves.CarsPerAnger); + return string.Format("Sarka waves: %1 deployed, %2/%3 pending in wave %4; %5. %6 cars per anger point (30 per wave maximum).", m_SarkaWaves.Spawned, m_SarkaWaves.Pending, m_SarkaWaves.Target, m_SarkaWaves.Wave, m_SarkaStatus, m_SarkaWaves.CarsPerAnger); } // HQ maintenance runs even while tactical ticks pause in an empty round. void PauseSarkaIfEmpty() @@ -434,7 +434,13 @@ class ERR_HunterService : ERR_ConvoyService ERR_HQ.Event("HUNTER RESERVE", string.Format("%1 replaces unavailable patrol %2; reserve=%3/3; next departure in at least 480s; silence is not a confirmed death", unit.Source, m_PendingReserve.Source, m_ReserveSpent)); m_PendingReserve = null; } - override string Status() { return string.Format("HQ hunting patrols: %1 active including bikes and Sarkas; %2 UAZ/trucks deployed; aggression allowance %3, reserve used %4/3 (15 total maximum). Reserve departures at least eight minutes apart. Motorbikes have a separate allowance.", ActiveHunters(), Deployed(), m_Target, m_ReserveSpent) + SarkaStatus(); } + override string Status() + { + // Keep the formatted patrol summary before calling another formatting method. + string patrols = string.Format("HQ hunting patrols: %1 active including bikes and Sarkas; %2 UAZ/trucks deployed; aggression allowance %3, reserve used %4/3 (15 total maximum). Reserve departures at least eight minutes apart. Motorbikes have a separate allowance.", ActiveHunters(), Deployed(), m_Target, m_ReserveSpent); + string sarka = SarkaStatus(); + return patrols + "\n" + sarka; + } protected bool StartHunter(ERR_HQ hq, float now) { if ((!m_PendingReserve && Deployed() >= m_Target + m_ReserveSpent) || Deployed() >= 15 || m_Mode.Forces().Count() >= 250) return false; diff --git a/addons/core/UI/layouts/ERR/AdminMenu.layout b/addons/core/UI/layouts/ERR/AdminMenu.layout index 8b2a6c8..30622c7 100644 --- a/addons/core/UI/layouts/ERR/AdminMenu.layout +++ b/addons/core/UI/layouts/ERR/AdminMenu.layout @@ -325,12 +325,12 @@ ScrollLayoutWidgetClass { { VerticalLayoutWidgetClass { Name "JournalContent" Slot AlignableSlot { - HorizontalAlign 3 VerticalAlign 3 Padding 8 4 14 4 + HorizontalAlign 3 VerticalAlign 0 Padding 8 4 14 4 } { TextWidgetClass { Name "JournalText" Slot LayoutSlot { - HorizontalAlign 3 Padding 0 0 0 8 SizeMode Fill + HorizontalAlign 3 Padding 0 0 0 8 SizeMode Auto } Clipping Ancestor Color 0.9 0.92 0.94 1 Text "Waiting for the first HQ event..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" @@ -748,7 +748,7 @@ TextWidgetClass { FrameWidgetClass { "Is Visible" 0 Name "StatusPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } { TextWidgetClass { Name "StatusHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } - Color 0.9 0.92 0.94 1 Text "Live server state. Mortar counts mean operational / deployed; UAZ allowances include past losses." "Font Size" 19 "Min Font Size" 19 Wrap 1 + Color 0.9 0.92 0.94 1 Text "Live mission status. Scroll for more. Mortars: operational / deployed. UAZ allowances include past losses." "Font Size" 19 "Min Font Size" 19 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" } } ScrollLayoutWidgetClass { @@ -760,12 +760,12 @@ ScrollLayoutWidgetClass { { VerticalLayoutWidgetClass { Name "StatusContent" Slot AlignableSlot { - HorizontalAlign 3 VerticalAlign 3 Padding 8 4 14 4 + HorizontalAlign 3 VerticalAlign 0 Padding 8 4 14 4 } { TextWidgetClass { Name "Status" Slot LayoutSlot { - HorizontalAlign 3 Padding 0 0 0 8 SizeMode Fill + HorizontalAlign 3 Padding 0 0 0 8 SizeMode Auto } Clipping Ancestor Color 0.9 0.92 0.94 1 Text "Waiting for mission status..." "Font Size" 18 "Min Font Size" 18 Wrap 1 FontProperties FontProperties { Font "{3E7733BAC8C831F6}UI/Fonts/RobotoCondensed/RobotoCondensed_Regular.fnt" diff --git a/ui/admin_menu/pages/JournalPage.layout.in b/ui/admin_menu/pages/JournalPage.layout.in index f7f4dbb..f99bb57 100644 --- a/ui/admin_menu/pages/JournalPage.layout.in +++ b/ui/admin_menu/pages/JournalPage.layout.in @@ -13,12 +13,12 @@ ScrollLayoutWidgetClass { { VerticalLayoutWidgetClass { Name "JournalContent" Slot AlignableSlot { - HorizontalAlign 3 VerticalAlign 3 Padding 8 4 14 4 + HorizontalAlign 3 VerticalAlign 0 Padding 8 4 14 4 } { TextWidgetClass { Name "JournalText" Slot LayoutSlot { - HorizontalAlign 3 Padding 0 0 0 8 SizeMode Fill + HorizontalAlign 3 Padding 0 0 0 8 SizeMode Auto } Clipping Ancestor Color {{COLOR_TEXT}} Text "Waiting for the first HQ event..." "Font Size" {{SIZE_BODY}} "Min Font Size" {{SIZE_BODY}} Wrap 1 FontProperties FontProperties { Font "{{FONT}}" diff --git a/ui/admin_menu/pages/StatusPage.layout.in b/ui/admin_menu/pages/StatusPage.layout.in index 008d8f9..59748f3 100644 --- a/ui/admin_menu/pages/StatusPage.layout.in +++ b/ui/admin_menu/pages/StatusPage.layout.in @@ -1,7 +1,7 @@ FrameWidgetClass { "Is Visible" {{VISIBLE_StatusPage}} Name "StatusPage" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 220 OffsetLeft 220 PositionY 160 OffsetTop 160 SizeX 1000 OffsetRight -1220 SizeY 486 OffsetBottom -646 } { TextWidgetClass { Name "StatusHelp" Slot FrameWidgetSlot { Anchor 0 0 0 0 PositionX 28 OffsetLeft 28 PositionY 6 OffsetTop 6 SizeX 936 OffsetRight -964 SizeY 50 OffsetBottom -56 } - Color {{COLOR_TEXT}} Text "Live server state. Mortar counts mean operational / deployed; UAZ allowances include past losses." "Font Size" {{SIZE_INTRO}} "Min Font Size" {{SIZE_INTRO}} Wrap 1 + Color {{COLOR_TEXT}} Text "Live mission status. Scroll for more. Mortars: operational / deployed. UAZ allowances include past losses." "Font Size" {{SIZE_INTRO}} "Min Font Size" {{SIZE_INTRO}} Wrap 1 FontProperties FontProperties { Font "{{FONT}}" } } ScrollLayoutWidgetClass { @@ -13,12 +13,12 @@ ScrollLayoutWidgetClass { { VerticalLayoutWidgetClass { Name "StatusContent" Slot AlignableSlot { - HorizontalAlign 3 VerticalAlign 3 Padding 8 4 14 4 + HorizontalAlign 3 VerticalAlign 0 Padding 8 4 14 4 } { TextWidgetClass { Name "Status" Slot LayoutSlot { - HorizontalAlign 3 Padding 0 0 0 8 SizeMode Fill + HorizontalAlign 3 Padding 0 0 0 8 SizeMode Auto } Clipping Ancestor Color {{COLOR_TEXT}} Text "Waiting for mission status..." "Font Size" {{SIZE_BODY}} "Min Font Size" {{SIZE_BODY}} Wrap 1 FontProperties FontProperties { Font "{{FONT}}"