diff --git a/src/EvoSC.Common/Remote/EventArgsModels/WarmUpRoundEventArgs.cs b/src/EvoSC.Common/Remote/EventArgsModels/WarmUpRoundEventArgs.cs
new file mode 100644
index 000000000..742fe68c0
--- /dev/null
+++ b/src/EvoSC.Common/Remote/EventArgsModels/WarmUpRoundEventArgs.cs
@@ -0,0 +1,14 @@
+namespace EvoSC.Common.Remote.EventArgsModels;
+
+public class WarmUpRoundEventArgs: EventArgs
+{
+ ///
+ /// The current warm-up round.
+ ///
+ public required int Current { get; init; }
+
+ ///
+ /// The total amount of warm-ups.
+ ///
+ public required int Total { get; init; }
+}
diff --git a/src/EvoSC.Common/Remote/ModeScriptEvent.cs b/src/EvoSC.Common/Remote/ModeScriptEvent.cs
index ca84fcb2e..6a0295874 100644
--- a/src/EvoSC.Common/Remote/ModeScriptEvent.cs
+++ b/src/EvoSC.Common/Remote/ModeScriptEvent.cs
@@ -46,6 +46,18 @@ public enum ModeScriptEvent
[Identifier(Name = "ModeScript.WarmUpStart")]
WarmUpStart,
+ ///
+ /// When a warm-up round starts.
+ ///
+ [Identifier(Name = "ModeScript.WarmUpStartRound")]
+ WarmUpStartRound,
+
+ ///
+ /// When a warm-up round starts.
+ ///
+ [Identifier(Name = "ModeScript.WarmUpEndRound")]
+ WarmUpEndRound,
+
///
/// When a player got eliminated by an obstacle.
///
diff --git a/src/EvoSC.Common/Remote/ServerCallbackHandler.cs b/src/EvoSC.Common/Remote/ServerCallbackHandler.cs
index 731929538..7098943a3 100644
--- a/src/EvoSC.Common/Remote/ServerCallbackHandler.cs
+++ b/src/EvoSC.Common/Remote/ServerCallbackHandler.cs
@@ -114,6 +114,22 @@ await _events.RaiseAsync(ModeScriptEvent.StartLine,
case "Trackmania.WarmUp.Start":
await _events.RaiseAsync(ModeScriptEvent.WarmUpStart, EventArgs.Empty);
break;
+ case "Trackmania.WarmUp.StartRound":
+ await _events.RaiseAsync(ModeScriptEvent.WarmUpStartRound,
+ new WarmUpRoundEventArgs
+ {
+ Current = data.GetValue("current", StringComparison.Ordinal).ToObject(),
+ Total = data.GetValue("total", StringComparison.Ordinal).ToObject()
+ });
+ break;
+ case "Trackmania.WarmUp.EndRound":
+ await _events.RaiseAsync(ModeScriptEvent.WarmUpEndRound,
+ new WarmUpRoundEventArgs
+ {
+ Current = data.GetValue("current", StringComparison.Ordinal).ToObject(),
+ Total = data.GetValue("total", StringComparison.Ordinal).ToObject()
+ });
+ break;
case "Trackmania.Event.Eliminated":
await _events.RaiseAsync(ModeScriptEvent.Eliminated,
new PlayerUpdateEventArgs
diff --git a/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs b/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs
deleted file mode 100644
index c253972b6..000000000
--- a/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs
+++ /dev/null
@@ -1,22 +0,0 @@
-using EvoSC.Common.Controllers;
-using EvoSC.Common.Controllers.Attributes;
-using EvoSC.Common.Controllers.Context;
-using EvoSC.Common.Events.Attributes;
-using EvoSC.Common.Remote;
-using EvoSC.Common.Remote.EventArgsModels;
-using EvoSC.Modules.Official.SpectatorCamModeModule.Interfaces;
-
-namespace EvoSC.Modules.Official.SpectatorCamModeModule.Controllers;
-
-[Controller]
-public class SpectatorCamModeEventController(ISpectatorCamModeService camModeService)
- : EvoScController
-{
- [Subscribe(ModeScriptEvent.EndRoundStart)]
- public Task OnEndRoundStartAsync(object sender, RoundEventArgs eventArgs) =>
- camModeService.HideCamModeWidgetAsync();
-
- [Subscribe(ModeScriptEvent.StartRoundStart)]
- public Task OnStartRoundStartAsync(object sender, RoundEventArgs eventArgs) =>
- camModeService.SendPersistentCamModeWidgetAsync();
-}
diff --git a/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs b/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs
index 7ffac03a6..256bfd51d 100644
--- a/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs
+++ b/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs
@@ -9,12 +9,6 @@ public interface ISpectatorCamModeService
///
///
public Task SendPersistentCamModeWidgetAsync();
-
- ///
- /// Hides the previously send widget.
- ///
- ///
- public Task HideCamModeWidgetAsync();
///
/// Hides the default UI provided by the game mode.
diff --git a/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs b/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs
index 69212135b..7b469b7c6 100644
--- a/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs
+++ b/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs
@@ -22,9 +22,6 @@ ISpectatorCamModeSettings settings
public Task SendPersistentCamModeWidgetAsync() =>
manialinks.SendPersistentManialinkAsync(WidgetTemplate, new { settings });
- public Task HideCamModeWidgetAsync() =>
- manialinks.HideManialinkAsync(WidgetTemplate);
-
public Task HideGameModeUiAsync() =>
gameModeUiModuleService.ApplyComponentSettingsAsync(GetGameModeUiSettings());
diff --git a/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms b/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms
index 843927ebf..8108480cc 100644
--- a/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms
+++ b/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms
@@ -39,29 +39,24 @@ Void SetCamModeNameAndIcon(Integer _CamMode, CMlFrame camModeFrame) {
}
declare Real spacing = 1.0;
- declare Real offset = 0.0;
- declare Real width = 0.0;
- if (camModeLabel != Null){
- camModeLabel.Value = TextLib::ToUpperCase(Text_CamMode);
- offset = spacing * 2.0 + camModeLabel.ComputeWidth(camModeLabel.Value);
- width = spacing * 2.0 + camModeLabel.ComputeWidth(camModeLabel.Value);
- }
if (camModeQuad != Null){
camModeQuad.ImageUrl = Icon_CamMode;
- camModeQuad.RelativePosition_V3.X = offset + spacing;
- width = width + spacing + camModeQuad.Size.X;
+ camModeQuad.RelativePosition_V3.X = {{ width }} * 1.0 - spacing - camModeQuad.Size.X;
+ }
+ if (camModeLabel != Null){
+ camModeLabel.Value = TextLib::ToUpperCase(Text_CamMode);
+ camModeLabel.RelativePosition_V3.X = camModeQuad.RelativePosition_V3.X - spacing;
}
- width = width + spacing * 2.0;
- camModeFrame.Size.X = width;
- camModeBg.Size.X = width;
+ camModeFrame.Size.X = 32.0;
+ camModeBg.Size.X = 32.0;
declare Integer targetCamMode for camModeFrame;
targetCamMode = _CamMode;
if({{ settings.Alignment == WidgetPosition.Right ? "True" : "False" }}){
- camModeFrame.RelativePosition_V3.X = width * -1.0;
+ camModeFrame.RelativePosition_V3.X = camModeFrame.Size.X * -1.0;
}else if({{ settings.Alignment == WidgetPosition.Center ? "True" : "False" }}){
- camModeFrame.RelativePosition_V3.X = width / -2.0;
+ camModeFrame.RelativePosition_V3.X = camModeFrame.Size.X / -2.0;
}
}
@@ -236,7 +231,9 @@ main(){
while(True){
yield;
- declare shouldBeDisplayed = InputPlayer != Null && InputPlayer.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned;
+ declare shouldBeDisplayed = InputPlayer != Null
+ && InputPlayer.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned
+ && UI.UISequence == CUIConfig::EUISequence::Playing;
if(!shouldBeDisplayed){
if(mainFrame.Visible){
diff --git a/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt b/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt
index 41d138210..cd5a668c5 100644
--- a/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt
+++ b/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt
@@ -8,7 +8,7 @@
-
+
@@ -27,6 +27,7 @@
textfont="{{ Font.Bold }}"
text="CAM MODE"
valign="center2"
+ halign="right"
/>
-
-
-
-
+
+
+
+
diff --git a/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs b/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs
index 5afc8f94b..7631644ea 100644
--- a/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs
+++ b/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs
@@ -34,5 +34,14 @@ public async Task OnNewRoundAsync(object sender, RoundEventArgs roundEventArgs)
{
await spectatorTargetInfoService.ClearCheckpointsAsync();
await spectatorTargetInfoService.FetchAndCacheTeamInfoAsync();
+ await spectatorTargetInfoService.ResetWidgetForSpectatorsAsync();
+ }
+
+ [Subscribe(ModeScriptEvent.WarmUpStartRound)]
+ public async Task OnNewWarmUpRoundAsync(object sender, WarmUpRoundEventArgs roundEventArgs)
+ {
+ await spectatorTargetInfoService.ClearCheckpointsAsync();
+ await spectatorTargetInfoService.FetchAndCacheTeamInfoAsync();
+ await spectatorTargetInfoService.ResetWidgetForSpectatorsAsync();
}
}
diff --git a/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms b/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms
index 3bc6f9edc..aba5f6be8 100644
--- a/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms
+++ b/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms
@@ -70,37 +70,37 @@ Void FocusPlayer(CSmPlayer _Player) {
}
}
-Text SpecPrevious(CMlLabel button, Boolean focus){
+Void SpecPrevious(CMlLabel button, Boolean focus){
AnimatePop(button);
declare CSmPlayer target <=> GetNextSpawnedPlayer();
- if(focus){
+ if(target == Null && focus){
FocusPlayer(target);
}
- return target.User.Login;
}
-Text SpecNext(CMlLabel button, Boolean focus){
+Void SpecNext(CMlLabel button, Boolean focus){
AnimatePop(button);
declare CSmPlayer target <=> GetNextSpawnedPlayer();
- if(focus){
+ if(target != Null && focus){
FocusPlayer(target);
}
- return target.User.Login;
}
main() {
declare mainFrame <=> (Page.MainFrame.GetFirstChild("main_frame") as CMlFrame);
declare previousButton <=> (Page.MainFrame.GetFirstChild("left_button") as CMlLabel);
declare nextButton <=> (Page.MainFrame.GetFirstChild("right_button") as CMlLabel);
- declare targetLogin = "{{ playerLogin }}";
while(True){
yield;
- if(GUIPlayer == Null){
+ declare shouldBeDisplayed = GUIPlayer != Null && UI.UISequence == CUIConfig::EUISequence::Playing;
+
+ if(!shouldBeDisplayed){
if(mainFrame.Visible){
mainFrame.Hide();
}
+ sleep(100);
continue;
}
@@ -122,10 +122,10 @@ main() {
foreach(Event in PendingEvents){
if(Event.Type == CMlScriptEvent::Type::MouseClick){
if(Event.Control == previousButton){
- targetLogin = SpecPrevious(previousButton, True);
+ SpecPrevious(previousButton, True);
continue;
}else if(Event.Control == nextButton){
- targetLogin = SpecNext(nextButton, True);
+ SpecNext(nextButton, True);
continue;
}
}
diff --git a/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt b/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt
index 4d7e5dabf..fbb54191e 100644
--- a/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt
+++ b/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt
@@ -53,7 +53,7 @@
size="{{ (h*3.4)*0.8 }} {{ h }}"
textsize="{{ Theme.UI_FontSize*2 }}"
textfont="{{ Font.Regular }}"
- text='{{ timeDifference > 0 ? RaceTime.FromMilliseconds(timeDifference) : "000" }}'
+ text='{{ RaceTime.FromMilliseconds(timeDifference) }}'
textprefix="+"
halign="center"
valign="center2"
diff --git a/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs b/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs
index 6e2420dba..c52fbab37 100644
--- a/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs
+++ b/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs
@@ -35,16 +35,6 @@ public async Task SendsPersistentCamModeWidget()
m.SendPersistentManialinkAsync("SpectatorCamModeModule.SpectatorMode", It.IsAny