diff --git a/BGAnimations/ScreenSelectMusic overlay/Leaderboard.lua b/BGAnimations/ScreenSelectMusic overlay/Leaderboard.lua index aea5f65a6..ff5af2e5f 100644 --- a/BGAnimations/ScreenSelectMusic overlay/Leaderboard.lua +++ b/BGAnimations/ScreenSelectMusic overlay/Leaderboard.lua @@ -16,6 +16,24 @@ local SetLeaderboardForPlayer = function(player_num, leaderboard, leaderboardDat local entryNum = 1 local rivalNum = 1 + + if leaderboardData["Disabled"] then + if leaderboardData["Name"] then + local name = leaderboardData["Name"]:gsub("ITL Online", "ITL") + leaderboard:GetChild("Header"):settext(name) + end + for j=1, NumEntries do + local entry = leaderboard:GetChild("LeaderboardEntry"..j) + if j == 1 then + SetEntryText("", "Disabled", "", "", entry) + else + -- Empty out the remaining rows. + SetEntryText("", "", "", "", entry) + end + end + return + end + -- Hide the rival and self highlights. -- They will be unhidden and repositioned as needed below. for i=1,3 do @@ -91,7 +109,38 @@ local SetLeaderboardForPlayer = function(player_num, leaderboard, leaderboardDat end end end - +local getLocalLeaderboard = function(pn) + if not GAMESTATE:IsPlayerEnabled(pn) then return {} end + local HighScores = PROFILEMAN:GetMachineProfile():GetHighScoreList(GAMESTATE:GetCurrentSong(),GAMESTATE:GetCurrentSteps(pn)):GetHighScores() + local profileName = PROFILEMAN:GetProfile(pn):GetLastUsedHighScoreName() + local localData = {} + if HighScores then + for i, highscore in ipairs(HighScores) do + local name = highscore:GetName() + local percentDP = highscore:GetPercentDP() + local score = tonumber(("%.0f"):format(percentDP * 10000)) + local date = highscore:GetDate() + local grade = highscore:GetGrade() + local isRival = false + local isSelf = name == profileName + local isFail = false + if grade == "Grade_Failed" then + isFail = true + end + local entry = { + name=name, + score=score, + date=date, + isRival=isRival, + isSelf=isSelf, + isFail=isFail, + rank=i + } + table.insert(localData, entry) + end + end + return localData +end local LeaderboardRequestProcessor = function(res, master) if master == nil then return end @@ -106,6 +155,14 @@ local LeaderboardRequestProcessor = function(res, master) for i=1, 2 do local pn = "P"..i local leaderboard = master:GetChild(pn.."Leaderboard") + local leaderboardList = master[pn]["Leaderboards"] + local localData = getLocalLeaderboard(pn) + leaderboardList[#leaderboardList + 1] = { + Name="Machine's Best", + Data=DeepCopy(localData), + IsEX=false + } + master[pn]["LeaderboardIndex"] = 1 for j=1, NumEntries do local entry = leaderboard:GetChild("LeaderboardEntry"..j) if j == 1 then @@ -129,7 +186,6 @@ local LeaderboardRequestProcessor = function(res, master) if data[playerStr] then master[pn].isRanked = data[playerStr]["isRanked"] - if SL["P"..i].ActiveModifiers.ShowEXScore then -- If the player is using EX scoring, then we want to display the EX leaderboard first. if data[playerStr]["exLeaderboard"] then @@ -183,6 +239,17 @@ local LeaderboardRequestProcessor = function(res, master) end end + -- Display the local leaderboard last if the preference is not set + if not ThemePrefs.Get("PrioritizeLocalLeaderboard") then + local localData = getLocalLeaderboard(pn) + leaderboardList[#leaderboardList + 1] = { + Name="Machine's Best", + Data=DeepCopy(localData), + IsEX=false + } + master[pn]["LeaderboardIndex"] = 1 + end + if #leaderboardList > 1 then leaderboard:GetChild("PaneIcons"):visible(true) else @@ -253,22 +320,51 @@ local af = Def.ActorFrame{ }, RequestResponseActor(17, 50)..{ SendLeaderboardRequestCommand=function(self) + -- If a player does not have an API key or chart hash just show the local leaderboard. + + for i=1,2 do + local pn = "P"..i + if SL[pn].ApiKey == "" or SL[pn].Streams.Hash == "" or ThemePrefs.Get("PrioritizeLocalLeaderboard") or not IsServiceAllowed(SL.GrooveStats.Leaderboard) then + local pn = "P"..i + local leaderboard = self:GetParent():GetChild(pn.."Leaderboard") + local leaderboardList = self:GetParent()[pn]["Leaderboards"] + local localData = getLocalLeaderboard(pn) + leaderboardList[#leaderboardList + 1] = { + Name="Machine's Best", + Data=DeepCopy(localData), + IsEX=false + } + self:GetParent()[pn]["LeaderboardIndex"] = 1 + end + end + -- Display the local leaderboard first if the preference is set + if ThemePrefs.Get("PrioritizeLocalLeaderboard") or not IsServiceAllowed(SL.GrooveStats.Leaderboard) then + for i=1, 2 do + local pn = "P"..i + local leaderboard = self:GetParent():GetChild(pn.."Leaderboard") + local leaderboardList = self:GetParent()[pn]["Leaderboards"] + local localData = getLocalLeaderboard(pn) + leaderboardList[#leaderboardList + 1] = { + Name="Machine's Bests", + Data=DeepCopy(localData), + IsEX=false + } + self:GetParent()[pn]["LeaderboardIndex"] = 1 + end + end if not IsServiceAllowed(SL.GrooveStats.Leaderboard) then if SL.GrooveStats.IsConnected then -- If we disable the service from a previous request, surface it to the user here. - -- (Even though the Leaderboard option is already removed from the sort menu, so this is extra). for i=1, 2 do local pn = "P"..i local leaderboard = self:GetParent():GetChild(pn.."Leaderboard") - for j=1, NumEntries do - local entry = leaderboard:GetChild("LeaderboardEntry"..j) - if j == 1 then - SetEntryText("", "Disabled", "", "", entry) - else - -- Empty out the remaining rows. - SetEntryText("", "", "", "", entry) - end - end + local leaderboardList = self:GetParent()[pn]["Leaderboards"] + leaderboardList[#leaderboardList + 1] = { + Name="Groovestats", + Disabled=true, + IsEX=false + } + SetLeaderboardForPlayer(i, leaderboard, leaderboardList[1], false) end end return diff --git a/BGAnimations/ScreenSelectMusic overlay/SortMenu/default.lua b/BGAnimations/ScreenSelectMusic overlay/SortMenu/default.lua index f2922b548..c424f62ad 100644 --- a/BGAnimations/ScreenSelectMusic overlay/SortMenu/default.lua +++ b/BGAnimations/ScreenSelectMusic overlay/SortMenu/default.lua @@ -188,9 +188,7 @@ local function AddPlayerSortOptions() local player_sort_options = {} for player in ivalues(GAMESTATE:GetHumanPlayers()) do if PROFILEMAN:IsPersistentProfile(player) then - SM("Adding player sort options") table.insert(player_sort_options, {"SortBy", "Top" .. ToEnumShortString(player) .. "Grades"}) - table.insert(player_sort_options, {"SortBy", "Recent" .. ToEnumShortString(player) .. "Played"}) end end return player_sort_options @@ -245,7 +243,8 @@ local wheel_options = { -- Conditions: -- These determine whether or not the option will be displayed. -- For instance: { {"SortBy", "Group"}, GAMESTATE:IsCourseMode() } will only display the Group option in CourseMode. - -- You can use any Lua expression that returns a boolean value here. + -- You can use any Lua expression that equates to a boolean value here. + -- Alternatively, you may provide a function that returns a boolean value for more complex and timely conditions. -- Submenus: -- We can create categories within the SortMenu by providing a table as the second element @@ -274,9 +273,9 @@ local wheel_options = { {"", "CategoryAdvanced"}, { { {"FeelingSalty", "TestInput"}, GAMESTATE:IsEventMode() }, - { {"HardTime", "PracticeMode"}, GAMESTATE:IsEventMode() and GAMESTATE:GetCurrentSong() ~= nil and ThemePrefs.Get("KeyboardFeatures")}, + { {"HardTime", "PracticeMode"}, function() return GAMESTATE:IsEventMode() and GAMESTATE:GetCurrentSong() ~= nil and ThemePrefs.Get("KeyboardFeatures") end }, { {"TakeABreather", "LoadNewSongs"} }, - { {"NeedMoreRam", "ViewDownloads"}, DownloadsExist() }, + { {"NeedMoreRam", "ViewDownloads"}, DownloadsExist }, { {"WhereforeArtThou", "SongSearch"}, not GAMESTATE:IsCourseMode() and ThemePrefs.Get("KeyboardFeatures") }, { {"NextPlease", "SwitchProfile"}, ThemePrefs.Get("AllowScreenSelectProfile") }, { {"SetSummaryText", "SetSummary"}, SL.Global.Stages.PlayedThisGame > 0 }, @@ -299,9 +298,9 @@ local wheel_options = { -- It's technically not possible to reach the sort menu in Casual Mode, but juuust in case let's still -- include the check. { {"ChangeMode", "Casual"}, SL.Global.Stages.PlayedThisGame == 0 and SL.Global.GameMode ~= "Casual" }, - { {"ImLovinIt", "AddFavorite"}, GAMESTATE:GetCurrentSong() ~= nil }, + { {"ImLovinIt", "AddFavorite"}, function() return GAMESTATE:GetCurrentSong() ~= nil end}, AddFavorites(), - { {"GrooveStats", "Leaderboard"}, IsServiceAllowed(SL.GrooveStats.Leaderboard) and GAMESTATE:GetCurrentSong() ~= nil }, + { {"GrooveStats", "Leaderboard"}, function() return GAMESTATE:GetCurrentSong() ~= nil end }, } @@ -331,7 +330,11 @@ local t = Def.ActorFrame { local sub_options = {} for j=1, #option[2] do local sub_option = option[2][j] - if sub_option[2] == nil or sub_option[2] == true then + if type(sub_option[2]) == "function" then + if sub_option[2]() then + table.insert(filtered_wheel_options, sub_option[1]) + end + elseif sub_option[2] == nil or sub_option[2] == true then table.insert(filtered_wheel_options, sub_option[1]) end end @@ -428,13 +431,21 @@ local t = Def.ActorFrame { local sub_options = {} for j=1, #option[2] do local sub_option = option[2][j] - if sub_option[2] == nil or sub_option[2] == true then + if type(sub_option[2]) == "function" then + if sub_option[2]() then + table.insert(sub_options, sub_option) + end + elseif sub_option[2] == nil or sub_option[2] == true then table.insert(sub_options, sub_option) end end if #sub_options > 0 then table.insert(filtered_wheel_options, {option[1][1], option[1][2]}) end + elseif type(option[2]) == "function" then + if option[2]() then + table.insert(filtered_wheel_options, {option[1][1], option[1][2]}) + end elseif option[2] == nil or option[2] == true then table.insert(filtered_wheel_options, {option[1][1], option[1][2]}) end diff --git a/Languages/en.ini b/Languages/en.ini index 1c72b02b7..ffa6b35bf 100644 --- a/Languages/en.ini +++ b/Languages/en.ini @@ -778,6 +778,7 @@ EnableGrooveStats=Enable GrooveStats AutoDownloadUnlocks=Auto-Download Unlocks SeparateUnlocksByPlayer=Separate Unlocks By Player QRLogin=Display GrooveStats QR Login +PrioritizeLocalLeaderboard=Show Machine Scores First ############################################## # now we get into the longer explanations of options @@ -932,6 +933,8 @@ SeparateUnlocksByPlayer=Separate Downloaded Unlocks for Each Profile. QRLogin=When to display that QR Login screen.\n\nAlways - Always display the QR Login screen.\n\nSometimes - Only display the QR Login screen if needed for the profiles.\n\nDisable QR Login entirely. + +PrioritizeLocalLeaderboard=When viewing the leaderboard, Show the scores obtained on this machine first before showing any obtained from Groovestats. # ScreenPlayerOptions SpeedModType=Change the way arrows react to changing BPMs. SpeedMod=Adjust the speed at which arrows travel toward the targets. diff --git a/Scripts/99 SL-ThemePrefs.lua b/Scripts/99 SL-ThemePrefs.lua index ec48eebe2..d39051831 100644 --- a/Scripts/99 SL-ThemePrefs.lua +++ b/Scripts/99 SL-ThemePrefs.lua @@ -298,7 +298,6 @@ SL_CustomPrefs.Get = function() Choices = { THEME:GetString("ThemePrefs","Yes"), THEME:GetString("ThemePrefs", "No") }, Values = { true, false } }, - QRLogin = { Default = "Sometimes", Choices = { @@ -307,6 +306,11 @@ SL_CustomPrefs.Get = function() THEME:GetString("ThemePrefs", "Never"), }, Values = { "Always", "Sometimes", "Never" } + }, + PrioritizeLocalLeaderboard = { + Default = false, + Choices = { THEME:GetString("ThemePrefs","Yes"), THEME:GetString("ThemePrefs", "No") }, + Values = { true, false } } } end diff --git a/metrics.ini b/metrics.ini index 271745ab8..7472c1277 100644 --- a/metrics.ini +++ b/metrics.ini @@ -1290,12 +1290,13 @@ ItemOnCommand=visible,false [ScreenGrooveStatsOptions] Fallback="ScreenOptionsServiceChild" -LineNames="EnableGrooveStats,AutoDownloadUnlocks,SeparateUnlocksByPlayer,QRLogin" +LineNames="EnableGrooveStats,AutoDownloadUnlocks,SeparateUnlocksByPlayer,QRLogin,PrioritizeLocalLeaderboard" LineEnableGrooveStats="lua,ThemePrefsRows.GetRow('EnableGrooveStats')" LineAutoDownloadUnlocks="lua,ThemePrefsRows.GetRow('AutoDownloadUnlocks')" LineSeparateUnlocksByPlayer="lua,ThemePrefsRows.GetRow('SeparateUnlocksByPlayer')" LineQRLogin="lua,ThemePrefsRows.GetRow('QRLogin')" +LinePrioritizeLocalLeaderboard="lua,ThemePrefsRows.GetRow('PrioritizeLocalLeaderboard')" [ScreenTournamentModeOptions]