示例#1
0
 private static int AreaComparison(AreaData a, AreaData b)
 {
     if (string.IsNullOrEmpty(a.GetLevelSet()) && !string.IsNullOrEmpty(b.GetLevelSet()))
     {
         return(1);
     }
     if (!string.IsNullOrEmpty(a.GetLevelSet()) && string.IsNullOrEmpty(b.GetLevelSet()))
     {
         return(-1);
     }
     return(string.Compare(a.GetSID(), b.GetSID()));
 }
示例#2
0
        private static void onJournalEnter(OuiJournal journal, Oui from)
        {
            // if using the vanilla journal, we just don't have anything to do, since vanilla already did everything for us!
            if (vanillaJournal)
            {
                return;
            }

            AreaData forceArea = journal.Overworld == null ? null : new DynData <Overworld>(journal.Overworld).Get <AreaData>("collabInGameForcedArea");

            if (forceArea != null)
            {
                // custom journal: throw away all pages, except the cover.
                for (int i = 0; i < journal.Pages.Count; i++)
                {
                    if (journal.Pages[i].GetType() != typeof(OuiJournalCover))
                    {
                        journal.Pages.RemoveAt(i);
                        i--;
                    }
                }

                // then, fill in the journal with our custom pages.
                journal.Pages.AddRange(OuiJournalCollabProgressInLobby.GeneratePages(journal, forceArea.GetLevelSet(), showOnlyDiscovered));

                // and add the map if we have it as well.
                if (MTN.Journal.Has("collabLobbyMaps/" + forceArea.GetLevelSet()))
                {
                    journal.Pages.Add(new OuiJournalLobbyMap(journal, MTN.Journal["collabLobbyMaps/" + forceArea.GetLevelSet()]));
                }
            }
        }
示例#3
0
        public override IEnumerator Enter(Oui from)
        {
            if (Direction == 0)
            {
                Overworld.Goto <OuiChapterSelect>();
                goto Done;
            }
            Direction = Math.Sign(Direction);

            yield return(0.25f);

            int    startID       = SaveData.Instance.LastArea.ID;
            string startLevelSet = SaveData.Instance.GetLevelSet();
            int    count         = AreaData.Areas.Count;

            for (int i = (count + startID + Direction) % count; i != startID; i = (count + i + Direction) % count)
            {
                AreaData area = AreaData.Areas[i];
                if (area.GetLevelSet() != startLevelSet)
                {
                    SaveData.Instance.LastArea = area.ToKey();
                    goto Done;
                }
            }

Done:
            Audio.Play("event:/ui/world_map/chapter/pane_expand");
            Overworld.Goto <OuiChapterSelect>();
            yield break;
        }
示例#4
0
        private IEnumerator EnterFirstAreaRoutine()
        {
            // Replace ID 0 with SaveData.Instance.LastArea.ID

            Overworld overworld = fileSelect.Overworld;
            AreaData  area      = AreaData.Areas[SaveData.Instance.LastArea.ID];

            if (area.GetLevelSet() != "Celeste")
            {
                // Pretend that we've beaten Prologue.
                LevelSetStats stats = SaveData.Instance.GetLevelSetStatsFor("Celeste");
                stats.UnlockedAreas = 1;
                stats.AreasIncludingCeleste[0].Modes[0].Completed = true;
            }

            yield return(fileSelect.Leave(null));

            yield return(overworld.Mountain.EaseCamera(0, area.MountainIdle));

            yield return(0.3f);

            overworld.Mountain.EaseCamera(0, area.MountainZoom, 1f);
            yield return(0.4f);

            area.Wipe(overworld, false, null);
            overworld.RendererList.UpdateLists();
            overworld.RendererList.MoveToFront(overworld.Snow);

            yield return(0.5f);

            LevelEnter.Go(new Session(SaveData.Instance.LastArea), false);
        }
示例#5
0
        private IEnumerator EaseOut(Oui next)
        {
            OuiChapterSelectIcon selected = null;

            if (next is OuiChapterPanel)
            {
                (selected = icons[area]).Select();
            }

            bool isVanilla = currentLevelSet == "Celeste";

            foreach (OuiChapterSelectIcon icon in icons)
            {
                AreaData area = AreaData.Areas[icon.Area];
                if (area.GetLevelSet() != currentLevelSet)
                {
                    continue;
                }

                if (selected != icon)
                {
                    icon.Hide();
                }

                if (isVanilla)
                {
                    yield return(0.01f);
                }
            }

            Visible = false;
            yield break;
        }
