private static bool shouldDisplaySpeedBerryColumn() { if (CollabModule.Instance.Settings.BestTimeToDisplayInJournal == CollabSettings.BestTimeInJournal.SpeedBerry) { foreach (AreaStats item in SaveData.Instance.Areas_Safe) { // start going through all maps belonging to the collab level set, or to a lobby level set belonging to this collab. bool belongsToCollab = false; if (item.LevelSet == SaveData.Instance.LevelSet) { belongsToCollab = true; } else { string lobby = LobbyHelper.GetLobbyForLevelSet(item.LevelSet); if (lobby != null && AreaData.Get(lobby).GetLevelSet() == SaveData.Instance.LevelSet) { belongsToCollab = true; } } if (belongsToCollab && CollabMapDataProcessor.SpeedBerries.ContainsKey(item.GetSID())) { // this level has a speed berry! return(true); } } } // either we disabled speed berries in the journal, or just went through all maps without finding any... return(false); }
public static void OnSessionCreated() { // transfer the lobby info into the session that was just created. CollabModule.Instance.Session.LobbySID = temporaryLobbySIDHolder; CollabModule.Instance.Session.LobbyRoom = temporaryRoomHolder; CollabModule.Instance.Session.LobbySpawnPointX = temporarySpawnPointHolder.X; CollabModule.Instance.Session.LobbySpawnPointY = temporarySpawnPointHolder.Y; CollabModule.Instance.Session.SaveAndReturnToLobbyAllowed = temporarySaveAllowedHolder; temporaryLobbySIDHolder = null; temporaryRoomHolder = null; temporarySpawnPointHolder = Vector2.Zero; temporarySaveAllowedHolder = false; if (CollabModule.Instance.Session.LobbySID == null) { Session session = SaveData.Instance.CurrentSession_Safe; string lobbySID = LobbyHelper.GetLobbyForLevelSet(session.Area.GetLevelSet()); if (lobbySID == null) { lobbySID = LobbyHelper.GetLobbyForGym(session.Area.GetSID()); } if (lobbySID != null) { Logger.Log(LogLevel.Warn, "CollabUtils2/ReturnToLobbyHelper", $"We are in {session.Area.GetSID()} without a Return to Lobby button! Setting it to {lobbySID}."); CollabModule.Instance.Session.LobbySID = lobbySID; } } }
public GameController(LogUserActivity logUserActivity, MindOfSpaceRepository mindOfSpaceRepository, PlayerRepository playerRepository, LobbyHelper lobbyHelper) { this.playerRepository = playerRepository; this.lobbyHelper = lobbyHelper; this.logUserActivity = logUserActivity; this.mindOfSpaceRepository = mindOfSpaceRepository; }
private IEnumerator Routine() { if (targetSID != null && AreaData.Get(targetSID) == null) { // we are returning to a map that does not exist! Logger.Log(LogLevel.Warn, "CollabUtils2/LevelExitToLobby", $"We are trying to return to a nonexistent lobby: {targetSID}!"); targetSID = null; targetRoom = null; // try detecting the lobby. if we don't succeed, targetSID will stay null and we will return to map. string lobbySID = LobbyHelper.GetLobbyForLevelSet(SaveData.Instance.CurrentSession_Safe.Area.GetLevelSet()); if (lobbySID == null) { lobbySID = LobbyHelper.GetLobbyForGym(SaveData.Instance.CurrentSession_Safe.Area.GetSID()); } if (lobbySID != null) { Logger.Log(LogLevel.Warn, "CollabUtils2/LevelExitToLobby", $"We will be returning to the detected lobby for the current map instead: {lobbySID}."); targetSID = lobbySID; } } Session oldSession = SaveData.Instance.CurrentSession_Safe; Session newSession = null; if (targetSID != null) { newSession = new Session(AreaData.Get(targetSID).ToKey()); newSession.FirstLevel = false; newSession.StartedFromBeginning = false; newSession.Level = targetRoom ?? newSession.MapData.StartLevel().Name; newSession.RespawnPoint = targetRoom == null ? (Vector2?)null : targetSpawnPoint; SaveData.Instance.StartSession(newSession); } UserIO.SaveHandler(file: true, settings: true); while (UserIO.Saving) { yield return(null); } while (SaveLoadIcon.OnScreen) { yield return(null); } SaveData.Instance.CurrentSession_Safe = oldSession; if (targetSID == null) { // failsafe: if there is no lobby to return to, return to map instead. Engine.Scene = new OverworldLoader( exitMode == LevelExit.Mode.Completed ? Overworld.StartMode.AreaComplete : Overworld.StartMode.AreaQuit); } else { new DynData <Session>(newSession)["pauseTimerUntilAction"] = true; LevelEnter.Go(newSession, false); } }
private static bool isPanelShowingLobby(OuiChapterPanel panel = null) { if (overworldWrapper != null) { panel = overworldWrapper.WrappedScene?.GetUI <OuiChapterPanel>(); } if (panel == null) { panel = (Engine.Scene as Overworld)?.GetUI <OuiChapterPanel>(); } return(LobbyHelper.GetLobbyLevelSet(panel?.Area.GetSID() ?? "") != null); }
private static void addCollabVersionToEndscreen(string levelSID) { // add the collab version after the Everest version string collabName = LobbyHelper.GetCollabNameForSID(levelSID); if (collabName != null) { string collabNameFormatted = Dialog.Clean($"endscreen_collabname_{collabName}"); areaCompleteVersionFull.SetValue(null, areaCompleteVersionFull.GetValue(null).ToString() + $"\n{collabNameFormatted} " + (Everest.Modules.Where(m => m.Metadata?.Name == collabName).FirstOrDefault()?.Metadata.Version ?? new Version(0, 0))); isCollabEndscreen = true; } }
private static void ModStrawberriesCounterRender(ILContext il) { ILCursor cursor = new ILCursor(il); while (cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdstr("collectables/goldberry"))) { Logger.Log("CollabUtils2/InGameOverworldHelper", $"Changing strawberry icon w/ silver one at {cursor.Index} in IL for StrawberriesCounter.Render"); cursor.EmitDelegate <Func <string, string> >(orig => { if (isPanelShowingLobby()) { return("CollabUtils2/rainbowberry"); } if (Engine.Scene == overworldWrapper?.Scene && !LobbyHelper.IsHeartSide(overworldWrapper.WrappedScene?.GetUI <OuiChapterPanel>().Area.GetSID())) { return("CollabUtils2/silverberry"); } return(orig); }); } }
private static void OnChapterPanelUpdateStats(On.Celeste.OuiChapterPanel.orig_UpdateStats orig, OuiChapterPanel self, bool wiggle, bool?overrideStrawberryWiggle, bool?overrideDeathWiggle, bool?overrideHeartWiggle) { orig(self, wiggle, overrideStrawberryWiggle, overrideDeathWiggle, overrideHeartWiggle); DeathsCounter deathsCounter = new DynData <OuiChapterPanel>(self).Get <DeathsCounter>("deaths"); if (Engine.Scene == overworldWrapper?.Scene) { // within lobbies, death counts always show up, even if you didn't beat the map yet. AreaModeStats areaModeStats = self.DisplayedStats.Modes[(int)self.Area.Mode]; deathsCounter.Visible = areaModeStats.Deaths > 0 && !AreaData.Get(self.Area).Interlude_Safe; } // mod the death icon: for the path, use the current level set, or for lobbies, the lobby's matching level set. string pathToSkull = "CollabUtils2/skulls/" + self.Area.GetLevelSet(); if (LobbyHelper.GetLobbyLevelSet(self.Area.GetSID()) != null) { pathToSkull = "CollabUtils2/skulls/" + LobbyHelper.GetLobbyLevelSet(self.Area.GetSID()); } if (GFX.Gui.Has(pathToSkull)) { new DynData <DeathsCounter>(deathsCounter)["icon"] = GFX.Gui[pathToSkull]; } new DynData <DeathsCounter>(deathsCounter)["modifiedByCollabUtils"] = GFX.Gui.Has(pathToSkull); if (isPanelShowingLobby(self) || Engine.Scene == overworldWrapper?.Scene) { // turn strawberry counter into golden if there only are golden berries in the map MapData mapData = AreaData.Get(self.Area).Mode[0].MapData; if (mapData.GetDetectedStrawberriesIncludingUntracked() == mapData.Goldenberries.Count) { StrawberriesCounter strawberriesCounter = new DynData <OuiChapterPanel>(self).Get <StrawberriesCounter>("strawberries"); strawberriesCounter.Golden = true; strawberriesCounter.ShowOutOf = false; } } }
public static List <OuiJournalCollabProgressInLobby> GeneratePages(OuiJournal journal, string levelSet) { List <OuiJournalCollabProgressInLobby> pages = new List <OuiJournalCollabProgressInLobby>(); int rowCount = 0; OuiJournalCollabProgressInLobby currentPage = new OuiJournalCollabProgressInLobby(journal, levelSet); pages.Add(currentPage); int totalStrawberries = 0; int totalDeaths = 0; int sumOfBestDeaths = 0; long totalTime = 0; long sumOfBestTimes = 0; bool allMapsDone = true; bool allLevelsDone = true; bool allSpeedBerriesDone = true; string heartTexture = MTN.Journal.Has("CollabUtils2Hearts/" + levelSet) ? "CollabUtils2Hearts/" + levelSet : "heartgem0"; foreach (AreaStats item in SaveData.Instance.Areas_Safe) { AreaData areaData = AreaData.Get(item.ID_Safe); if (!areaData.Interlude_Safe) { if (LobbyHelper.IsHeartSide(areaData.GetSID())) { if (allMapsDone || item.TotalTimePlayed > 0) { // add a separator, like the one between regular maps and Farewell currentPage.table.AddRow(); } else { // all maps weren't complete yet, and the heart side was never accessed: hide the heart side for now. continue; } } string strawberryText = null; if (areaData.Mode[0].TotalStrawberries > 0 || item.TotalStrawberries > 0) { strawberryText = item.TotalStrawberries.ToString(); if (item.Modes[0].Completed) { strawberryText = strawberryText + "/" + areaData.Mode[0].TotalStrawberries; } } else { strawberryText = "-"; } Row row = currentPage.table.AddRow() .Add(new TextCell(Dialog.Clean(areaData.Name), new Vector2(1f, 0.5f), 0.6f, currentPage.TextColor)) .Add(null) .Add(new IconCell(item.Modes[0].HeartGem ? heartTexture : "dot")) .Add(new TextCell(strawberryText, currentPage.TextJustify, 0.5f, currentPage.TextColor)); if (item.TotalTimePlayed > 0) { row.Add(new TextCell(Dialog.Deaths(item.Modes[0].Deaths), currentPage.TextJustify, 0.5f, currentPage.TextColor)); } else { row.Add(new IconCell("dot")); } AreaStats stats = SaveData.Instance.GetAreaStatsFor(areaData.ToKey()); if (CollabMapDataProcessor.SilverBerries.TryGetValue(areaData.GetLevelSet(), out Dictionary <string, EntityID> levelSetBerries) && levelSetBerries.TryGetValue(areaData.GetSID(), out EntityID berryID) && stats.Modes[0].Strawberries.Contains(berryID)) { // silver berry was obtained! row.Add(new IconCell("CollabUtils2/silver_strawberry")); } else if (stats.Modes[0].Strawberries.Any(berry => areaData.Mode[0].MapData.Goldenberries.Any(golden => golden.ID == berry.ID && golden.Level.Name == berry.Level))) { // golden berry was obtained! row.Add(new IconCell("CollabUtils2/golden_strawberry")); } else if (item.Modes[0].SingleRunCompleted) { row.Add(new TextCell(Dialog.Deaths(item.Modes[0].BestDeaths), currentPage.TextJustify, 0.5f, currentPage.TextColor)); sumOfBestDeaths += item.Modes[0].BestDeaths; } else { // the player didn't ever do a single run. row.Add(new IconCell("dot")); allLevelsDone = false; } if (item.TotalTimePlayed > 0) { row.Add(new TextCell(Dialog.Time(item.TotalTimePlayed), currentPage.TextJustify, 0.5f, currentPage.TextColor)); } else { row.Add(new IconCell("dot")); } if (CollabModule.Instance.Settings.BestTimeToDisplayInJournal == CollabSettings.BestTimeInJournal.SpeedBerry) { if (CollabMapDataProcessor.SpeedBerries.TryGetValue(item.GetSID(), out CollabMapDataProcessor.SpeedBerryInfo speedBerryInfo) && CollabModule.Instance.SaveData.SpeedBerryPBs.TryGetValue(item.GetSID(), out long speedBerryPB)) { row.Add(new TextCell(Dialog.Time(speedBerryPB), currentPage.TextJustify, 0.5f, getRankColor(speedBerryInfo, speedBerryPB))); row.Add(new IconCell(getRankIcon(speedBerryInfo, speedBerryPB))); sumOfBestTimes += speedBerryPB; } else { row.Add(new IconCell("dot")).Add(null); allSpeedBerriesDone = false; } } else { if (item.Modes[0].BestTime > 0f) { row.Add(new TextCell(Dialog.Time(item.Modes[0].BestTime), currentPage.TextJustify, 0.5f, currentPage.TextColor)).Add(null); sumOfBestTimes += item.Modes[0].BestTime; } else { row.Add(new IconCell("dot")).Add(null); allSpeedBerriesDone = false; } } totalStrawberries += item.TotalStrawberries; totalDeaths += item.Modes[0].Deaths; totalTime += item.TotalTimePlayed; if (!item.Modes[0].HeartGem) { allMapsDone = false; } rowCount++; if (rowCount > 11) { // split the next zones into another page. rowCount = 0; currentPage = new OuiJournalCollabProgressInLobby(journal, levelSet); pages.Add(currentPage); } } } if (currentPage.table.Rows > 1) { currentPage.table.AddRow(); Row totalsRow = currentPage.table.AddRow() .Add(new TextCell(Dialog.Clean("journal_totals"), new Vector2(1f, 0.5f), 0.7f, currentPage.TextColor)).Add(null) .Add(null) .Add(new TextCell(totalStrawberries.ToString(), currentPage.TextJustify, 0.6f, currentPage.TextColor)) .Add(new TextCell(Dialog.Deaths(totalDeaths), currentPage.TextJustify, 0.6f, currentPage.TextColor)) .Add(new TextCell(allLevelsDone ? Dialog.Deaths(sumOfBestDeaths) : "-", currentPage.TextJustify, 0.6f, currentPage.TextColor)) .Add(new TextCell(Dialog.Time(totalTime), currentPage.TextJustify, 0.6f, currentPage.TextColor)) .Add(new TextCell(allSpeedBerriesDone ? Dialog.Time(sumOfBestTimes) : "-", currentPage.TextJustify, 0.6f, currentPage.TextColor)).Add(null); for (int l = 1; l < SaveData.Instance.UnlockedModes; l++) { totalsRow.Add(null); } totalsRow.Add(new TextCell(Dialog.Time(SaveData.Instance.Time), currentPage.TextJustify, 0.6f, currentPage.TextColor)); currentPage.table.AddRow(); } return(pages); }
public OuiJournalCollabProgressInOverworld(OuiJournal journal) : base(journal) { bool displaySpeedBerryColumn = shouldDisplaySpeedBerryColumn(); PageTexture = "page"; table = new Table() .AddColumn(new TextCell(Dialog.Clean("journal_progress"), new Vector2(0f, 0.5f), 1f, Color.Black * 0.7f, 420f)) .AddColumn(new EmptyCell(20f)) .AddColumn(new EmptyCell(64f)) .AddColumn(new IconCell("strawberry", 150f)) .AddColumn(new IconCell("skullblue", 100f)) .AddColumn(new IconCell("CollabUtils2MinDeaths/SpringCollab2020/1-Beginner", 100f)); if (OuiJournalCollabProgressDashCountMod.IsDashCountEnabled()) { table.AddColumn(new IconCell("max480/DashCountMod/dashes", 80f)); } table .AddColumn(new IconCell("time", 220f)) .AddColumn(new IconCell("CollabUtils2/speed_berry_pbs_heading", 220f)) .AddColumn(new EmptyCell(30f)); int totalStrawberries = 0; int totalDeaths = 0; int sumOfBestDeaths = 0; int sumOfBestDashes = 0; long totalTime = 0; long sumOfBestTimes = 0; bool allLevelsDone = true; bool allSpeedBerriesDone = true; bool allMapsCompletedInSingleRun = true; foreach (AreaStats item in SaveData.Instance.Areas_Safe) { AreaData areaData = AreaData.Get(item.ID_Safe); if (areaData.GetLevelSet() == SaveData.Instance.LevelSet) { string lobbyMapLevelSetName = LobbyHelper.GetLobbyLevelSet(areaData.GetSID()); LevelSetStats lobbyMapLevelSet = null; if (lobbyMapLevelSetName != null) { lobbyMapLevelSet = SaveData.Instance.GetLevelSetStatsFor(lobbyMapLevelSetName); } int lobbyStrawberries = item.TotalStrawberries; int lobbyTotalStrawberries = areaData.Mode[0].TotalStrawberries; int lobbyDeaths = item.Modes[0].Deaths; int lobbySumOfBestDeaths = 0; int lobbySumOfBestDashes = OuiJournalCollabProgressDashCountMod.DisplaysTotalDashes() ? OuiJournalCollabProgressDashCountMod.GetLevelDashesForJournalProgress(item) : 0; long lobbyTotalTime = item.TotalTimePlayed; long lobbySumOfBestTimes = 0; bool lobbyLevelsDone = true; int lobbySpeedBerryLevel = 1; bool lobbySilverBerriesObtained = true; bool lobbyAllMapsCompletedInSingleRun = true; foreach (AreaStats lobbyMap in lobbyMapLevelSet?.Areas ?? new List <AreaStats>()) { AreaData lobbyAreaData = AreaData.Get(lobbyMap.ID_Safe); lobbyStrawberries += lobbyMap.TotalStrawberries; lobbyTotalStrawberries += lobbyAreaData.Mode[0].TotalStrawberries; lobbyDeaths += lobbyMap.Modes[0].Deaths; lobbyTotalTime += lobbyMap.TotalTimePlayed; lobbyAllMapsCompletedInSingleRun &= lobbyMap.Modes[0].SingleRunCompleted; if (displaySpeedBerryColumn) { if (CollabMapDataProcessor.SpeedBerries.TryGetValue(lobbyMap.GetSID(), out CollabMapDataProcessor.SpeedBerryInfo mapSpeedBerryInfo) && CollabModule.Instance.SaveData.SpeedBerryPBs.TryGetValue(lobbyMap.GetSID(), out long mapSpeedBerryPB)) { lobbySpeedBerryLevel = Math.Max(getRankLevel(mapSpeedBerryInfo, mapSpeedBerryPB), lobbySpeedBerryLevel); lobbySumOfBestTimes += mapSpeedBerryPB; } else { lobbySpeedBerryLevel = 4; } } else { if (lobbyMap.Modes[0].BestTime > 0f) { lobbySumOfBestTimes += lobbyMap.Modes[0].BestTime; } else { lobbySpeedBerryLevel = 4; } } bool goldenBerryNotObtained = !lobbyMap.Modes[0].Strawberries.Any(berry => lobbyAreaData.Mode[0].MapData.Goldenberries.Any(golden => golden.ID == berry.ID && golden.Level.Name == berry.Level)); bool silverBerryNotObtained = !CollabMapDataProcessor.SilverBerries.TryGetValue(lobbyMap.GetLevelSet(), out Dictionary <string, EntityID> levelSetBerries) || !levelSetBerries.TryGetValue(lobbyMap.GetSID(), out EntityID berryID) || !lobbyMap.Modes[0].Strawberries.Contains(berryID); if (goldenBerryNotObtained && silverBerryNotObtained) { lobbySilverBerriesObtained = false; lobbySumOfBestDeaths += lobbyMap.Modes[0].BestDeaths; } lobbySumOfBestDashes += OuiJournalCollabProgressDashCountMod.GetLevelDashesForJournalProgress(lobbyMap); if (!lobbyMap.Modes[0].HeartGem) { lobbyLevelsDone = false; } } string strawberryText = null; if (lobbyStrawberries > 0 || lobbyTotalStrawberries > 0) { strawberryText = lobbyStrawberries.ToString(); if (lobbyLevelsDone) { strawberryText = strawberryText + "/" + lobbyTotalStrawberries; } } else { strawberryText = "-"; } string heartTexturePath = lobbyMapLevelSetName ?? areaData.GetSID(); string heartTexture = MTN.Journal.Has("CollabUtils2Hearts/" + heartTexturePath) ? "CollabUtils2Hearts/" + heartTexturePath : "heartgem0"; string areaName = Dialog.Clean(areaData.Name); if (Dialog.Has(areaData.Name + "_journal")) { areaName = Dialog.Clean(areaData.Name + "_journal"); } Row row = table.AddRow() .Add(new TextCell(areaName, new Vector2(1f, 0.5f), 0.6f, TextColor)) .Add(null) .Add(new IconCell(item.Modes[0].HeartGem ? heartTexture : "dot")) .Add(new TextCell(strawberryText, TextJustify, 0.5f, TextColor)); if (lobbyTotalTime > 0) { row.Add(new TextCell(Dialog.Deaths(lobbyDeaths), TextJustify, 0.5f, TextColor)); } else { row.Add(new IconCell("dot")); } if (lobbyLevelsDone) { AreaStats stats = SaveData.Instance.GetAreaStatsFor(areaData.ToKey()); if (lobbyMapLevelSet == null) { row.Add(new TextCell(Dialog.Deaths(item.Modes[0].BestDeaths), TextJustify, 0.5f, TextColor)); sumOfBestDeaths += item.Modes[0].BestDeaths; } else if (lobbySilverBerriesObtained) { row.Add(new IconCell("CollabUtils2/golden_strawberry")); } else if (lobbyAllMapsCompletedInSingleRun) { row.Add(new TextCell(Dialog.Deaths(lobbySumOfBestDeaths), TextJustify, 0.5f, TextColor)); } else { row.Add(new IconCell("dot")); } } else { row.Add(new IconCell("dot")); allLevelsDone = false; } if (OuiJournalCollabProgressDashCountMod.IsDashCountEnabled()) { if (lobbyMapLevelSet == null) { if ((OuiJournalCollabProgressDashCountMod.DisplaysTotalDashes() && item.TotalTimePlayed > 0) || item.Modes[0].SingleRunCompleted) { row.Add(new TextCell(Dialog.Deaths(OuiJournalCollabProgressDashCountMod.GetLevelDashesForJournalProgress(item)), TextJustify, 0.5f, TextColor)); sumOfBestDashes += OuiJournalCollabProgressDashCountMod.GetLevelDashesForJournalProgress(item); } else { row.Add(new IconCell("dot")); } } else if ((OuiJournalCollabProgressDashCountMod.DisplaysTotalDashes() && item.TotalTimePlayed > 0) || lobbyAllMapsCompletedInSingleRun) { row.Add(new TextCell(Dialog.Deaths(lobbySumOfBestDashes), TextJustify, 0.5f, TextColor)); } else { row.Add(new IconCell("dot")); } } if (lobbyTotalTime > 0) { row.Add(new TextCell(Dialog.Time(lobbyTotalTime), TextJustify, 0.5f, TextColor)); } else { row.Add(new IconCell("dot")); } if (lobbyMapLevelSet == null) { row.Add(new TextCell("-", TextJustify, 0.5f, TextColor)).Add(null); } else if (lobbySpeedBerryLevel < 4) { if (displaySpeedBerryColumn) { row.Add(new TextCell(Dialog.Time(lobbySumOfBestTimes), TextJustify, 0.5f, getRankColor(lobbySpeedBerryLevel))); row.Add(new IconCell(getRankIcon(lobbySpeedBerryLevel))); sumOfBestTimes += lobbySumOfBestTimes; } else { row.Add(new TextCell(Dialog.Time(lobbySumOfBestTimes), TextJustify, 0.5f, TextColor)).Add(null); sumOfBestTimes += lobbySumOfBestTimes; } } else { row.Add(new IconCell("dot")).Add(null); allSpeedBerriesDone = false; } totalStrawberries += lobbyStrawberries; totalDeaths += lobbyDeaths; sumOfBestDeaths += lobbySumOfBestDeaths; sumOfBestDashes += lobbySumOfBestDashes; totalTime += lobbyTotalTime; allMapsCompletedInSingleRun &= lobbyAllMapsCompletedInSingleRun; if (!lobbyLevelsDone) { allLevelsDone = false; } } } table.AddRow(); Row totalsRow = table.AddRow() .Add(new TextCell(Dialog.Clean("journal_totals"), new Vector2(1f, 0.5f), 0.7f, TextColor)).Add(null) .Add(null) .Add(new TextCell(totalStrawberries.ToString(), TextJustify, 0.6f, TextColor)) .Add(new TextCell(Dialog.Deaths(totalDeaths), TextJustify, 0.6f, TextColor)) .Add(new TextCell(allLevelsDone && allMapsCompletedInSingleRun ? Dialog.Deaths(sumOfBestDeaths) : "-", TextJustify, 0.6f, TextColor)); if (OuiJournalCollabProgressDashCountMod.IsDashCountEnabled()) { totalsRow.Add(new TextCell(OuiJournalCollabProgressDashCountMod.DisplaysTotalDashes() || (allLevelsDone && allMapsCompletedInSingleRun) ? Dialog.Deaths(sumOfBestDashes) : "-", TextJustify, 0.6f, TextColor)); } totalsRow .Add(new TextCell(Dialog.Time(totalTime), TextJustify, 0.6f, TextColor)) .Add(new TextCell(allSpeedBerriesDone ? Dialog.Time(sumOfBestTimes) : "-", TextJustify, 0.6f, TextColor)).Add(null); for (int l = 1; l < SaveData.Instance.UnlockedModes; l++) { totalsRow.Add(null); } totalsRow.Add(new TextCell(Dialog.Time(SaveData.Instance.Time), TextJustify, 0.6f, TextColor)); table.AddRow(); }
public static List <OuiJournalCollabProgressInLobby> GeneratePages(OuiJournal journal, string levelSet, bool showOnlyDiscovered) { bool displaySpeedBerryColumn = shouldDisplaySpeedBerryColumn(levelSet); List <OuiJournalCollabProgressInLobby> pages = new List <OuiJournalCollabProgressInLobby>(); int rowCount = 0; int totalStrawberries = 0; int totalDeaths = 0; int sumOfBestDeaths = 0; int sumOfBestDashes = 0; long totalTime = 0; long sumOfBestTimes = 0; bool allMapsDone = true; bool allLevelsDone = true; bool allSpeedBerriesDone = true; string heartTexture = MTN.Journal.Has("CollabUtils2Hearts/" + levelSet) ? "CollabUtils2Hearts/" + levelSet : "heartgem0"; int mapsPerPage = 12; int mapAmount = SaveData.Instance.Areas_Safe.Where(item => !AreaData.Get(item.ID_Safe).Interlude_Safe && (!showOnlyDiscovered || item.TotalTimePlayed > 0)).Count(); // we want to display the map icons if they're not actually all the same. ^^' bool displayIcons = AreaData.Areas .Where(area => !area.Interlude_Safe) .Select(area => area.Icon) .Distinct() .Count() > 1; OuiJournalCollabProgressInLobby currentPage = new OuiJournalCollabProgressInLobby(journal, levelSet, displayIcons); pages.Add(currentPage); if (mapAmount >= mapsPerPage) { // we want the last page to contain at least 2 maps. while (mapAmount % mapsPerPage < 2) { mapsPerPage--; } } List <AreaStats> sortedMaps = new List <AreaStats>(SaveData.Instance.Areas_Safe) .Where(map => !AreaData.Get(map).Interlude_Safe) .ToList(); // sort maps by icon name if all of their icons start with [number]-... // because then we know the ordering is intentional (and not accidental like easy > hard > medium) Regex startsWithNumber = new Regex(".*/[0-9]+-.*"); if (sortedMaps.Select(map => AreaData.Get(map).Icon ?? "").All(icon => startsWithNumber.IsMatch(icon))) { sortedMaps.Sort((a, b) => { AreaData adata = AreaData.Get(a); AreaData bdata = AreaData.Get(b); bool aHeartSide = LobbyHelper.IsHeartSide(a.GetSID()); bool bHeartSide = LobbyHelper.IsHeartSide(b.GetSID()); // heart sides should appear last. if (aHeartSide && !bHeartSide) { return(1); } if (!aHeartSide && bHeartSide) { return(-1); } // sort by icon name, then by map bin name. return(adata.Icon == bdata.Icon ? adata.Name.CompareTo(bdata.Name) : adata.Icon.CompareTo(bdata.Icon)); }); } foreach (AreaStats item in sortedMaps) { AreaData areaData = AreaData.Get(item.ID_Safe); if (LobbyHelper.IsHeartSide(areaData.GetSID())) { if (allMapsDone || item.TotalTimePlayed > 0) { // add a separator, like the one between regular maps and Farewell currentPage.table.AddRow(); } else { // all maps weren't complete yet, and the heart side was never accessed: hide the heart side for now. continue; } } if (showOnlyDiscovered && item.TotalTimePlayed <= 0) { // skip the map, because it was not discovered yet. // since it wasn't discovered, we can already say all maps weren't done though. allMapsDone = false; allLevelsDone = false; allSpeedBerriesDone = false; continue; } string strawberryText = null; if (areaData.Mode[0].TotalStrawberries > 0 || item.TotalStrawberries > 0) { strawberryText = item.TotalStrawberries.ToString(); if (item.Modes[0].Completed) { strawberryText = strawberryText + "/" + areaData.Mode[0].TotalStrawberries; } } else { strawberryText = "-"; } Row row = currentPage.table.AddRow() .Add(new TextCell(Dialog.Clean(areaData.Name), new Vector2(1f, 0.5f), 0.6f, currentPage.TextColor)); if (displayIcons) { row.Add(null).Add(new IconCellFromGui(GFX.Gui.Has(areaData.Icon) ? areaData.Icon : "areas/null", 60f, 50f)); } row.Add(null) .Add(new IconCell(item.Modes[0].HeartGem ? heartTexture : "dot")) .Add(new TextCell(strawberryText, currentPage.TextJustify, 0.5f, currentPage.TextColor)); if (item.TotalTimePlayed > 0) { row.Add(new TextCell(Dialog.Deaths(item.Modes[0].Deaths), currentPage.TextJustify, 0.5f, currentPage.TextColor)); } else { row.Add(new IconCell("dot")); } AreaStats stats = SaveData.Instance.GetAreaStatsFor(areaData.ToKey()); if (CollabMapDataProcessor.SilverBerries.TryGetValue(areaData.GetLevelSet(), out Dictionary <string, EntityID> levelSetBerries) && levelSetBerries.TryGetValue(areaData.GetSID(), out EntityID berryID) && stats.Modes[0].Strawberries.Contains(berryID)) { // silver berry was obtained! row.Add(new IconCell("CollabUtils2/silver_strawberry")); } else if (stats.Modes[0].Strawberries.Any(berry => areaData.Mode[0].MapData.Goldenberries.Any(golden => golden.ID == berry.ID && golden.Level.Name == berry.Level))) { // golden berry was obtained! row.Add(new IconCell("CollabUtils2/golden_strawberry")); } else if (item.Modes[0].SingleRunCompleted) { row.Add(new TextCell(Dialog.Deaths(item.Modes[0].BestDeaths), currentPage.TextJustify, 0.5f, currentPage.TextColor)); sumOfBestDeaths += item.Modes[0].BestDeaths; } else { // the player didn't ever do a single run. row.Add(new IconCell("dot")); allLevelsDone = false; } if (OuiJournalCollabProgressDashCountMod.IsDashCountEnabled()) { if ((OuiJournalCollabProgressDashCountMod.DisplaysTotalDashes() && item.TotalTimePlayed > 0) || item.Modes[0].SingleRunCompleted) { row.Add(new TextCell(Dialog.Deaths(OuiJournalCollabProgressDashCountMod.GetLevelDashesForJournalProgress(item)), currentPage.TextJustify, 0.5f, currentPage.TextColor)); sumOfBestDashes += OuiJournalCollabProgressDashCountMod.GetLevelDashesForJournalProgress(item); } else { row.Add(new IconCell("dot")); } } if (item.TotalTimePlayed > 0) { row.Add(new TextCell(Dialog.Time(item.TotalTimePlayed), currentPage.TextJustify, 0.5f, currentPage.TextColor)); } else { row.Add(new IconCell("dot")); } if (displaySpeedBerryColumn) { if (CollabMapDataProcessor.SpeedBerries.TryGetValue(item.GetSID(), out CollabMapDataProcessor.SpeedBerryInfo speedBerryInfo) && CollabModule.Instance.SaveData.SpeedBerryPBs.TryGetValue(item.GetSID(), out long speedBerryPB)) { row.Add(new TextCell(Dialog.Time(speedBerryPB), currentPage.TextJustify, 0.5f, getRankColor(speedBerryInfo, speedBerryPB))); row.Add(new IconCell(getRankIcon(speedBerryInfo, speedBerryPB))); sumOfBestTimes += speedBerryPB; } else { row.Add(new IconCell("dot")).Add(null); allSpeedBerriesDone = false; } } else { if (item.Modes[0].BestTime > 0f) { row.Add(new TextCell(Dialog.Time(item.Modes[0].BestTime), currentPage.TextJustify, 0.5f, currentPage.TextColor)).Add(null); sumOfBestTimes += item.Modes[0].BestTime; } else { row.Add(new IconCell("dot")).Add(null); allSpeedBerriesDone = false; } } totalStrawberries += item.TotalStrawberries; totalDeaths += item.Modes[0].Deaths; totalTime += item.TotalTimePlayed; if (!item.Modes[0].HeartGem) { allMapsDone = false; } rowCount++; if (rowCount >= mapsPerPage) { // split the next zones into another page. rowCount = 0; currentPage = new OuiJournalCollabProgressInLobby(journal, levelSet, displayIcons); pages.Add(currentPage); } } if (currentPage.table.Rows > 1) { currentPage.table.AddRow(); Row totalsRow = currentPage.table.AddRow() .Add(new TextCell(Dialog.Clean("journal_totals"), new Vector2(1f, 0.5f), 0.7f, currentPage.TextColor)).Add(null); if (displayIcons) { totalsRow.Add(null).Add(null); } totalsRow.Add(null) .Add(new TextCell(totalStrawberries.ToString(), currentPage.TextJustify, 0.6f, currentPage.TextColor)) .Add(new TextCell(Dialog.Deaths(totalDeaths), currentPage.TextJustify, 0.6f, currentPage.TextColor)) .Add(new TextCell(allLevelsDone ? Dialog.Deaths(sumOfBestDeaths) : "-", currentPage.TextJustify, 0.6f, currentPage.TextColor)); if (OuiJournalCollabProgressDashCountMod.IsDashCountEnabled()) { totalsRow.Add(new TextCell(OuiJournalCollabProgressDashCountMod.DisplaysTotalDashes() || allLevelsDone ? Dialog.Deaths(sumOfBestDashes) : "-", currentPage.TextJustify, 0.6f, currentPage.TextColor)); } totalsRow .Add(new TextCell(Dialog.Time(totalTime), currentPage.TextJustify, 0.6f, currentPage.TextColor)) .Add(new TextCell(allSpeedBerriesDone ? Dialog.Time(sumOfBestTimes) : "-", currentPage.TextJustify, 0.6f, currentPage.TextColor)).Add(null); for (int l = 1; l < SaveData.Instance.UnlockedModes; l++) { totalsRow.Add(null); } totalsRow.Add(new TextCell(Dialog.Time(SaveData.Instance.Time), currentPage.TextJustify, 0.6f, currentPage.TextColor)); currentPage.table.AddRow(); } return(pages); }
private static void ModOuiChapterPanelRender(ILContext il) { ILCursor cursor = new ILCursor(il); // 1. Swap the "chapter xx" and the map name positions. while (cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdcR4(-2f) || instr.MatchLdcR4(-18f))) { Logger.Log("CollabUtils2/InGameOverworldHelper", $"Modding chapter panel title position at {cursor.Index} in IL for OuiChapterPanel.Render"); cursor.EmitDelegate <Func <float, float> >(orig => { if (Engine.Scene == overworldWrapper?.Scene && !isPanelShowingLobby()) { return(orig == -18f ? -49f : 43f); } else { return(orig); } }); } cursor.Index = 0; // 2. Resize the title if it does not fit. while (cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdcR4(-60))) { Logger.Log("CollabUtils2/InGameOverworldHelper", $"Modding chapter panel title bookmark position at {cursor.Index} in IL for OuiChapterPanel.Render"); cursor.Emit(OpCodes.Ldarg_0); cursor.EmitDelegate <Func <float, OuiChapterPanel, float> >((orig, self) => { if (Engine.Scene == overworldWrapper?.Scene) { float mapNameSize = ActiveFont.Measure(Dialog.Clean(AreaData.Get(self.Area).Name)).X; return(orig - Math.Max(0f, mapNameSize - 550f)); } else { return(orig); } }); } cursor.Index = 0; // 3. Turn the chapter card silver or rainbow instead of gold when relevant. while (cursor.TryGotoNext(MoveType.After, instr => instr.MatchLdstr("areaselect/cardtop_golden") || instr.MatchLdstr("areaselect/card_golden"), instr => instr.MatchLdarg(0), instr => instr.MatchCall <OuiChapterPanel>("_ModCardTexture"))) { Logger.Log("CollabUtils2/InGameOverworldHelper", $"Modding chapter panel card at {cursor.Index} in IL for OuiChapterPanel.Render"); cursor.EmitDelegate <Func <string, string> >(orig => { if (orig != "areaselect/cardtop_golden" && orig != "areaselect/card_golden") { // chapter card was reskinned through Everest, so don't change it. return(orig); } if (isPanelShowingLobby()) { return(orig == "areaselect/cardtop_golden" ? "CollabUtils2/chapterCard/cardtop_rainbow" : "CollabUtils2/chapterCard/card_rainbow"); } if (Engine.Scene == overworldWrapper?.Scene && !LobbyHelper.IsHeartSide(overworldWrapper.WrappedScene?.GetUI <OuiChapterPanel>().Area.GetSID())) { return(orig == "areaselect/cardtop_golden" ? "CollabUtils2/chapterCard/cardtop_silver" : "CollabUtils2/chapterCard/card_silver"); } return(orig); }); } }
//----------------------------------------- public static void Init() { LobbyHelper.Init(); }