From 30d51cd29a458e3911db53c23783093bfbbc6206 Mon Sep 17 00:00:00 2001 From: monsonjeremy Date: Thu, 29 May 2025 16:01:52 -0700 Subject: [PATCH 01/10] RMST --- .../ModalDialogs/Modes/RMSTHelpModalDialog.as | 91 +++ src/Interface/Views/RMCMenu.as | 107 ++-- src/Utils/DataManager.as | 29 +- src/Utils/MX/Methods/LoadRandomMap.as | 7 + src/Utils/RMC/GlobalProperties.as | 5 +- src/Utils/RMC/RMST.as | 554 ++++++++++++++++++ 6 files changed, 746 insertions(+), 47 deletions(-) create mode 100644 src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as create mode 100644 src/Utils/RMC/RMST.as diff --git a/src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as b/src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as new file mode 100644 index 00000000..748f7319 --- /dev/null +++ b/src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as @@ -0,0 +1,91 @@ +class RMSTHelpModalDialog : ModalDialog +{ + UI::Texture@ clubIdTex; + UI::Texture@ roomIdTex; + + RMSTHelpModalDialog() + { + super(Icons::InfoCircle + " \\$zRandom Map Survival Together###RMSTHelp"); + m_size = vec2(Draw::GetWidth(), Draw::GetHeight()) * 0.6f; + @clubIdTex = UI::LoadTexture("src/Assets/Images/help_clubId.jpg"); + @roomIdTex = UI::LoadTexture("src/Assets/Images/help_roomId.jpg"); + } + + void RenderDialog() override + { + float scale = UI::GetScale(); + UI::BeginChild("Content", vec2(0, -32) * scale); + UI::PushFont(Fonts::Header); + UI::Text("Random Map Survival Together"); + UI::PopFont(); + UI::Markdown( + "Random Map Survival Together is a multiplayer survival mode where players work together to survive as long as possible.\n\n" + + "The game mode requires all players to join the server you have set up. Players have no plugins to install and is compatible with console players.\n\n" + ); + UI::NewLine(); + UI::Separator(); + UI::PushFont(Fonts::Header); + UI::Text("Prerequisites for a good functioning of the RMST mode"); + UI::PopFont(); + UI::Markdown( + "- You need to have a **Club** with at least **Admin** permissions\n" + + "- You need to have a **Room** in this club\n" + + "- You need to **join the room** before starting the mode\n" + + "- All players must **join the same room**\n\n" + ); + UI::Separator(); + UI::PushFont(Fonts::Header); + UI::Text("How RMST works"); + UI::PopFont(); + UI::Markdown( + "**Collaborative Survival:**\n" + + "- All players share the same timer and work as a team\n" + + "- When **any player** gets a goal medal, the **entire team** gets +3 minutes\n" + + "- When **any player** skips a map, the **entire team** loses -1 minute\n" + + "- The session ends when the shared timer reaches 0\n\n" + + "**Team Progress Tracking:**\n" + + "- Team achievements (total medals and skips) are shared\n" + + "- Individual contributions are tracked for recognition\n" + + "- MVP is determined by individual goals vs skips ratio\n" + + "- Real-time team progress updates\n\n" + ); + UI::Separator(); + UI::PushFont(Fonts::Header); + UI::Text("How to get Club ID and Room ID"); + UI::PopFont(); + UI::Markdown( + "**Club ID:**\n" + + "Go to your club page on the Trackmania website and look at the URL. The Club ID is the number at the end.\n\n" + ); + if (clubIdTex !is null) { + UI::Image(clubIdTex, vec2(clubIdTex.GetSize().x, clubIdTex.GetSize().y) * 0.5f * scale); + } + UI::NewLine(); + UI::Markdown( + "**Room ID:**\n" + + "Go to your room page in the club and look at the URL. The Room ID is the number at the end.\n\n" + ); + if (roomIdTex !is null) { + UI::Image(roomIdTex, vec2(roomIdTex.GetSize().x, roomIdTex.GetSize().y) * 0.5f * scale); + } + UI::NewLine(); + UI::Separator(); + UI::PushFont(Fonts::Header); + UI::Text("Tips for a successful RMST session"); + UI::PopFont(); + UI::Markdown( + "- **True teamwork:** Any team member getting a goal medal helps everyone!\n" + + "- **Coordinate skips:** Discuss as a team before anyone skips a difficult map\n" + + "- **Divide and conquer:** Players can focus on different types of maps they're good at\n" + + "- **Watch the shared timer:** Keep track of team time and plan accordingly\n" + + "- **Use voice chat:** Communication is crucial for team coordination\n" + + "- **Celebrate together:** Every goal medal is a team achievement!\n" + + "- **Support each other:** Help teammates learn difficult sections\n\n" + ); + UI::EndChild(); + + if (UI::Button("Close")) { + m_shouldClose = true; + } + } +} \ No newline at end of file diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index 0572548f..783a1ff3 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -169,6 +169,47 @@ namespace RMC #endif UI::TreePop(); } + if (Permissions::CreateActivity() && UI::TreeNode(MX_COLOR_STR + Icons::Heart + " \\$zRandom Map Survival Together \\$f33(BETA)")) { + UI::TextDisabled(Icons::InfoCircle + " Hover for infos"); + UI::SetPreviousTooltip("Random Map Survival Together is a collaborative multiplayer survival mode where players work as a team to survive as long as possible. When any team member gets a goal medal, the entire team gets +3 minutes. When anyone skips, the team loses -1 minute. True teamwork!"); + + UI::AlignTextToFramePadding(); + UI::Text("Club ID:"); + UI::SameLine(); + UI::SetNextItemWidth(150); + PluginSettings::RMC_Together_ClubId = Text::ParseInt(UI::InputText("##RMSTSetClubID", tostring(PluginSettings::RMC_Together_ClubId), false, UI::InputTextFlags::CharsDecimal)); + UI::SameLine(); + UI::Text("Room ID:"); + UI::SameLine(); + UI::SetNextItemWidth(150); + PluginSettings::RMC_Together_RoomId = Text::ParseInt(UI::InputText("##RMSTSetRoomID", tostring(PluginSettings::RMC_Together_RoomId), false, UI::InputTextFlags::CharsDecimal)); + + bool RMST_isServerOK = false; + if (PluginSettings::RMC_Together_ClubId > 0 && PluginSettings::RMC_Together_RoomId > 0) { + RMST_isServerOK = true; + if (UI::Button(Icons::Search + " Auto-detect room")) { + startnew(BRMStartAutoDetectRoomRMST); + } + UI::SameLine(); + if (UI::Button(Icons::InfoCircle + " Help")) { + Renderables::Add(RMSTHelpModalDialog()); + } + } else { + UI::Text("\\$a50" + Icons::ExclamationTriangle + " \\$zPlease set a Club ID and Room ID"); + } + + if (RMST_isServerOK && !TM::IsInServer()) { + UI::BeginDisabled(); + UI::GreyButton(Icons::Heart + " Start Random Map Survival Together"); + UI::Text("\\$a50" + Icons::ExclamationTriangle + " \\$zPlease join the room before continuing"); + UI::EndDisabled(); + } + if (RMST_isServerOK && TM::IsInServer() && UI::GreenButton(Icons::Heart + " Start Random Map Survival Together")){ + selectedGameMode = GameMode::SurvivalTogether; + startnew(CoroutineFunc(SurvivalTogether.StartRMST)); + } + UI::TreePop(); + } #endif #if TMNEXT } else { @@ -220,14 +261,18 @@ namespace RMC UI::Text(RMC::FormatTimer(Objective.RunTime)); UI::PopFont(); } -#if TMNEXT else if (selectedGameMode == GameMode::Together) { Together.RenderGoalMedal(); - UI::HPadding(25); + UI::SameLine(); Together.RenderBelowGoalMedal(); Together.RenderScores(); } -#endif + else if (selectedGameMode == GameMode::SurvivalTogether) { + SurvivalTogether.RenderGoalMedal(); + UI::SameLine(); + SurvivalTogether.RenderBelowGoalMedal(); + SurvivalTogether.RenderScores(); + } } } @@ -237,6 +282,7 @@ namespace RMC else if (selectedGameMode == GameMode::Survival || selectedGameMode == GameMode::SurvivalChaos) Survival.Render(); else if (selectedGameMode == GameMode::Objective) Objective.Render(); else if (selectedGameMode == GameMode::Together) Together.Render(); + else if (selectedGameMode == GameMode::SurvivalTogether) SurvivalTogether.Render(); } void RenderBaseInfos() @@ -251,58 +297,31 @@ namespace RMC #if DEPENDENCY_BETTERROOMMANAGER void BRMStartAutoDetectRoomRMT() { - MXNadeoServicesGlobal::isCheckingRoom = true; autodetectError = false; - autodetectStatus = "Detecting... "; - auto cs = BRM::GetCurrentServerInfo(GetApp()); + autodetectStatus = "Detecting..."; + ClubServerInfo@ cs = MXNadeoServicesGlobal::GetClubServerInfo(); if (cs is null) { - MXNadeoServicesGlobal::roomCheckError = "Couldn't get current server info"; - autodetectError = true; - return; - } - if (cs.clubId <= 0) { - MXNadeoServicesGlobal::roomCheckError = "Could not detect club ID for this server (" + cs.name + " / " + cs.login + ")"; - autodetectError = true; - return; - } - - autodetectStatus = "Found Club ID: " + cs.clubId; - - auto myClubs = BRM::GetMyClubs(); - const Json::Value@ foundClub = null; - - for (uint i = 0; i < myClubs.Length; i++) { - if (cs.clubId == int(myClubs[i]['id'])) { - @foundClub = myClubs[i]; - break; - } - } - - if (foundClub is null) { - MXNadeoServicesGlobal::roomCheckError = "Club not found in your list of clubs (refresh from Better Room Manager if you joined the club recently)."; autodetectError = true; + autodetectStatus = "Error: Could not detect room"; return; } + autodetectStatus = "Found room: " + cs.name; + PluginSettings::RMC_Together_ClubId = cs.clubId; + PluginSettings::RMC_Together_RoomId = cs.roomId; + } - if (!bool(foundClub['isAnyAdmin'])) { - MXNadeoServicesGlobal::roomCheckError = "Club was found but your role isn't enough to edit rooms (refresh from Better Room Manager if this changed recently)."; - autodetectError = true; - return; - } - - autodetectStatus = "Checking for matching rooms..."; - - if (cs.roomId <= 0) { - MXNadeoServicesGlobal::roomCheckError = "Room not found in club"; + void BRMStartAutoDetectRoomRMST() { + autodetectError = false; + autodetectStatus = "Detecting..."; + ClubServerInfo@ cs = MXNadeoServicesGlobal::GetClubServerInfo(); + if (cs is null) { autodetectError = true; + autodetectStatus = "Error: Could not detect room"; return; } - + autodetectStatus = "Found room: " + cs.name; PluginSettings::RMC_Together_ClubId = cs.clubId; PluginSettings::RMC_Together_RoomId = cs.roomId; - - autodetectStatus = "Done"; - MXNadeoServicesGlobal::isCheckingRoom = false; } #endif } \ No newline at end of file diff --git a/src/Utils/DataManager.as b/src/Utils/DataManager.as index 77f7a6d1..d516de29 100644 --- a/src/Utils/DataManager.as +++ b/src/Utils/DataManager.as @@ -56,6 +56,12 @@ namespace DataManager void CreateSaveFile() { string lastLetter = tostring(RMC::selectedGameMode).SubStr(0,1); string gameMode = "RM" + lastLetter; + + // Handle SurvivalTogether mode separately to avoid conflict with Survival + if (RMC::selectedGameMode == RMC::GameMode::SurvivalTogether) { + gameMode = "RMST"; + } + Json::Value SaveFileData = Json::Object(); SaveFileData["PBOnMap"] = -1; SaveFileData["TimerRemaining"] = 0; @@ -74,6 +80,12 @@ namespace DataManager void RemoveCurrentSaveFile() { string lastLetter = tostring(RMC::selectedGameMode).SubStr(0,1); string gameMode = "RM" + lastLetter; + + // Handle SurvivalTogether mode separately to avoid conflict with Survival + if (RMC::selectedGameMode == RMC::GameMode::SurvivalTogether) { + gameMode = "RMST"; + } + IO::Delete(SAVE_DATA_LOCATION + gameMode + ".json"); RMC::CurrentRunData = Json::Object(); } @@ -81,6 +93,12 @@ namespace DataManager void SaveCurrentRunData() { string lastLetter = tostring(RMC::selectedGameMode).SubStr(0,1); string gameMode = "RM" + lastLetter; + + // Handle SurvivalTogether mode separately to avoid conflict with Survival + if (RMC::selectedGameMode == RMC::GameMode::SurvivalTogether) { + gameMode = "RMST"; + } + Json::ToFile(SAVE_DATA_LOCATION + gameMode + ".json", RMC::CurrentRunData); } @@ -126,8 +144,15 @@ namespace DataManager bool LoadRunData() { string lastLetter = tostring(RMC::selectedGameMode).SubStr(0,1); string gameMode = "RM" + lastLetter; - if (IO::FileExists(SAVE_DATA_LOCATION + gameMode + ".json")) { - RMC::CurrentRunData = Json::FromFile(SAVE_DATA_LOCATION + gameMode + ".json"); + + // Handle SurvivalTogether mode separately to avoid conflict with Survival + if (RMC::selectedGameMode == RMC::GameMode::SurvivalTogether) { + gameMode = "RMST"; + } + + string saveFilePath = SAVE_DATA_LOCATION + gameMode + ".json"; + if (IO::FileExists(saveFilePath)) { + RMC::CurrentRunData = Json::FromFile(saveFilePath); if (!EnsureSaveDataIsLoadable(gameMode, RMC::CurrentRunData)) { Log::Error("Deleting the current" + gameMode + " save file, as it is corrupted!"); Log::Error("Please create an issue on github if this repeatedly happens"); diff --git a/src/Utils/MX/Methods/LoadRandomMap.as b/src/Utils/MX/Methods/LoadRandomMap.as index ac4cbbba..9e1e6a5e 100644 --- a/src/Utils/MX/Methods/LoadRandomMap.as +++ b/src/Utils/MX/Methods/LoadRandomMap.as @@ -149,6 +149,13 @@ namespace MX return; } + if (RMC::selectedGameMode == RMC::GameMode::SurvivalTogether && map.ServerSizeExceeded) { + Log::Warn("Map is too big to play in servers, retrying..."); + sleep(1000); + PreloadRandomMap(); + return; + } + // Check if map is uploaded to Nadeo Services (if goal == WorldRecord) if (PluginSettings::RMC_GoalMedal == RMC::Medals[4]) { if (map.OnlineMapId == "" && !MXNadeoServicesGlobal::CheckIfMapExistsAsync(map.MapUid)) { diff --git a/src/Utils/RMC/GlobalProperties.as b/src/Utils/RMC/GlobalProperties.as index 11abcd23..ed0ad868 100644 --- a/src/Utils/RMC/GlobalProperties.as +++ b/src/Utils/RMC/GlobalProperties.as @@ -43,6 +43,7 @@ namespace RMC RMS@ Survival; RMObjective@ Objective; RMT@ Together; + RMST@ SurvivalTogether; enum GameMode { @@ -51,7 +52,8 @@ namespace RMC ChallengeChaos, SurvivalChaos, Objective, - Together + Together, + SurvivalTogether } GameMode selectedGameMode; @@ -72,6 +74,7 @@ namespace RMC @Survival = RMS(); @Objective = RMObjective(); @Together = RMT(); + @SurvivalTogether = RMST(); } string FormatTimer(int time) { diff --git a/src/Utils/RMC/RMST.as b/src/Utils/RMC/RMST.as new file mode 100644 index 00000000..65328cd2 --- /dev/null +++ b/src/Utils/RMC/RMST.as @@ -0,0 +1,554 @@ +class RMST : RMS +{ +#if TMNEXT + string LobbyMapUID = ""; + NadeoServices::ClubRoom@ RMSTRoom; + MX::MapInfo@ currentMap; + MX::MapInfo@ nextMap; + array m_mapPersonalBests; + array m_playerScores; + bool m_CurrentlyLoadingRecords = false; + PBTime@ playerGotGoalActualMap; + uint RMSTTimerMapChange = 0; + bool isSwitchingMap = false; + bool pressedStopButton = false; + bool isFetchingNextMap = false; + array seenMaps; + int SurvivedTimeStart = -1; + int SurvivedTime = -1; + + string GetModeName() override { return "Random Map Survival Together";} + + void DevButtons() override {} + + void Render() override + { + if (UI::IsOverlayShown() || (!UI::IsOverlayShown() && PluginSettings::RMC_AlwaysShowBtns)) { + if (UI::RedButton(Icons::Times + " Stop RMST")) + { + pressedStopButton = true; + RMC::IsRunning = false; + RMC::ShowTimer = false; + RMC::StartTime = -1; + RMC::EndTime = -1; + @nextMap = null; + @MX::preloadedMap = null; +#if DEPENDENCY_BETTERCHAT + BetterChat::SendChatMessage(Icons::Users + " Random Map Survival Together stopped"); + startnew(CoroutineFunc(BetterChatSendLeaderboard)); +#endif + startnew(CoroutineFunc(ResetToLobbyMap)); + } + + RenderCustomSearchWarning(); + UI::Separator(); + } + + RenderTimer(); + if (IS_DEV_MODE) UI::Text(RMC::FormatTimer(RMC::StartTime - SurvivedTimeStart)); + UI::Separator(); + RenderGoalMedal(); + UI::HPadding(25); + RenderBelowGoalMedal(); + RenderMVPPlayer(); + + if (PluginSettings::RMC_DisplayCurrentMap) + { + RenderCurrentMap(); + } + + if (RMC::IsRunning && (UI::IsOverlayShown() || (!UI::IsOverlayShown() && PluginSettings::RMC_AlwaysShowBtns))) { + UI::Separator(); + RenderPlayingButtons(); + UI::Separator(); + DrawPlayerProgress(); + } + } + + void RenderTimer() override + { + UI::PushFont(Fonts::TimerFont); + if (RMC::IsRunning || RMC::EndTime > 0 || RMC::StartTime > 0) { + if (RMC::IsPaused) UI::TextDisabled(RMC::FormatTimer(RMC::EndTime - RMC::StartTime)); + else UI::Text(RMC::FormatTimer(RMC::EndTime - RMC::StartTime)); + + SurvivedTime = RMC::StartTime - SurvivedTimeStart; + if (SurvivedTime > 0 && PluginSettings::RMC_SurvivalShowSurvivedTime) { + UI::PopFont(); + UI::Dummy(vec2(0, 8)); + UI::PushFont(Fonts::HeaderSub); + UI::Text(RMC::FormatTimer(SurvivedTime)); + UI::SetPreviousTooltip("Total time survived"); + } else { + UI::Dummy(vec2(0, 8)); + } + if (PluginSettings::RMC_DisplayMapTimeSpent) { + if(SurvivedTime > 0 && PluginSettings::RMC_SurvivalShowSurvivedTime) { + UI::SameLine(); + } + UI::PushFont(Fonts::HeaderSub); + UI::Text(Icons::Map + " " + RMC::FormatTimer(RMC::TimeSpentMap)); + UI::SetPreviousTooltip("Time spent on this map"); + UI::PopFont(); + } + } else { + UI::TextDisabled(RMC::FormatTimer(TimeLimit())); + UI::Dummy(vec2(0, 8)); + } + + UI::PopFont(); + } + + void StartRMST() + { + m_mapPersonalBests = {}; + m_playerScores = {}; + if (!seenMaps.IsEmpty()) seenMaps.RemoveRange(0, seenMaps.Length); + RMC::GoalMedalCount = 0; + Skips = 0; + RMC::ShowTimer = true; + RMC::ClickedOnSkip = false; + pressedStopButton = false; + Log::Trace("RMST: Getting lobby map UID from the room..."); + MXNadeoServicesGlobal::CheckNadeoRoomAsync(); + yield(); + @RMSTRoom = MXNadeoServicesGlobal::foundRoom; + LobbyMapUID = RMSTRoom.room.currentMapUid; + Log::Trace("RMST: Lobby map UID: " + LobbyMapUID); +#if DEPENDENCY_BETTERCHAT + BetterChat::SendChatMessage(Icons::Users + " Starting Random Map Survival Together. Have Fun!"); + sleep(200); + BetterChat::SendChatMessage(Icons::Users + " Goal medal: " + tostring(PluginSettings::RMC_GoalMedal)); +#endif + SetupMapStart(); + } + + void SetupMapStart() { + RMC::IsStarting = true; + isSwitchingMap = true; + // Fetch a map + Log::Trace("RMST: Fetching a random map..."); + Json::Value res; + try { + res = API::GetAsync(MX::CreateQueryURL())["Results"][0]; + } catch { + Log::Error("ManiaExchange API returned an error, retrying...", true); + SetupMapStart(); + return; + } + @currentMap = MX::MapInfo(res); + Log::Trace("RMST: Random map: " + currentMap.Name + " (" + currentMap.MapId + ")"); + seenMaps.InsertLast(currentMap.MapUid); + UI::ShowNotification(Icons::InfoCircle + " RMST - Information on map switching", "Nadeo prevent sometimes when switching map too often and will not change map.\nIf after 10 seconds the podium screen is not shown, you can start a vote to change to next map in the game pause menu.", Text::ParseHexColor("#420399")); + + if (!MXNadeoServicesGlobal::CheckIfMapExistsAsync(currentMap.MapUid)) { + Log::Trace("RMST: Map is not on NadeoServices, retrying..."); + SetupMapStart(); + return; + } + + DataManager::SaveMapToRecentlyPlayed(currentMap); + MXNadeoServicesGlobal::ClubRoomSetMapAndSwitchAsync(RMSTRoom, currentMap.MapUid); + while (!TM::IsMapCorrect(currentMap.MapUid)) sleep(1000); + MXNadeoServicesGlobal::ClubRoomSetCountdownTimer(RMSTRoom, TimeLimit() / 1000); + while (GetApp().CurrentPlayground is null) yield(); + CGamePlayground@ GamePlayground = cast(GetApp().CurrentPlayground); + while (GamePlayground.GameTerminals.Length < 0) yield(); + while (GamePlayground.GameTerminals[0] is null) yield(); + while (GamePlayground.GameTerminals[0].ControlledPlayer is null) yield(); + CSmPlayer@ player = cast(GamePlayground.GameTerminals[0].ControlledPlayer); + while (player.ScriptAPI is null) yield(); + CSmScriptPlayer@ playerScriptAPI = cast(player.ScriptAPI); + while (playerScriptAPI.Post == 0) yield(); + RMC::StartTime = Time::Now; + RMC::EndTime = RMC::StartTime + TimeLimit(); + SurvivedTimeStart = Time::Now; + RMC::IsPaused = false; + RMC::GotGoalMedalOnCurrentMap = false; + RMC::IsRunning = true; + startnew(CoroutineFunc(TimerYield)); + startnew(CoroutineFunc(UpdateRecordsLoop)); + RMC::TimeSpawnedMap = Time::Now; + isSwitchingMap = false; + RMC::IsStarting = false; + startnew(CoroutineFunc(RMSTFetchNextMap)); + } + + void RMSTFetchNextMap() { + isFetchingNextMap = true; + // Fetch a map + Log::Trace("RMST: Fetching a random map..."); + Json::Value res; + try { + res = API::GetAsync(MX::CreateQueryURL())["Results"][0]; + } catch { + Log::Error("ManiaExchange API returned an error, retrying..."); + RMSTFetchNextMap(); + return; + } + @nextMap = MX::MapInfo(res); + Log::Trace("RMST: Next Random map: " + nextMap.Name + " (" + nextMap.MapId + ")"); + + if (PluginSettings::SkipSeenMaps) { + if (seenMaps.Find(nextMap.MapUid) != -1) { + Log::Trace("Map has been played already, retrying..."); + RMSTFetchNextMap(); + return; + } + + seenMaps.InsertLast(nextMap.MapUid); + } + + if (!MXNadeoServicesGlobal::CheckIfMapExistsAsync(nextMap.MapUid)) { + Log::Trace("RMST: Next map is not on NadeoServices, retrying..."); + @nextMap = null; + RMSTFetchNextMap(); + return; + } + + isFetchingNextMap = false; + } + + void RMSTSwitchMap() { + m_playerScores.SortDesc(); + isSwitchingMap = true; + m_mapPersonalBests = {}; + RMSTTimerMapChange = RMC::EndTime - RMC::StartTime; + RMC::IsPaused = true; + RMC::GotGoalMedalOnCurrentMap = false; + if (nextMap is null && !isFetchingNextMap) RMSTFetchNextMap(); + while (isFetchingNextMap) yield(); + @currentMap = nextMap; + @nextMap = null; + Log::Trace("RMST: Random map: " + currentMap.Name + " (" + currentMap.MapId + ")"); + UI::ShowNotification(Icons::InfoCircle + " RMST - Information on map switching", "Nadeo prevent sometimes when switching map too often and will not change map.\nIf after 10 seconds the podium screen is not shown, you can start a vote to change to next map in the game pause menu.", Text::ParseHexColor("#420399")); + + DataManager::SaveMapToRecentlyPlayed(currentMap); + MXNadeoServicesGlobal::ClubRoomSetMapAndSwitchAsync(RMSTRoom, currentMap.MapUid); + while (!TM::IsMapCorrect(currentMap.MapUid)) sleep(1000); + MXNadeoServicesGlobal::ClubRoomSetCountdownTimer(RMSTRoom, RMSTTimerMapChange / 1000); + while (GetApp().CurrentPlayground is null) yield(); + CGamePlayground@ GamePlayground = cast(GetApp().CurrentPlayground); + while (GamePlayground.GameTerminals.Length < 0) yield(); + while (GamePlayground.GameTerminals[0] is null) yield(); + while (GamePlayground.GameTerminals[0].ControlledPlayer is null) yield(); + CSmPlayer@ player = cast(GamePlayground.GameTerminals[0].ControlledPlayer); + while (player.ScriptAPI is null) yield(); + m_playerScores.SortDesc(); +#if DEPENDENCY_BETTERCHAT + if (m_playerScores.Length > 0) { + RMSTPlayerScore@ p = m_playerScores[0]; + string currentStatChat = Icons::Users + " RMST Team Progress: " + tostring(RMC::GoalMedalCount) + " " + tostring(PluginSettings::RMC_GoalMedal) + " medals - " + Skips + " skips\n"; + currentStatChat += "Current MVP: " + p.name + ": " + p.goals + " " + tostring(PluginSettings::RMC_GoalMedal) + " - " + p.skips + " skips"; + BetterChat::SendChatMessage(currentStatChat); + } +#endif + CSmScriptPlayer@ playerScriptAPI = cast(player.ScriptAPI); + while (playerScriptAPI.Post == 0) yield(); + RMC::EndTime = RMC::EndTime + (Time::Now - RMC::StartTime); + RMC::TimeSpawnedMap = Time::Now; + RMC::IsPaused = false; + isSwitchingMap = false; + RMC::ClickedOnSkip = false; + startnew(CoroutineFunc(RMSTFetchNextMap)); + } + + void ResetToLobbyMap() { + if (LobbyMapUID != "") { + UI::ShowNotification("Returning to lobby map", "Please wait...", Text::ParseHexColor("#993f03")); +#if DEPENDENCY_BETTERCHAT + sleep(200); + BetterChat::SendChatMessage(Icons::Users + " Returning to lobby map..."); +#endif + MXNadeoServicesGlobal::SetMapToClubRoomAsync(RMSTRoom, LobbyMapUID); + if (pressedStopButton) MXNadeoServicesGlobal::ClubRoomSwitchMapAsync(RMSTRoom); + while (!TM::IsMapCorrect(LobbyMapUID)) sleep(1000); + pressedStopButton = false; + } + MXNadeoServicesGlobal::ClubRoomSetCountdownTimer(RMSTRoom, 0); + } + + void TimerYield() override + { + while (RMC::IsRunning){ + yield(); + if (RMC::IsPaused) { + RMC::StartTime = Time::Now - (Time::Now - RMC::StartTime); + RMC::EndTime = Time::Now - (Time::Now - RMC::EndTime); + } else { + CGameCtnChallenge@ currentMapChallenge = cast(GetApp().RootMap); + if (currentMapChallenge !is null) { + CGameCtnChallengeInfo@ currentMapInfo = currentMapChallenge.MapInfo; + if (currentMapInfo !is null) { + RMC::StartTime = Time::Now; + RMC::TimeSpentMap = Time::Now - RMC::TimeSpawnedMap; + SurvivedTime = RMC::StartTime - SurvivedTimeStart; + PendingTimerLoop(); + + if (!pressedStopButton && (RMC::StartTime > RMC::EndTime || !RMC::IsRunning || RMC::EndTime <= 0)) { + RMC::StartTime = -1; + RMC::EndTime = -1; + RMC::IsRunning = false; + RMC::ShowTimer = false; + GameEndNotification(); + @nextMap = null; + @MX::preloadedMap = null; + m_playerScores.SortDesc(); +#if DEPENDENCY_BETTERCHAT + BetterChat::SendChatMessage(Icons::Users + " Random Map Survival Together ended, thanks for playing!"); + sleep(200); + BetterChatSendLeaderboard(); +#endif + ResetToLobbyMap(); + } + } + } + } + } + } + + void PendingTimerLoop() override + { + // Cap timer max + if ((RMC::EndTime - RMC::StartTime) > (PluginSettings::RMC_SurvivalMaxTime-Skips)*60*1000) { + RMC::EndTime = RMC::StartTime + (PluginSettings::RMC_SurvivalMaxTime-Skips)*60*1000; + } + } + + void GotGoalMedalNotification() override + { + Log::Trace("RMST: Got the "+ tostring(PluginSettings::RMC_GoalMedal) + " medal!"); + // In survival mode, add 3 minutes when getting a goal medal + RMC::EndTime += (3*60*1000); + + // Find the player who got the medal for the notification + string playerName = "Someone"; + if (playerGotGoalActualMap !is null) { + playerName = playerGotGoalActualMap.name; + } + + UI::ShowNotification("\\$071" + Icons::Trophy + " Team Goal Medal!", playerName + " got the " + tostring(PluginSettings::RMC_GoalMedal) + " medal! +3 minutes added to team timer!"); + + if (PluginSettings::RMC_AutoSwitch) { + startnew(CoroutineFunc(RMSTSwitchMap)); + } + } + + void SkipButtons() override + { + UI::BeginDisabled(TM::IsPauseMenuDisplayed() || RMC::ClickedOnSkip); + if (UI::Button(Icons::PlayCircleO + " Skip")) { + if (RMC::IsPaused) RMC::IsPaused = false; + Skips += 1; + // In survival mode, lose 1 minute when skipping + RMC::EndTime -= (1*60*1000); + Log::Trace("RMST: Skipping map"); + UI::ShowNotification("Please wait...", "-1 minute for skip"); + startnew(CoroutineFunc(RMSTSwitchMap)); + } + if (UI::OrangeButton(Icons::PlayCircleO + " Skip Broken Map")) { + if (!UI::IsOverlayShown()) UI::ShowOverlay(); + RMC::IsPaused = true; + Renderables::Add(BrokenMapSkipWarnModalDialog()); + } + + if (TM::IsPauseMenuDisplayed()) UI::SetPreviousTooltip("To skip the map, please exit the pause menu."); + UI::EndDisabled(); + } + + void NextMapButton() override + { + if(UI::GreenButton(Icons::Play + " Next map")) { + if (RMC::IsPaused) RMC::IsPaused = false; + Log::Trace("RMST: Next map"); + UI::ShowNotification("Please wait..."); + RMC::EndTime += (3*60*1000); + startnew(CoroutineFunc(RMSTSwitchMap)); + } + } + + void GameEndNotification() override + { + if (RMC::selectedGameMode == RMC::GameMode::SurvivalTogether) { +#if TMNEXT + RMCLeaderAPI::postRMS(RMC::GoalMedalCount, Skips, SurvivedTime, PluginSettings::RMC_GoalMedal); +#endif + UI::ShowNotification( + "\\$0f0Random Map Survival Together ended!", + "You survived with a time of " + RMC::FormatTimer(SurvivedTime) + + ".\nYou got "+ RMC::GoalMedalCount + " " + tostring(PluginSettings::RMC_GoalMedal) + + " medals and " + Skips + " skips." + ); + } + } + + void UpdateRecordsLoop() { + while (RMC::IsRunning) { + if (!m_CurrentlyLoadingRecords && !isSwitchingMap) { + m_CurrentlyLoadingRecords = true; + startnew(CoroutineFunc(UpdateRecords)); + } + sleep(1000); + } + } + + void UpdateRecords() { + if (currentMap is null) { + m_CurrentlyLoadingRecords = false; + return; + } + + array records = MXNadeoServicesGlobal::GetMapRecords(currentMap.MapUid); + if (records.Length == 0) { + m_CurrentlyLoadingRecords = false; + return; + } + + m_mapPersonalBests = records; + + for (uint i = 0; i < m_mapPersonalBests.Length; i++) { + PBTime@ record = m_mapPersonalBests[i]; + if (record is null) continue; + + bool foundPlayer = false; + for (uint j = 0; j < m_playerScores.Length; j++) { + if (m_playerScores[j].wsid == record.wsid) { + foundPlayer = true; + break; + } + } + + if (!foundPlayer) { + m_playerScores.InsertLast(RMSTPlayerScore(record)); + } + + // Collaborative mode: Any player getting the goal medal benefits the entire team + if (record.medal >= RMC::Medals.Find(PluginSettings::RMC_GoalMedal) && !RMC::GotGoalMedalOnCurrentMap) { + @playerGotGoalActualMap = record; + RMC::GotGoalMedalOnCurrentMap = true; + RMC::GoalMedalCount++; + + // Update the specific player's goal count for leaderboard tracking + for (uint j = 0; j < m_playerScores.Length; j++) { + if (m_playerScores[j].wsid == record.wsid) { + m_playerScores[j].AddGoal(); + break; + } + } + + GotGoalMedalNotification(); + } + } + + m_CurrentlyLoadingRecords = false; + } + + void RenderMVPPlayer() { + if (m_playerScores.Length > 0) { + m_playerScores.SortDesc(); + RMSTPlayerScore@ mvp = m_playerScores[0]; + UI::Text("MVP: " + mvp.name + " (" + mvp.goals + " goals, " + mvp.skips + " skips)"); + } + } + + void DrawPlayerProgress() { + if (m_playerScores.Length == 0) return; + + UI::Text("Team Member Contributions:"); + m_playerScores.SortDesc(); + + for (uint i = 0; i < Math::Min(m_playerScores.Length, 10); i++) { + RMSTPlayerScore@ player = m_playerScores[i]; + UI::Text((i+1) + ". " + player.name + ": " + player.goals + " goals, " + player.skips + " skips"); + } + } + + void RenderScores() { + UI::Text("Team Progress: " + tostring(RMC::GoalMedalCount) + " " + tostring(PluginSettings::RMC_GoalMedal) + " medals, " + Skips + " skips"); + + if (m_playerScores.Length == 0) return; + + UI::Text("Individual Contributions:"); + m_playerScores.SortDesc(); + + for (uint i = 0; i < Math::Min(m_playerScores.Length, 5); i++) { + RMSTPlayerScore@ player = m_playerScores[i]; + UI::Text((i+1) + ". " + player.name + ": " + player.goals + " goals, " + player.skips + " skips"); + } + } + + void BetterChatSendLeaderboard() { +#if DEPENDENCY_BETTERCHAT + if (m_playerScores.Length == 0) return; + + m_playerScores.SortDesc(); + string leaderboard = Icons::Users + " RMST Team Results:\n"; + leaderboard += "Team Achievement: " + tostring(RMC::GoalMedalCount) + " " + tostring(PluginSettings::RMC_GoalMedal) + " medals, " + Skips + " skips\n"; + leaderboard += "Individual Contributions:\n"; + + for (uint i = 0; i < Math::Min(m_playerScores.Length, 5); i++) { + RMSTPlayerScore@ player = m_playerScores[i]; + leaderboard += (i+1) + ". " + player.name + ": " + player.goals + " goals, " + player.skips + " skips\n"; + } + + BetterChat::SendChatMessage(leaderboard); +#endif + } + + void RenderCustomSearchWarning() { + // Implementation for custom search warning if needed + // For now, empty implementation + } + + void RenderCurrentMap() { + if (currentMap !is null) { + UI::Text("Current Map: " + currentMap.Name); + UI::Text("Author: " + currentMap.AuthorName); + } + } + + void RenderPlayingButtons() { + SkipButtons(); + if (!PluginSettings::RMC_AutoSwitch) { + NextMapButton(); + } + } + +#else + string GetModeName() override { return "Random Map Survival Together (NOT SUPPORTED ON THIS GAME)";} +#endif +} + +class RMSTPlayerScore { + string name; + string wsid; + int goals; + int skips; + + RMSTPlayerScore(PBTime@ _player) { + wsid = _player.wsid; + name = _player.name; + goals = 0; + skips = 0; + } + + int AddGoal() { + goals = goals + 1; + return goals; + } + + int AddSkip() { + skips = skips + 1; + return skips; + } + + int opCmp(RMSTPlayerScore@ other) const { + if (goals < other.goals) return -1; + if (goals == other.goals) { + if (skips > other.skips) return -1; + if (skips == other.skips) return 0; + return 1; + } + return 1; + } +} \ No newline at end of file From f2df64652011c00cfb755b2c4af67849b0dc07de Mon Sep 17 00:00:00 2001 From: monsonjeremy Date: Thu, 29 May 2025 16:17:35 -0700 Subject: [PATCH 02/10] fixes --- .../ModalDialogs/Modes/RMSTHelpModalDialog.as | 2 +- src/Utils/RMC/RMST.as | 109 +++++++++++------- 2 files changed, 71 insertions(+), 40 deletions(-) diff --git a/src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as b/src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as index 748f7319..90aa4751 100644 --- a/src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as +++ b/src/Interface/ModalDialogs/Modes/RMSTHelpModalDialog.as @@ -85,7 +85,7 @@ class RMSTHelpModalDialog : ModalDialog UI::EndChild(); if (UI::Button("Close")) { - m_shouldClose = true; + m_visible = false; } } } \ No newline at end of file diff --git a/src/Utils/RMC/RMST.as b/src/Utils/RMC/RMST.as index 65328cd2..bd73ff9b 100644 --- a/src/Utils/RMC/RMST.as +++ b/src/Utils/RMC/RMST.as @@ -14,8 +14,6 @@ class RMST : RMS bool pressedStopButton = false; bool isFetchingNextMap = false; array seenMaps; - int SurvivedTimeStart = -1; - int SurvivedTime = -1; string GetModeName() override { return "Random Map Survival Together";} @@ -393,54 +391,87 @@ class RMST : RMS } void UpdateRecords() { - if (currentMap is null) { - m_CurrentlyLoadingRecords = false; - return; - } - - array records = MXNadeoServicesGlobal::GetMapRecords(currentMap.MapUid); - if (records.Length == 0) { - m_CurrentlyLoadingRecords = false; - return; - } - - m_mapPersonalBests = records; - - for (uint i = 0; i < m_mapPersonalBests.Length; i++) { - PBTime@ record = m_mapPersonalBests[i]; - if (record is null) continue; + auto newPBs = GetPlayersPBsMLFeed(); + if (newPBs.Length > 0) // empty arrays are returned on e.g., http error + m_mapPersonalBests = newPBs; + + // Check for goal medals + if (GetApp().RootMap !is null) { + uint objectiveTime = uint(-1); + if (PluginSettings::RMC_GoalMedal == RMC::Medals[3]) objectiveTime = GetApp().RootMap.MapInfo.TMObjective_GoldTime; + if (PluginSettings::RMC_GoalMedal == RMC::Medals[2]) objectiveTime = GetApp().RootMap.MapInfo.TMObjective_SilverTime; + if (PluginSettings::RMC_GoalMedal == RMC::Medals[1]) objectiveTime = GetApp().RootMap.MapInfo.TMObjective_BronzeTime; +#if TMNEXT + if (PluginSettings::RMC_GoalMedal == RMC::Medals[4]) objectiveTime = TM::GetWorldRecordFromCache(GetApp().RootMap.MapInfo.MapUid); +#endif - bool foundPlayer = false; - for (uint j = 0; j < m_playerScores.Length; j++) { - if (m_playerScores[j].wsid == record.wsid) { - foundPlayer = true; - break; + if (m_mapPersonalBests.Length > 0 && !RMC::GotGoalMedalOnCurrentMap) { + for (uint r = 0; r < m_mapPersonalBests.Length; r++) { + PBTime@ record = m_mapPersonalBests[r]; + if (record is null || record.time <= 0) continue; + + // Collaborative mode: Any player getting the goal medal benefits the entire team + if (record.time <= objectiveTime) { + @playerGotGoalActualMap = record; + RMC::GotGoalMedalOnCurrentMap = true; + RMC::GoalMedalCount++; + + // Update the specific player's goal count for leaderboard tracking + for (uint j = 0; j < m_playerScores.Length; j++) { + if (m_playerScores[j].wsid == record.wsid) { + m_playerScores[j].AddGoal(); + break; + } + } + + GotGoalMedalNotification(); + break; // Only count one goal medal per update + } } } + } - if (!foundPlayer) { - m_playerScores.InsertLast(RMSTPlayerScore(record)); - } + m_CurrentlyLoadingRecords = false; + } - // Collaborative mode: Any player getting the goal medal benefits the entire team - if (record.medal >= RMC::Medals.Find(PluginSettings::RMC_GoalMedal) && !RMC::GotGoalMedalOnCurrentMap) { - @playerGotGoalActualMap = record; - RMC::GotGoalMedalOnCurrentMap = true; - RMC::GoalMedalCount++; + array GetPlayersPBsMLFeed() { + array ret; +#if DEPENDENCY_MLFEEDRACEDATA + try { + auto app = cast(GetApp()); + if (app.Network is null || app.Network.ClientManiaAppPlayground is null) return {}; + auto raceData = MLFeed::GetRaceData_V4(); + if (raceData is null) return {}; + auto @players = raceData.SortedPlayers_TimeAttack; + if (players.Length == 0) return {}; + + // Update player scores list + for (uint i = 0; i < players.Length; i++) { + auto player = cast(players[i]); + if (player is null) continue; + if (player.bestTime < 1) continue; + if (player.BestRaceTimes is null || player.BestRaceTimes.Length != raceData.CPsToFinish) continue; + auto pbTime = PBTime(player); + ret.InsertLast(pbTime); - // Update the specific player's goal count for leaderboard tracking + // Ensure player is in our scores list + bool foundPlayer = false; for (uint j = 0; j < m_playerScores.Length; j++) { - if (m_playerScores[j].wsid == record.wsid) { - m_playerScores[j].AddGoal(); + if (m_playerScores[j].wsid == pbTime.wsid) { + foundPlayer = true; break; } } - - GotGoalMedalNotification(); + if (!foundPlayer) { + m_playerScores.InsertLast(RMSTPlayerScore(pbTime)); + } } + ret.SortAsc(); + } catch { + warn("Error while getting player PBs: " + getExceptionInfo()); } - - m_CurrentlyLoadingRecords = false; +#endif + return ret; } void RenderMVPPlayer() { @@ -503,7 +534,7 @@ class RMST : RMS void RenderCurrentMap() { if (currentMap !is null) { UI::Text("Current Map: " + currentMap.Name); - UI::Text("Author: " + currentMap.AuthorName); + UI::Text("Author: " + currentMap.Username); } } From a7a4af6d1edbf523e8cae53f1afbc0136bbba359 Mon Sep 17 00:00:00 2001 From: monsonjeremy Date: Thu, 29 May 2025 16:25:33 -0700 Subject: [PATCH 03/10] fixes again --- src/Interface/Views/RMCMenu.as | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index 783a1ff3..f9a946a9 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -299,29 +299,35 @@ namespace RMC void BRMStartAutoDetectRoomRMT() { autodetectError = false; autodetectStatus = "Detecting..."; - ClubServerInfo@ cs = MXNadeoServicesGlobal::GetClubServerInfo(); - if (cs is null) { + + // Use BRM to get current server info + if (!BRM::IsInAServer(GetApp())) { autodetectError = true; - autodetectStatus = "Error: Could not detect room"; + autodetectStatus = "Error: Not in a server"; return; } - autodetectStatus = "Found room: " + cs.name; - PluginSettings::RMC_Together_ClubId = cs.clubId; - PluginSettings::RMC_Together_RoomId = cs.roomId; + + // For now, show a message that manual setup is required + // This would need proper BRM integration to get club/room IDs + autodetectError = true; + autodetectStatus = "Please set Club ID and Room ID manually"; } void BRMStartAutoDetectRoomRMST() { autodetectError = false; autodetectStatus = "Detecting..."; - ClubServerInfo@ cs = MXNadeoServicesGlobal::GetClubServerInfo(); - if (cs is null) { + + // Use BRM to get current server info + if (!BRM::IsInAServer(GetApp())) { autodetectError = true; - autodetectStatus = "Error: Could not detect room"; + autodetectStatus = "Error: Not in a server"; return; } - autodetectStatus = "Found room: " + cs.name; - PluginSettings::RMC_Together_ClubId = cs.clubId; - PluginSettings::RMC_Together_RoomId = cs.roomId; + + // For now, show a message that manual setup is required + // This would need proper BRM integration to get club/room IDs + autodetectError = true; + autodetectStatus = "Please set Club ID and Room ID manually"; } #endif } \ No newline at end of file From 35eda594158fd5381ce1f440072a427bef21811b Mon Sep 17 00:00:00 2001 From: monsonjeremy Date: Thu, 29 May 2025 17:57:26 -0700 Subject: [PATCH 04/10] revert --- src/Interface/Views/RMCMenu.as | 67 ++++++++++++++++++++++------------ 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index f9a946a9..9b5df495 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -297,37 +297,58 @@ namespace RMC #if DEPENDENCY_BETTERROOMMANAGER void BRMStartAutoDetectRoomRMT() { + MXNadeoServicesGlobal::isCheckingRoom = true; autodetectError = false; - autodetectStatus = "Detecting..."; - - // Use BRM to get current server info - if (!BRM::IsInAServer(GetApp())) { + autodetectStatus = "Detecting... "; + auto cs = BRM::GetCurrentServerInfo(GetApp()); + if (cs is null) { + MXNadeoServicesGlobal::roomCheckError = "Couldn't get current server info"; + autodetectError = true; + return; + } + if (cs.clubId <= 0) { + MXNadeoServicesGlobal::roomCheckError = "Could not detect club ID for this server (" + cs.name + " / " + cs.login + ")"; autodetectError = true; - autodetectStatus = "Error: Not in a server"; return; } - - // For now, show a message that manual setup is required - // This would need proper BRM integration to get club/room IDs - autodetectError = true; - autodetectStatus = "Please set Club ID and Room ID manually"; - } - void BRMStartAutoDetectRoomRMST() { - autodetectError = false; - autodetectStatus = "Detecting..."; - - // Use BRM to get current server info - if (!BRM::IsInAServer(GetApp())) { + autodetectStatus = "Found Club ID: " + cs.clubId; + + auto myClubs = BRM::GetMyClubs(); + const Json::Value@ foundClub = null; + + for (uint i = 0; i < myClubs.Length; i++) { + if (cs.clubId == int(myClubs[i]['id'])) { + @foundClub = myClubs[i]; + break; + } + } + + if (foundClub is null) { + MXNadeoServicesGlobal::roomCheckError = "Club not found in your list of clubs (refresh from Better Room Manager if you joined the club recently)."; autodetectError = true; - autodetectStatus = "Error: Not in a server"; return; } - - // For now, show a message that manual setup is required - // This would need proper BRM integration to get club/room IDs - autodetectError = true; - autodetectStatus = "Please set Club ID and Room ID manually"; + + if (!bool(foundClub['isAnyAdmin'])) { + MXNadeoServicesGlobal::roomCheckError = "Club was found but your role isn't enough to edit rooms (refresh from Better Room Manager if this changed recently)."; + autodetectError = true; + return; + } + + autodetectStatus = "Checking for matching rooms..."; + + if (cs.roomId <= 0) { + MXNadeoServicesGlobal::roomCheckError = "Room not found in club"; + autodetectError = true; + return; + } + + PluginSettings::RMC_Together_ClubId = cs.clubId; + PluginSettings::RMC_Together_RoomId = cs.roomId; + + autodetectStatus = "Done"; + MXNadeoServicesGlobal::isCheckingRoom = false; } #endif } \ No newline at end of file From 692a9e2b52dad7c15ac56988eb04f00d7dd421a5 Mon Sep 17 00:00:00 2001 From: Jeremy Monson <8846086+monsonjeremy@users.noreply.github.com> Date: Thu, 29 May 2025 17:58:05 -0700 Subject: [PATCH 05/10] Update src/Interface/Views/RMCMenu.as --- src/Interface/Views/RMCMenu.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index 9b5df495..9067772d 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -263,7 +263,7 @@ namespace RMC } else if (selectedGameMode == GameMode::Together) { Together.RenderGoalMedal(); - UI::SameLine(); + UI::HPadding(25); Together.RenderBelowGoalMedal(); Together.RenderScores(); } From 9babf165132c8bfe2bc3ca33d1d4d6305efab578 Mon Sep 17 00:00:00 2001 From: monsonjeremy Date: Thu, 29 May 2025 18:00:02 -0700 Subject: [PATCH 06/10] revert tmnext removal --- src/Interface/Views/RMCMenu.as | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index 9b5df495..097992c1 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -261,6 +261,7 @@ namespace RMC UI::Text(RMC::FormatTimer(Objective.RunTime)); UI::PopFont(); } + #if TMNEXT else if (selectedGameMode == GameMode::Together) { Together.RenderGoalMedal(); UI::SameLine(); @@ -269,10 +270,11 @@ namespace RMC } else if (selectedGameMode == GameMode::SurvivalTogether) { SurvivalTogether.RenderGoalMedal(); - UI::SameLine(); + UI::HPadding(25); SurvivalTogether.RenderBelowGoalMedal(); SurvivalTogether.RenderScores(); } + #endif } } From a77243026739453f74654e2263c774fad61f4b8d Mon Sep 17 00:00:00 2001 From: monsonjeremy Date: Thu, 29 May 2025 18:00:45 -0700 Subject: [PATCH 07/10] fix indentation --- src/Interface/Views/RMCMenu.as | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index fd1806fe..27e55205 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -261,7 +261,7 @@ namespace RMC UI::Text(RMC::FormatTimer(Objective.RunTime)); UI::PopFont(); } - #if TMNEXT +#if TMNEXT else if (selectedGameMode == GameMode::Together) { Together.RenderGoalMedal(); UI::HPadding(25); @@ -274,7 +274,7 @@ namespace RMC SurvivalTogether.RenderBelowGoalMedal(); SurvivalTogether.RenderScores(); } - #endif +#endif } } From 70781259ef4c4d38acaafd714cdbf33c3e0f6b9c Mon Sep 17 00:00:00 2001 From: Jeremy Monson <8846086+monsonjeremy@users.noreply.github.com> Date: Thu, 29 May 2025 20:19:20 -0700 Subject: [PATCH 08/10] merge rmst --- src/Interface/Views/RMCMenu.as | 35 ++-------------------------------- 1 file changed, 2 insertions(+), 33 deletions(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index 27e55205..832fc8a3 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -166,38 +166,6 @@ namespace RMC selectedGameMode = GameMode::Together; startnew(CoroutineFunc(Together.StartRMT)); } -#endif - UI::TreePop(); - } - if (Permissions::CreateActivity() && UI::TreeNode(MX_COLOR_STR + Icons::Heart + " \\$zRandom Map Survival Together \\$f33(BETA)")) { - UI::TextDisabled(Icons::InfoCircle + " Hover for infos"); - UI::SetPreviousTooltip("Random Map Survival Together is a collaborative multiplayer survival mode where players work as a team to survive as long as possible. When any team member gets a goal medal, the entire team gets +3 minutes. When anyone skips, the team loses -1 minute. True teamwork!"); - - UI::AlignTextToFramePadding(); - UI::Text("Club ID:"); - UI::SameLine(); - UI::SetNextItemWidth(150); - PluginSettings::RMC_Together_ClubId = Text::ParseInt(UI::InputText("##RMSTSetClubID", tostring(PluginSettings::RMC_Together_ClubId), false, UI::InputTextFlags::CharsDecimal)); - UI::SameLine(); - UI::Text("Room ID:"); - UI::SameLine(); - UI::SetNextItemWidth(150); - PluginSettings::RMC_Together_RoomId = Text::ParseInt(UI::InputText("##RMSTSetRoomID", tostring(PluginSettings::RMC_Together_RoomId), false, UI::InputTextFlags::CharsDecimal)); - - bool RMST_isServerOK = false; - if (PluginSettings::RMC_Together_ClubId > 0 && PluginSettings::RMC_Together_RoomId > 0) { - RMST_isServerOK = true; - if (UI::Button(Icons::Search + " Auto-detect room")) { - startnew(BRMStartAutoDetectRoomRMST); - } - UI::SameLine(); - if (UI::Button(Icons::InfoCircle + " Help")) { - Renderables::Add(RMSTHelpModalDialog()); - } - } else { - UI::Text("\\$a50" + Icons::ExclamationTriangle + " \\$zPlease set a Club ID and Room ID"); - } - if (RMST_isServerOK && !TM::IsInServer()) { UI::BeginDisabled(); UI::GreyButton(Icons::Heart + " Start Random Map Survival Together"); @@ -208,6 +176,7 @@ namespace RMC selectedGameMode = GameMode::SurvivalTogether; startnew(CoroutineFunc(SurvivalTogether.StartRMST)); } +#endif UI::TreePop(); } #endif @@ -353,4 +322,4 @@ namespace RMC MXNadeoServicesGlobal::isCheckingRoom = false; } #endif -} \ No newline at end of file +} From c5b2d1af9530f8384184bb6bce360edce45f0013 Mon Sep 17 00:00:00 2001 From: Jeremy Monson <8846086+monsonjeremy@users.noreply.github.com> Date: Tue, 3 Jun 2025 09:53:23 -0700 Subject: [PATCH 09/10] Update src/Interface/Views/RMCMenu.as Co-authored-by: Philippe --- src/Interface/Views/RMCMenu.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index 832fc8a3..8e577fa1 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -172,7 +172,7 @@ namespace RMC UI::Text("\\$a50" + Icons::ExclamationTriangle + " \\$zPlease join the room before continuing"); UI::EndDisabled(); } - if (RMST_isServerOK && TM::IsInServer() && UI::GreenButton(Icons::Heart + " Start Random Map Survival Together")){ + if (RMT_isServerOK && TM::IsInServer() && UI::GreenButton(Icons::Heart + " Start Random Map Survival Together")){ selectedGameMode = GameMode::SurvivalTogether; startnew(CoroutineFunc(SurvivalTogether.StartRMST)); } From d9a5cb19f3d35d6dca722b0dfa1d4814fb6ee6de Mon Sep 17 00:00:00 2001 From: Jeremy Monson <8846086+monsonjeremy@users.noreply.github.com> Date: Fri, 6 Jun 2025 19:07:36 -0700 Subject: [PATCH 10/10] Update RMCMenu.as Co-authored-by: Philippe --- src/Interface/Views/RMCMenu.as | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Interface/Views/RMCMenu.as b/src/Interface/Views/RMCMenu.as index 8e577fa1..b737e630 100644 --- a/src/Interface/Views/RMCMenu.as +++ b/src/Interface/Views/RMCMenu.as @@ -166,7 +166,7 @@ namespace RMC selectedGameMode = GameMode::Together; startnew(CoroutineFunc(Together.StartRMT)); } - if (RMST_isServerOK && !TM::IsInServer()) { + if (RMT_isServerOK && !TM::IsInServer()) { UI::BeginDisabled(); UI::GreyButton(Icons::Heart + " Start Random Map Survival Together"); UI::Text("\\$a50" + Icons::ExclamationTriangle + " \\$zPlease join the room before continuing");