示例#6
0
        private IEnumerator Routine()
        {
            if (ErrorMessage != null)
            {
                string message = ErrorMessage;
                ErrorMessage = null;
                return(ErrorRoutine(message));
            }

            if (AreaData.Get(session) == null)
            {
                string message = Dialog.Get("postcard_levelgone")
                                 .Replace("((player))", SaveData.Instance.Name)
                                 .Replace("((sid))", session.Area.GetSID())
                ;
                return(ErrorRoutine(message));
            }

            AreaData areaData = AreaData.Get(session);
            MapMeta  areaMeta = areaData.GetMeta();

            if (areaMeta != null && areaData.GetLevelSet() != "Celeste" &&
                Dialog.Has(areaData.Name + "_postcard") &&
                session.StartedFromBeginning && !fromSaveData &&
                session.Area.Mode == AreaMode.Normal &&
                (!SaveData.Instance.Areas[session.Area.ID].Modes[0].Completed || SaveData.Instance.DebugMode))
            {
                return(EnterWithPostcardRoutine(Dialog.Get(areaData.Name + "_postcard"), areaMeta.PostcardSoundID));
            }

            return(orig_Routine());
        }
示例#7
0
        public override IEnumerator Enter(Oui from)
        {
            // Fix "out of bounds" level selection.
            int areaOffs = SaveData.Instance.GetLevelSetStats().AreaOffset;
            int areaMax  = Math.Max(areaOffs, SaveData.Instance.UnlockedAreas);

            area = Calc.Clamp(area, areaOffs, areaMax);

            Visible = true;
            EaseCamera();
            display = true;

            journalEnabled = Celeste.PlayMode == Celeste.PlayModes.Debug || (SaveData.Instance?.CheatMode ?? false);
            for (int i = 0; i <= SaveData.Instance.UnlockedAreas && !journalEnabled; i++)
            {
                if (SaveData.Instance.Areas[i].Modes[0].TimePlayed > 0L && !AreaData.Get(i).Interlude)
                {
                    journalEnabled = true;
                }
            }

            OuiChapterSelectIcon unselected = null;

            if (from is OuiChapterPanel)
            {
                (unselected = icons[area]).Unselect();
            }

            currentLevelSet = SaveData.Instance?.GetLevelSet() ?? "Celeste";
            foreach (OuiChapterSelectIcon icon in icons)
            {
                AreaData area = AreaData.Areas[icon.Area];
                if (area.GetLevelSet() != currentLevelSet)
                {
                    continue;
                }

                int index = area.ToKey().ID;
                if (index <= Math.Max(1, SaveData.Instance.UnlockedAreas) && icon != unselected)
                {
                    icon.Position = icon.HiddenPosition;
                    icon.Show();
                    icon.AssistModeUnlockable = false;
                }
                else if (SaveData.Instance.AssistMode && index == SaveData.Instance.UnlockedAreas + 1)
                {
                    icon.Position = icon.HiddenPosition;
                    icon.Show();
                    icon.AssistModeUnlockable = true;
                }

                // yield return 0.01f; // Originally returns 0.01f
            }

            if (from is OuiChapterPanel)
            {
                yield return(0.25f);
            }
        }
示例#8
0
        private static int AreaComparison(AreaData a, AreaData b)
        {
            string aSet = a.GetLevelSet();
            string aSID = a.GetSID();
            string bSet = b.GetLevelSet();
            string bSID = b.GetSID();

            // Celeste appears before everything else.
            if (aSet == "Celeste" && bSet != "Celeste")
            {
                return(-1);
            }
            if (aSet != "Celeste" && bSet == "Celeste")
            {
                return(1);
            }

            // Uncategorized appears after everything else.
            if (string.IsNullOrEmpty(aSet) && !string.IsNullOrEmpty(bSet))
            {
                return(1);
            }
            if (!string.IsNullOrEmpty(aSet) && string.IsNullOrEmpty(bSet))
            {
                return(-1);
            }

            // Compare level sets alphabetically.
            if (aSet != bSet)
            {
                return(string.Compare(aSet, bSet));
            }

            int?     aOrder;
            AreaMode aSide;
            string   aName;

            ParseName(aSID, out aOrder, out aSide, out aName);

            int?     bOrder;
            AreaMode bSide;
            string   bName;

            ParseName(bSID, out bOrder, out bSide, out bName);

            if (aOrder != null && bOrder != null &&
                aOrder.Value != bOrder.Value)
            {
                return(aOrder.Value - bOrder.Value);
            }

            if (aSide != bSide)
            {
                return(aSide - bSide);
            }

            return(string.Compare(aName, bName));
        }
        public override IEnumerator Enter(Oui from)
        {
            if (Direction == 0)
            {
                Overworld.Goto <OuiChapterSelect>();
                goto Done;
            }
            Direction = Math.Sign(Direction);

            yield return(0.25f);

            int    startID       = SaveData.Instance.LastArea.ID;
            string startLevelSet = SaveData.Instance.GetLevelSet();
            int    count         = AreaData.Areas.Count;

            for (int i = (count + startID + Direction) % count; i != startID; i = (count + i + Direction) % count)
            {
                AreaData area = AreaData.Get(i);
                if (area == null || area.GetLevelSet() != startLevelSet)
                {
                    SaveData.Instance.LastArea = area.ToKey();
                    goto Done;
                }
            }

Done:
            if (Direction > 0)
            {
                Audio.Play(SFX.ui_world_chapter_pane_expand);
            }
            else
            {
                Audio.Play(SFX.ui_world_chapter_pane_contract);
            }
            Overworld.Goto <OuiChapterSelect>();
        }
示例#10
0
        private static int AreaComparison(AreaData a, AreaData b)
        {
            string  aSet  = a.GetLevelSet();
            string  aSID  = a.GetSID();
            MapMeta aMeta = a.GetMeta();
            string  bSet  = b.GetLevelSet();
            string  bSID  = b.GetSID();
            MapMeta bMeta = b.GetMeta();

            // Celeste appears before everything else.
            if (aSet == "Celeste" && bSet != "Celeste")
            {
                return(-1);
            }
            if (aSet != "Celeste" && bSet == "Celeste")
            {
                return(1);
            }

            // Uncategorized appears after everything else.
            if (string.IsNullOrEmpty(aSet) && !string.IsNullOrEmpty(bSet))
            {
                return(1);
            }
            if (!string.IsNullOrEmpty(aSet) && string.IsNullOrEmpty(bSet))
            {
                return(-1);
            }

            // Compare level sets alphabetically.
            if (aSet != bSet)
            {
                return(string.Compare(aSet, bSet));
            }

            // Put "parented" levels at the end.
            if (!string.IsNullOrEmpty(aMeta?.Parent) && string.IsNullOrEmpty(bMeta?.Parent))
            {
                return(1);
            }
            if (string.IsNullOrEmpty(aMeta?.Parent) && !string.IsNullOrEmpty(bMeta?.Parent))
            {
                return(-1);
            }

            int?     aOrder;
            AreaMode aSide;
            string   aName;

            ParseName(aSID, out aOrder, out aSide, out aName);

            int?     bOrder;
            AreaMode bSide;
            string   bName;

            ParseName(bSID, out bOrder, out bSide, out bName);

            // put the "unordered" levels at the end. (Farewell is one of them.)
            if (aOrder != null && bOrder == null)
            {
                return(-1);
            }

            if (aOrder == null && bOrder != null)
            {
                return(1);
            }

            // order the rest by order, then by name, then by side
            if (aOrder != null && bOrder != null && aOrder.Value != bOrder.Value)
            {
                return(aOrder.Value - bOrder.Value);
            }

            if (aName != bName)
            {
                return(string.Compare(aName, bName));
            }

            if (aSide != bSide)
            {
                return(aSide - bSide);
            }

            // everything is the same: this is the same level
            return(0);
        }
示例#11
0
        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();
        }
示例#12
0
        public static new void Load()
        {
            orig_Load();

            // assign SIDs and CheckpointData.Area for vanilla maps.
            foreach (AreaData area in Areas)
            {
                area.SetSID("Celeste/" + area.Mode[0].Path);

                for (int modeId = 0; modeId < area.Mode.Length; modeId++)
                {
                    ModeProperties mode = area.Mode[modeId];
                    if (mode?.Checkpoints == null)
                    {
                        continue;
                    }

                    foreach (CheckpointData checkpoint in mode.Checkpoints)
                    {
                        checkpoint.SetArea(area.ToKey((AreaMode)modeId));
                    }
                }
            }

            // Separate array as we sort it afterwards.
            List <AreaData> modAreas = new List <AreaData>();

            lock (Everest.Content.Map) {
                foreach (ModAsset asset in Everest.Content.Map.Values.Where(asset => asset.Type == typeof(AssetTypeMap)))
                {
                    string path = asset.PathVirtual.Substring(5);

                    AreaData area = new AreaData();

                    // Default values.

                    area.SetSID(path);
                    area.Name = path;
                    area.Icon = "areas/" + path.ToLowerInvariant();
                    if (!GFX.Gui.Has(area.Icon))
                    {
                        area.Icon = "areas/null";
                    }

                    area.Interlude    = false;
                    area.CanFullClear = true;

                    area.TitleBaseColor   = Calc.HexToColor("6c7c81");
                    area.TitleAccentColor = Calc.HexToColor("2f344b");
                    area.TitleTextColor   = Color.White;

                    area.IntroType = Player.IntroTypes.WakeUp;

                    area.Dreaming   = false;
                    area.ColorGrade = null;

                    area.Mode = new ModeProperties[] {
                        new ModeProperties {
                            Inventory  = PlayerInventory.Default,
                            AudioState = new AudioState(SFX.music_city, SFX.env_amb_00_main)
                        }
                    };

                    area.Wipe = (Scene scene, bool wipeIn, Action onComplete)
                                => new AngledWipe(scene, wipeIn, onComplete);

                    area.DarknessAlpha = 0.05f;
                    area.BloomBase     = 0f;
                    area.BloomStrength = 1f;

                    area.Jumpthru = "wood";

                    area.CassseteNoteColor = Calc.HexToColor("33a9ee");
                    area.CassetteSong      = SFX.cas_01_forsaken_city;

                    // Custom values can be set via the MapMeta.
                    MapMeta meta = new MapMeta();
                    meta.ApplyTo(area);
                    MapMeta metaLoaded = asset.GetMeta <MapMeta>();
                    if (metaLoaded != null)
                    {
                        area.SetMeta(null);
                        metaLoaded.ApplyTo(area);
                        meta = metaLoaded;
                    }

                    if (string.IsNullOrEmpty(area.Mode[0].Path))
                    {
                        area.Mode[0].Path = asset.PathVirtual.Substring(5);
                    }

                    // Some of the game's code checks for [1] / [2] explicitly.
                    // Let's just provide null modes to fill any gaps.
                    meta.Modes = meta.Modes ?? new MapMetaModeProperties[3];
                    if (meta.Modes.Length < 3)
                    {
                        MapMetaModeProperties[] larger = new MapMetaModeProperties[3];
                        for (int i = 0; i < meta.Modes.Length; i++)
                        {
                            larger[i] = meta.Modes[i];
                        }
                        meta.Modes = larger;
                    }
                    if (area.Mode.Length < 3)
                    {
                        ModeProperties[] larger = new ModeProperties[3];
                        for (int i = 0; i < area.Mode.Length; i++)
                        {
                            larger[i] = area.Mode[i];
                        }
                        area.Mode = larger;
                    }

                    // Celeste levelset always appears first.
                    if (area.GetLevelSet() == "Celeste")
                    {
                        Areas.Add(area);
                    }
                    else
                    {
                        modAreas.Add(area);
                    }

                    // Some special handling.
                    area.OnLevelBegin = (level) => {
                        MapMeta levelMeta = AreaData.Get(level.Session).GetMeta();
                        MapMetaModeProperties levelMetaMode = level.Session.MapData.GetMeta();

                        if (levelMetaMode?.SeekerSlowdown ?? false)
                        {
                            level.Add(new SeekerEffectsController());
                        }
                    };
                }
            }


            // Merge modAreas into Areas.
            Areas.AddRange(modAreas);

            // Find duplicates and remove any earlier copies.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                int      otherIndex = Areas.FindIndex(other => other.GetSID() == area.GetSID());
                if (otherIndex < i)
                {
                    Areas[otherIndex] = area;
                    Areas.RemoveAt(i);
                    i--;
                }
            }

            // Sort areas.
            Areas.Sort(AreaComparison);

            // Remove AreaDatas which are now a mode of another AreaData.
            // This can happen late as the map data (.bin) can contain additional metadata.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                string   path       = area.Mode[0].Path;
                int      otherIndex = Areas.FindIndex(other => other.Mode.Any(otherMode => otherMode?.Path == path));
                if (otherIndex != -1 && otherIndex != i)
                {
                    Areas.RemoveAt(i);
                    i--;
                    continue;
                }

                int?     order;
                AreaMode side;
                string   name;
                ParseName(path, out order, out side, out name);

                // Also check for .bins possibly belonging to A side .bins by their path and lack of existing modes.
                for (int ii = 0; ii < Areas.Count; ii++)
                {
                    AreaData other = Areas[ii];
                    int?     otherOrder;
                    AreaMode otherSide;
                    string   otherName;
                    ParseName(other.Mode[0].Path, out otherOrder, out otherSide, out otherName);

                    if (area.GetLevelSet() == other.GetLevelSet() && order == otherOrder && name == otherName && side != otherSide &&
                        !other.HasMode(side))
                    {
                        if (other.Mode[(int)side] == null)
                        {
                            other.Mode[(int)side] = new ModeProperties {
                                Inventory  = PlayerInventory.Default,
                                AudioState = new AudioState(SFX.music_city, SFX.env_amb_00_main)
                            }
                        }
                        ;
                        other.Mode[(int)side].Path = path;
                        Areas.RemoveAt(i);
                        i--;
                        break;
                    }
                }
            }

            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area = Areas[i];
                area.ID = i;

                // Clean up non-existing modes.
                int modei = 0;
                for (; modei < area.Mode.Length; modei++)
                {
                    ModeProperties mode = area.Mode[modei];
                    if (mode == null || string.IsNullOrEmpty(mode.Path))
                    {
                        break;
                    }
                }
                Array.Resize(ref area.Mode, modei);

                Logger.Log("AreaData", $"{i}: {area.GetSID()} - {area.Mode.Length} sides");

                // Update old MapData areas and load any new areas.

                // Add the A side MapData or update its area key.
                if (area.Mode[0].MapData != null)
                {
                    area.Mode[0].MapData.Area = area.ToKey();
                }
                else
                {
                    area.Mode[0].MapData = new MapData(area.ToKey());
                }

                if (area.IsInterludeUnsafe())
                {
                    continue;
                }

                // A and (some) B sides have PoemIDs. Can be overridden via empty PoemID.
                if (area.Mode[0].PoemID == null)
                {
                    area.Mode[0].PoemID = area.GetSID().DialogKeyify() + "_A";
                }
                if (area.Mode.Length > 1 &&
                    area.Mode[1] != null &&
                    area.Mode[1].PoemID == null)
                {
                    area.Mode[1].PoemID = area.GetSID().DialogKeyify() + "_B";
                }

                // Update all other existing mode's area keys.
                for (int mode = 1; mode < area.Mode.Length; mode++)
                {
                    if (area.Mode[mode] == null)
                    {
                        continue;
                    }
                    if (area.Mode[mode].MapData != null)
                    {
                        area.Mode[mode].MapData.Area = area.ToKey((AreaMode)mode);
                    }
                    else
                    {
                        area.Mode[mode].MapData = new MapData(area.ToKey((AreaMode)mode));
                    }
                }
            }

            // Load custom mountains
            // This needs to be done after areas are loaded because it depends on the MapMeta
            MTNExt.LoadMod();
            MTNExt.LoadModData();
        }
示例#13
0
        private void ReloadItems()
        {
            foreach (TextMenu.Item item in items)
            {
                menu.Remove(item);
            }
            items.Clear();

            string filterSet = null;

            if (type == 0)
            {
                filterSet = "Celeste";
            }
            else if (type >= 3)
            {
                filterSet = sets[type - 3];
            }

            string        lastLevelSet          = null;
            LevelSetStats levelSetStats         = null;
            int           levelSetAreaOffset    = 0;
            int           levelSetUnlockedAreas = int.MaxValue;
            int           levelSetUnlockedModes = int.MaxValue;
            string        name;

            SaveData         save         = SaveData.Instance;
            List <AreaStats> areaStatsAll = save.Areas;

            for (int i = 0; i < AreaData.Areas.Count; i++)
            {
                AreaData area = AreaData.Get(i);
                if (area == null || !area.HasMode((AreaMode)side))
                {
                    continue;
                }

                // TODO: Make subchapters hidden by default in the map list, even in debug mode.
                if (!save.DebugMode && !string.IsNullOrEmpty(area.GetMeta()?.Parent))
                {
                    continue;
                }

                string levelSet = area.GetLevelSet();

                if (type != 1 && ((filterSet == null && levelSet == "Celeste") || (filterSet != null && filterSet != levelSet)))
                {
                    continue;
                }

                name = area.Name;
                name = name.DialogCleanOrNull() ?? name.SpacedPascalCase();

                if (lastLevelSet != levelSet)
                {
                    lastLevelSet          = levelSet;
                    levelSetStats         = SaveData.Instance.GetLevelSetStatsFor(levelSet);
                    levelSetAreaOffset    = levelSetStats.AreaOffset;
                    levelSetUnlockedAreas = levelSetStats.UnlockedAreas;
                    levelSetUnlockedModes = levelSetStats.UnlockedModes;
                    string setname = DialogExt.CleanLevelSet(levelSet);
                    TextMenuExt.SubHeaderExt levelSetHeader = new TextMenuExt.SubHeaderExt(setname);
                    levelSetHeader.Alpha = 0f;
                    menu.Add(levelSetHeader);
                    items.Add(levelSetHeader);
                }

                TextMenuExt.ButtonExt button = new TextMenuExt.ButtonExt(name);
                button.Alpha = 0f;

                if (area.Icon != "areas/null")
                {
                    button.Icon = area.Icon;
                }
                button.IconWidth = 64f;

                if (levelSet == "Celeste" && i > levelSetAreaOffset + levelSetUnlockedAreas)
                {
                    button.Disabled = true;
                }
                if (side == 1 && !areaStatsAll[i].Cassette)
                {
                    button.Disabled = true;
                }
                if (side >= 2 && levelSetUnlockedModes < (side + 1))
                {
                    button.Disabled = true;
                }

                menu.Add(button.Pressed(() => {
                    Inspect(area, (AreaMode)side);
                }));
                items.Add(button);
            }

            // compute a delay so that options don't take more than a second to show up if many mods are installed.
            float delayBetweenOptions = 0.03f;

            if (items.Count > 0)
            {
                delayBetweenOptions = Math.Min(0.03f, 1f / items.Count);
            }

            // Do this afterwards as the menu has now properly updated its size.
            for (int i = 0; i < items.Count; i++)
            {
                Add(new Coroutine(FadeIn(i, delayBetweenOptions, items[i])));
            }

            if (menu.Height > menu.ScrollableMinSize)
            {
                menu.Position.Y = menu.ScrollTargetY;
            }
        }
示例#14
0
        private void ReloadItems()
        {
            foreach (TextMenu.Item item in items)
            {
                menu.Remove(item);
            }
            items.Clear();

            string filterSet = null;

            if (type == 0)
            {
                filterSet = "Celeste";
            }
            else if (type >= 2)
            {
                filterSet = sets[type - 2];
            }

            string        lastLevelSet          = null;
            LevelSetStats levelSetStats         = null;
            int           levelSetAreaOffset    = 0;
            int           levelSetUnlockedAreas = int.MaxValue;
            int           levelSetUnlockedModes = int.MaxValue;
            string        name;

            List <AreaStats> areaStatsAll = SaveData.Instance.Areas;

            for (int i = 0; i < AreaData.Areas.Count; i++)
            {
                AreaData area = AreaData.Areas[i];
                if (!area.HasMode((AreaMode)side))
                {
                    continue;
                }

                string levelSet = area.GetLevelSet();

                if ((filterSet == null && levelSet == "Celeste") || (filterSet != null && filterSet != levelSet))
                {
                    continue;
                }

                if (lastLevelSet != levelSet)
                {
                    lastLevelSet          = levelSet;
                    levelSetStats         = SaveData.Instance.GetLevelSetStatsFor(levelSet);
                    levelSetAreaOffset    = levelSetStats.AreaOffset;
                    levelSetUnlockedAreas = levelSetStats.UnlockedAreas;
                    levelSetUnlockedModes = levelSetStats.UnlockedModes;
                    if (levelSet != "Celeste")
                    {
                        name = DialogExt.CleanLevelSet(levelSet);
                        TextMenuExt.SubHeaderExt levelSetHeader = new TextMenuExt.SubHeaderExt(name);
                        levelSetHeader.Alpha = 0f;
                        menu.Add(levelSetHeader);
                        items.Add(levelSetHeader);
                    }
                }

                name = area.Name;
                name = name.DialogCleanOrNull() ?? name.SpacedPascalCase();

                TextMenuExt.ButtonExt button = new TextMenuExt.ButtonExt(name);
                button.Alpha = 0f;

                if (area.Icon != "areas/null")
                {
                    button.Icon = area.Icon;
                }
                button.IconWidth = 64f;

                if (levelSet == "Celeste" && i > levelSetAreaOffset + levelSetUnlockedAreas)
                {
                    button.Disabled = true;
                }
                if (side == 1 && !areaStatsAll[i].Cassette)
                {
                    button.Disabled = true;
                }
                if (side >= 2 && levelSetUnlockedModes < (side + 1))
                {
                    button.Disabled = true;
                }

                menu.Add(button.Pressed(() => {
                    Inspect(area, (AreaMode)side);
                }));
                items.Add(button);
            }

            // Do this afterwards as the menu has now properly updated its size.
            for (int i = 0; i < items.Count; i++)
            {
                Add(new Coroutine(FadeIn(i, items[i])));
            }

            if (menu.Height > menu.ScrollableMinSize)
            {
                menu.Position.Y = menu.ScrollTargetY;
            }
        }
示例#15
0
        public override IEnumerator Enter(Oui from)
        {
            // Fix "out of bounds" level selection.
            GetMinMaxArea(out int areaOffs, out int areaMax);
            int areaUnclamp = area;

            area = Calc.Clamp(area, areaOffs, areaMax);

            Visible = true;
            EaseCamera();
            display = true;

            currentLevelSet = SaveData.Instance?.GetLevelSet() ?? "Celeste";

            journalEnabled = string.IsNullOrEmpty(currentLevelSet) || Celeste.PlayMode == Celeste.PlayModes.Debug || (SaveData.Instance?.CheatMode ?? false);
            for (int i = 0; i <= SaveData.Instance.UnlockedAreas && !journalEnabled; i++)
            {
                if (SaveData.Instance.Areas[i].Modes[0].TimePlayed > 0L && !AreaData.Get(i).Interlude)
                {
                    journalEnabled = true;
                }
            }

            OuiChapterSelectIcon unselected = null;

            if (from is OuiChapterPanel)
            {
                (unselected = icons[areaUnclamp]).Unselect();
                if (areaUnclamp != area)
                {
                    unselected.Hide();
                }
            }

            bool isVanilla = currentLevelSet == "Celeste";

            foreach (OuiChapterSelectIcon icon in icons)
            {
                AreaData area = AreaData.Get(icon.Area);
                if (area == null || area.GetLevelSet() != currentLevelSet)
                {
                    continue;
                }

                int index = area.ToKey().ID;
                if ((string.IsNullOrEmpty(currentLevelSet) || index <= Math.Max(1, SaveData.Instance.UnlockedAreas)) &&
                    icon != unselected)
                {
                    icon.Position = icon.HiddenPosition;
                    icon.Show();
                    icon.AssistModeUnlockable = false;
                }
                else if (SaveData.Instance.AssistMode && index == SaveData.Instance.UnlockedAreas + 1)
                {
                    icon.Position = icon.HiddenPosition;
                    icon.Show();
                    icon.AssistModeUnlockable = true;
                }

                if (isVanilla)
                {
                    yield return(0.01f);
                }
            }

            if (from is OuiChapterPanel)
            {
                yield return(0.25f);
            }
        }
示例#16
0
        public static new void Load()
        {
            orig_Load();

            foreach (AreaData area in Areas)
            {
                area.SetSID("Celeste/" + area.Mode[0].Path);
            }

            // Separate array as we sort it afterwards.
            List <AreaData> modAreas = new List <AreaData>();

            foreach (ModAsset asset in Everest.Content.ListMaps)
            {
                string  path = asset.PathMapped.Substring(5);
                MapMeta meta = asset.GetMeta <MapMeta>();

                AreaData area = new AreaData();

                // Default values.

                area.SetSID(path);

                area.Name = path;
                area.Icon = "areas/" + path.ToLowerInvariant();
                if (!GFX.Gui.Has(area.Icon))
                {
                    area.Icon = "areas/null";
                }

                area.TitleBaseColor   = Calc.HexToColor("6c7c81");
                area.TitleAccentColor = Calc.HexToColor("2f344b");
                area.TitleTextColor   = Color.White;

                area.IntroType = Player.IntroTypes.WakeUp;

                area.Dreaming   = false;
                area.ColorGrade = null;

                area.Mode = new ModeProperties[] {
                    new ModeProperties {
                        Path       = asset.PathMapped.Substring(5),
                        Inventory  = PlayerInventory.Default,
                        AudioState = new AudioState(Sfxs.music_city, Sfxs.env_amb_00_main)
                    }
                };

                area.Wipe = (Scene scene, bool wipeIn, Action onComplete)
                            => new AngledWipe(scene, wipeIn, onComplete);

                area.DarknessAlpha = 0.05f;
                area.BloomBase     = 0f;
                area.BloomStrength = 1f;

                area.Jumpthru = "wood";

                area.CassseteNoteColor = Calc.HexToColor("33a9ee");
                area.CassetteSong      = Sfxs.cas_01_forsaken_city;

                // Custom values.
                if (meta != null)
                {
                    if (!string.IsNullOrEmpty(meta.Name))
                    {
                        area.Name = meta.Name;
                    }

                    if (!string.IsNullOrEmpty(meta.SID))
                    {
                        area.SetSID(meta.SID);
                    }

                    if (!string.IsNullOrEmpty(meta.Icon) && GFX.Gui.Has(meta.Icon))
                    {
                        area.Icon = meta.Icon;
                    }

                    area.Interlude = meta.Interlude;
                    if (!string.IsNullOrEmpty(meta.CompleteScreenName))
                    {
                        area.CompleteScreenName = meta.CompleteScreenName;
                    }

                    area.CassetteCheckpointIndex = meta.CassetteCheckpointIndex;

                    if (!string.IsNullOrEmpty(meta.TitleBaseColor))
                    {
                        area.TitleBaseColor = Calc.HexToColor(meta.TitleBaseColor);
                    }
                    if (!string.IsNullOrEmpty(meta.TitleAccentColor))
                    {
                        area.TitleAccentColor = Calc.HexToColor(meta.TitleAccentColor);
                    }
                    if (!string.IsNullOrEmpty(meta.TitleTextColor))
                    {
                        area.TitleTextColor = Calc.HexToColor(meta.TitleTextColor);
                    }

                    area.IntroType = meta.IntroType;

                    area.Dreaming = meta.Dreaming;
                    if (!string.IsNullOrEmpty(meta.ColorGrade))
                    {
                        area.ColorGrade = meta.ColorGrade;
                    }

                    area.Mode = MapMeta.Convert(meta.Modes) ?? area.Mode;

                    if (!string.IsNullOrEmpty(meta.Wipe))
                    {
                        Type            type = Assembly.GetEntryAssembly().GetType(meta.Wipe);
                        ConstructorInfo ctor = type?.GetConstructor(new Type[] { typeof(Scene), typeof(bool), typeof(Action) });
                        if (type != null && ctor != null)
                        {
                            area.Wipe = (scene, wipeIn, onComplete) => ctor.Invoke(new object[] { scene, wipeIn, onComplete });
                        }
                    }

                    area.DarknessAlpha = meta.DarknessAlpha;
                    area.BloomBase     = meta.BloomBase;
                    area.BloomStrength = meta.BloomStrength;

                    if (!string.IsNullOrEmpty(meta.Jumpthru))
                    {
                        area.Jumpthru = meta.Jumpthru;
                    }

                    if (!string.IsNullOrEmpty(meta.CassetteNoteColor))
                    {
                        area.CassseteNoteColor = Calc.HexToColor(meta.CassetteNoteColor);
                    }
                    if (!string.IsNullOrEmpty(meta.CassetteSong))
                    {
                        area.CassetteSong = meta.CassetteSong;
                    }

                    area.MountainIdle   = meta.Mountain?.Idle?.Convert() ?? area.MountainIdle;
                    area.MountainSelect = meta.Mountain?.Select?.Convert() ?? area.MountainSelect;
                    area.MountainZoom   = meta.Mountain?.Zoom?.Convert() ?? area.MountainZoom;
                    area.MountainCursor = meta.Mountain?.Cursor?.ToVector3() ?? area.MountainCursor;
                    area.MountainState  = meta.Mountain?.State ?? area.MountainState;

                    area.SetCompleteScreenMeta(meta.CompleteScreen);
                }

                // Some of the game's code checks for [1] / [2] explicitly.
                // Let's just provide null modes to fill any gaps.
                if (area.Mode.Length < 3)
                {
                    ModeProperties[] larger = new ModeProperties[3];
                    for (int i = 0; i < area.Mode.Length; i++)
                    {
                        larger[i] = area.Mode[i];
                    }
                    area.Mode = larger;
                }

                // Celeste levelset always appears first.
                if (area.GetLevelSet() == "Celeste")
                {
                    Areas.Add(area);
                }
                else
                {
                    modAreas.Add(area);
                }
            }


            // Sort and merge modAreas into Areas. Makes for easier levelset handling.
            Areas.Sort(AreaComparison);
            modAreas.Sort(AreaComparison);
            Areas.AddRange(modAreas);

            // Find duplicates and remove the earlier copy.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                int      otherIndex = Areas.FindIndex(other => other.GetSID() == area.GetSID());
                if (otherIndex < i)
                {
                    Areas[otherIndex] = area;
                    Areas.RemoveAt(i);
                    i--;
                }
            }

            // Remove AreaDatas which are now a mode of another AreaData.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area       = Areas[i];
                int      otherIndex = Areas.FindIndex(other => other.Mode.Any(otherMode => otherMode?.Path == area.Mode[0].Path));
                if (otherIndex != -1 && otherIndex != i)
                {
                    Areas.RemoveAt(i);
                    i--;
                }
            }

            // Update old MapData areas and load any new areas.
            for (int i = 0; i < Areas.Count; i++)
            {
                AreaData area = Areas[i];
                area.ID = i;
                if (area.Mode[0].MapData != null)
                {
                    area.Mode[0].MapData.Area = area.ToKey();
                }
                else
                {
                    area.Mode[0].MapData = new MapData(area.ToKey());
                }
                if (area.Interlude)
                {
                    continue;
                }
                for (int mode = 1; mode < area.Mode.Length; mode++)
                {
                    if (area.Mode[mode] == null)
                    {
                        continue;
                    }
                    if (area.Mode[mode].MapData != null)
                    {
                        area.Mode[mode].MapData.Area = area.ToKey((AreaMode)mode);
                    }
                    else
                    {
                        area.Mode[mode].MapData = new MapData(area.ToKey((AreaMode)mode));
                    }
                }
            }
        }
示例#17
0
        private void EaseCamera()
        {
            AreaData areaData = AreaData.Areas[area];

            Overworld.Mountain.EaseCamera(area, areaData.MountainIdle, null, true, areaData.GetMeta()?.Mountain?.Rotate ?? areaData.GetLevelSet() == "Celeste" && area == 10);
            Overworld.Mountain.Model.EaseState(areaData.MountainState);
        }
        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);
        }
示例#19
0
        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);
        }