diff --git a/Themes/Til Death/BGAnimations/ScreenOnlineScoreTabOffsetPlot overlay.lua b/Themes/Til Death/BGAnimations/ScreenOnlineScoreTabOffsetPlot overlay.lua new file mode 100644 index 0000000000..dd68541e92 --- /dev/null +++ b/Themes/Til Death/BGAnimations/ScreenOnlineScoreTabOffsetPlot overlay.lua @@ -0,0 +1,106 @@ +-- if score is ever nil we done goofed way before this screen is ever loaded -mina +local score = getOnlineScoreForPlot() +local replayData = score.replaydata + +local tst = { 1.50,1.33,1.16,1.00,0.84,0.66,0.50,0.33,0.20 } +local plotWidth, plotHeight = SCREEN_WIDTH,SCREEN_WIDTH*0.3 +local plotX, plotY = SCREEN_CENTER_X, SCREEN_CENTER_Y +local dotDims, plotMargin = 2, 4 +local judge = GetTimingDifficulty() +local maxOffset = math.max(180, 180*tst[judge]) + +local o = Def.ActorFrame{ + InitCommand=function(self) + self:xy(plotX,plotY) + end, + CodeMessageCommand=function(self,params) + if params.Name == "PlotCancel" or params.Name == "PlotExit" or params.Name == "PlotThickens" or params.Name == "PlotTwist" or params.Name == "StarPlot64" or params.Name == "SheriffOfPlottingham" then + SCREENMAN:GetTopScreen():Cancel() + end + if params.Name == "PrevJudge" and judge > 1 then + judge = judge - 1 + elseif params.Name == "NextJudge" and judge < 9 then + judge = judge + 1 + end + maxOffset = math.max(180, 180*tst[judge]) + MESSAGEMAN:Broadcast("JudgeDisplayChanged") + end +} + +local td = GAMESTATE:GetCurrentSteps(PLAYER_1):GetTimingData() +local finalSecond = GAMESTATE:GetCurrentSong(PLAYER_1):GetLastSecond() + +local function fitX(x) -- Scale time values to fit within plot width. + return x/finalSecond*plotWidth - plotWidth/2 +end + +local function fitY(y) -- Scale offset values to fit within plot height + return -1*y/maxOffset*plotHeight/2 +end + +local function plotOffset(nr,dv) + if dv == 1000 then -- 1000 denotes a miss for which we use a different marker + return Def.Quad{ + InitCommand=function(self) + self:xy(fitX(nr),fitY(math.max(184, tst[judge]*184))):zoomto(dotDims,dotDims):diffuse(offsetToJudgeColor(dv/1000)):valign(0) + end + } + end + return Def.Quad{ + InitCommand=function(self) + self:xy(fitX(nr),fitY(dv)):zoomto(dotDims,dotDims):diffuse(offsetToJudgeColor(dv/1000)) + end, + JudgeDisplayChangedMessageCommand=function(self) + local pos = fitY(dv) + if math.abs(pos) > plotHeight/2 then + self:y(fitY(math.max(184, tst[judge]*184))) + else + self:y(pos) + end + self:diffuse(offsetToJudgeColor(dv/1000, tst[judge])) + end + } +end + +-- Center Bar +o[#o+1] = Def.Quad{InitCommand=function(self) + self:zoomto(plotWidth+plotMargin,1):diffuse(byJudgment("TapNoteScore_W1")) +end} +local fantabars = {22.5, 45, 90, 135} +local bantafars = {"TapNoteScore_W2", "TapNoteScore_W3", "TapNoteScore_W4", "TapNoteScore_W5"} +for i=1, #fantabars do + o[#o+1] = Def.Quad{InitCommand=function(self) + self:y( fitY(tst[judge]*fantabars[i])): zoomto(plotWidth+plotMargin,1):diffuse(byJudgment(bantafars[i])) + end} + o[#o+1] = Def.Quad{InitCommand=function(self) + self:y( fitY(-tst[judge]*fantabars[i])): zoomto(plotWidth+plotMargin,1):diffuse(byJudgment(bantafars[i])) + end} +end +-- Background +o[#o+1] = Def.Quad{InitCommand=function(self) + self:zoomto(plotWidth+plotMargin,plotHeight+plotMargin):diffuse(color("0.05,0.05,0.05,0.05")):diffusealpha(0.95) +end} +-- Convert noterows to timestamps and plot dots +for i=1,#replayData do + o[#o+1] = plotOffset(replayData[i][1], replayData[i][2]) +end + +-- Early/Late markers +o[#o+1] = LoadFont("Common Normal")..{ + InitCommand=function(self) + self:xy(-plotWidth/2,-plotHeight/2+2):settextf("Late (+%ims)", maxOffset):zoom(0.35):halign(0):valign(0) + end, + JudgeDisplayChangedMessageCommand=function(self) + self:settextf("Late (+%ims)", maxOffset) + end +} +o[#o+1] = LoadFont("Common Normal")..{ + InitCommand=function(self) + self:xy(-plotWidth/2,plotHeight/2-2):settextf("Early (-%ims)", maxOffset):zoom(0.35):halign(0):valign(1) + end, + JudgeDisplayChangedMessageCommand=function(self) + self:settextf("Early (-%ims)", maxOffset) + end +} + +return o \ No newline at end of file diff --git a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua index 0bc157105b..dec1957a68 100644 --- a/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua +++ b/Themes/Til Death/BGAnimations/ScreenSelectMusic decorations/score.lua @@ -18,7 +18,6 @@ local offsetX = 10 local offsetY = 30 local netScoresPerPage = 5 local netScoresCurrentPage = 1 -local netScores = {} local nestedTabButtonWidth = 50 local nestedTabButtonHeight = offsetY*2/3 local netPageButtonWidth = 40 @@ -519,38 +518,18 @@ local netscoreframeWidth = capWideScale(get43size(300),300) local netscorespacing = 34 local netscoreframex = capWideScale(get43size(70),70) local netscoreframey = offsetY+netscorespacing/2+capWideScale(get43size(70),70) +function updateNetScores(self) + if not (netScoresCurrentPage < math.ceil(DLMAN:GetTopChartScoreCount(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey())/netScoresPerPage)) then + netScoresCurrentPage = 1 + end + MESSAGEMAN:Broadcast("NetScoreUpdate") +end local netTab = Def.ActorFrame { - SetCommand = function(self) - netScores = {} - local steps = GAMESTATE:GetCurrentSteps(PLAYER_1) - if steps and GAMESTATE:GetCurrentSong() then - local ck = GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey() - for i=1,DLMAN:GetTopChartScoreCount(ck) do - netScores[i] = DLMAN:GetTopChartScore(ck, i) - end - end - if not (netScoresCurrentPage < math.ceil(#netScores/netScoresPerPage)) then - netScoresCurrentPage = 1 - end - MESSAGEMAN:Broadcast("NetScoreUpdate") - end, - ChartLeaderboardUpdateCommand = function(self) - self:queuecommand("Set") - end, ChartLeaderboardUpdateMessageCommand = function(self) - self:queuecommand("Set") + updateNetScores(self) end, - PlayerJoinedMessageCommand=function(self) - self:queuecommand("Set") - end, - CurrentSongChangedMessageCommand=function(self) - self:queuecommand("Set") - end, - CurrentStepsP1ChangedMessageCommand=function(self) - self:queuecommand("Set") - end, - CurrentStepsP2ChangedMessageCommand=function(self) - self:queuecommand("Set") + CurrentStepsP1ChangedMessageCommand=function(self) + updateNetScores(self) end, VisibilityCommand=function(self) self:visible(nestedTab == 2) @@ -576,7 +555,7 @@ local netTab = Def.ActorFrame { if netScoresCurrentPage > 1 then netScoresCurrentPage = netScoresCurrentPage - 1 else - netScoresCurrentPage = math.ceil(#netScores/netScoresPerPage) + netScoresCurrentPage = math.ceil(DLMAN:GetTopChartScoreCount(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey())/netScoresPerPage) end MESSAGEMAN:Broadcast("NetScoreUpdate") end @@ -602,7 +581,7 @@ local netTab = Def.ActorFrame { end, MouseLeftClickMessageCommand=function(self) if ButtonActive(self) and update and nestedTab == 2 then - if netScoresCurrentPage < math.ceil(#netScores/netScoresPerPage) then + if netScoresCurrentPage < math.ceil(DLMAN:GetTopChartScoreCount(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey())/netScoresPerPage) then netScoresCurrentPage = netScoresCurrentPage + 1 else netScoresCurrentPage = 1 @@ -623,22 +602,32 @@ local netTab = Def.ActorFrame { } } local function netscoreitem(drawindex) + local tmpScore + local index = drawindex local t = Def.ActorFrame { Name="scoreItem"..tostring(i), - SetCommand=function(self) - self:visible(nestedTab == 2 and netScores ~= nil and netScores[drawindex + (netScoresCurrentPage-1)*netScoresPerPage] ~= nil) - end, NetScoreUpdateMessageCommand=function(self) - self:queuecommand("Set") + index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage + tmpScore = DLMAN:GetTopChartScore(GAMESTATE:GetCurrentSteps(PLAYER_1):GetChartKey(), index) + self:visible(nestedTab == 2 and tmpScore ~= nil) end, NestedTabChangedMessageCommand=function(self) - self:queuecommand("Set") + self:visible(nestedTab == 2 and tmpScore ~= nil) end, --The main quad Def.Quad{ InitCommand=function(self) self:xy(netscoreframex,netscoreframey+(drawindex*netscorespacing)):zoomto(netscoreframeWidth,30):halign(0):valign(0):diffuse(color("#444444")):diffusealpha(1) end, + NetScoreUpdateMessageCommand=function(self) + self:diffuse(tmpScore and tmpScore.replaydata and color("#666666") or color("#444444")) + end, + MouseLeftClickMessageCommand=function(self) + if ButtonActive(self) and update and nestedTab == 2 and tmpScore and tmpScore.replaydata then + setOnlineScoreForPlot(tmpScore) + SCREENMAN:AddNewScreenToTop("ScreenOnlineScoreTabOffsetPlot") + end + end }, --rank LoadFont("Common normal")..{ @@ -646,8 +635,7 @@ local function netscoreitem(drawindex) self:xy(netscoreframex-8,netscoreframey+netscorespacing/2+(drawindex*netscorespacing)-2):zoom(0.35) end, SetCommand=function(self) - local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage - if netScores[index] then + if tmpScore then self:settext(index) else self:settext("") @@ -667,9 +655,8 @@ local function netscoreitem(drawindex) self:xy(netscoreframex+10,netscoreframey+10+(drawindex*netscorespacing)+4):zoom(0.35):halign(0):maxwidth((netscoreframeWidth-15)/0.35) end, SetCommand=function(self) - local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage - if netScores[index] then - self:settext(netScores[index].modifiers) + if tmpScore then + self:settext(tmpScore.modifiers) else self:settext("") end @@ -688,8 +675,7 @@ local function netscoreitem(drawindex) self:xy(netscoreframex+130+capWideScale(get43size(0),50),netscoreframey+2+(drawindex*netscorespacing)):zoom(0.35):halign(0.5):maxwidth((netscoreframeWidth-15)/0.35) end, SetCommand=function(self) - local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage - if netScores[index] then + if tmpScore then --self:settext(calcGradeFromWife(netScores[index].wife)) else self:settext("") @@ -709,17 +695,16 @@ local function netscoreitem(drawindex) self:xy(netscoreframex+10,netscoreframey+(drawindex*netscorespacing)+4):zoom(0.35):halign(0):maxwidth((netscoreframeWidth-15)/0.35) end, SetCommand=function(self) - local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage - if netScores[index] then + if tmpScore then self:settextf("%05.5f%% (Wife) %d / %d / %d / %d / %d / %d x%d", - netScores[index].wife*10000/100, - netScores[index].marvelous, - netScores[index].perfect, - netScores[index].great, - netScores[index].good, - netScores[index].bad, - netScores[index].miss, - netScores[index].maxcombo) + tmpScore.wife*10000/100, + tmpScore.marvelous, + tmpScore.perfect, + tmpScore.great, + tmpScore.good, + tmpScore.bad, + tmpScore.miss, + tmpScore.maxcombo) else self:settext("") end @@ -739,9 +724,8 @@ local function netscoreitem(drawindex) self:xy(netscoreframex+10,netscoreframey+20+(drawindex*netscorespacing)+4):zoom(0.35):halign(0) end, SetCommand=function(self) - local index = drawindex + (netScoresCurrentPage-1)*netScoresPerPage - if netScores[index] then - self:settext(netScores[index].datetime.." "..netScores[index].username) + if tmpScore then + self:settext(tmpScore.datetime.." "..tmpScore.username) else self:settext("") end diff --git a/Themes/Til Death/Scripts/Scores.lua b/Themes/Til Death/Scripts/Scores.lua index 4284b8a871..e7916b8456 100644 --- a/Themes/Til Death/Scripts/Scores.lua +++ b/Themes/Til Death/Scripts/Scores.lua @@ -76,6 +76,10 @@ local migsWeight = { -- Score Weights for MIGS score local ScoreForPlot = nil function setScoreForPlot(hs) ScoreForPlot = hs end function getScoreForPlot() return ScoreForPlot end +--Same as above for online scores +local NetScoreForPlot = nil +function setOnlineScoreForPlot(hs) NetScoreForPlot = hs end +function getOnlineScoreForPlot() return NetScoreForPlot end diff --git a/Themes/Til Death/metrics.ini b/Themes/Til Death/metrics.ini index 4cf70c3a7d..4d09462863 100644 --- a/Themes/Til Death/metrics.ini +++ b/Themes/Til Death/metrics.ini @@ -251,6 +251,10 @@ CodePlotTwist="MenuRight" CodeStarPlot64="MenuUp" CodeSheriffOfPlottingham="MenuDown" + +[ScreenOnlineScoreTabOffsetPlot] +Fallback="ScreenScoreTabOffsetPlot" + [ScreenColorChange] Class="ScreenWithMenuElements" Fallback="ScreenWithMenuElements" diff --git a/src/DownloadManager.cpp b/src/DownloadManager.cpp index 3c5efc3d14..3d9f5405d1 100644 --- a/src/DownloadManager.cpp +++ b/src/DownloadManager.cpp @@ -568,8 +568,6 @@ bool DownloadManager::ShouldUploadScores() inline void SetCURLPOSTScore(CURL*& curlHandle, curl_httppost*& form, curl_httppost*& lastPtr, HighScore*& hs) { SetCURLFormPostField(curlHandle, form, lastPtr, "scorekey", hs->GetScoreKey()); - FOREACH_ENUM(Skillset, ss) - SetCURLFormPostField(curlHandle, form, lastPtr, SkillsetToString(ss), hs->GetSkillsetSSR(ss)); SetCURLFormPostField(curlHandle, form, lastPtr, "ssr_norm", hs->GetSSRNormPercent()); SetCURLFormPostField(curlHandle, form, lastPtr, "max_combo", hs->GetMaxCombo()); SetCURLFormPostField(curlHandle, form, lastPtr, "valid", static_cast(hs->GetEtternaValid())); @@ -588,8 +586,7 @@ inline void SetCURLPOSTScore(CURL*& curlHandle, curl_httppost*& form, curl_httpp SetCURLFormPostField(curlHandle, form, lastPtr, "chartkey", hs->GetChartKey()); SetCURLFormPostField(curlHandle, form, lastPtr, "rate", hs->GetMusicRate()); auto chart = SONGMAN->GetStepsByChartkey(hs->GetChartKey()); - SetCURLFormPostField(curlHandle, form, lastPtr, "has_negative_BPM", chart->GetTimingData()->HasWarps()); - SetCURLFormPostField(curlHandle, form, lastPtr, "is_dance_single", chart->m_StepsType == StepsType_dance_single); + SetCURLFormPostField(curlHandle, form, lastPtr, "negsolo", chart->GetTimingData()->HasWarps() && chart->m_StepsType == StepsType_dance_single); SetCURLFormPostField(curlHandle, form, lastPtr, "cc", static_cast(!hs->GetChordCohesion())); SetCURLFormPostField(curlHandle, form, lastPtr, "calc_version", hs->GetSSRCalcVersion()); SetCURLFormPostField(curlHandle, form, lastPtr, "topscore", hs->GetTopScore()); @@ -644,10 +641,16 @@ void DownloadManager::UploadScoreWithReplayData(HighScore* hs) SetCURLFormPostField(curlHandle, form, lastPtr, "replay_data", replayString); SetCURLPostToURL(curlHandle, url); AddSessionCookieToCURL(curlHandle); - curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); + curl_easy_setopt(curlHandle, CURLOPT_HTTPPOST, form); function done = [hs](HTTPRequest& req) { - if (req.result == "\"Success\"") { - hs->AddUploadedServer(serverURL.Get()); + Json::Value json; + RString error; + hs->AddUploadedServer(serverURL.Get()); + if (JsonUtil::LoadFromString(json, req.result, error) && json.isMember("success") && !json.isMember("error")) { + auto ratings = json.get("success", ""); + FOREACH_ENUM(Skillset, ss) + (DLMAN->sessionRatings)[ss] = atof(ratings.get(SkillsetToString(ss), "0.0").asCString()); + (DLMAN->sessionRatings)[Skill_Overall] = atof(ratings.get("player_rating", "0.0").asCString()); } }; HTTPRequest* req = new HTTPRequest(curlHandle, done); @@ -777,6 +780,9 @@ void DownloadManager::RequestChartLeaderBoard(string chartkey) return; vector & vec = DLMAN->chartLeaderboards[chartkey]; vec.clear(); + LOG->Trace(req.result.c_str()); + LOG->Trace(json.toStyledString().c_str()); + LOG->Flush(); for (auto it = json.begin(); it != json.end(); ++it) { OnlineScore tmp; tmp.wife = atof((*it).get("wifescore", "0.0").asCString()); @@ -796,9 +802,18 @@ void DownloadManager::RequestChartLeaderBoard(string chartkey) tmp.nocc = (*it).get("nocc", "0").asBool(); tmp.valid = (*it).get("valid", "0").asBool(); FOREACH_ENUM(Skillset, ss) - tmp.SSRs[ss] = atof((*it).get(SkillsetToString(ss).c_str(), "0.0").asCString()); - //todo:replaydata from "replay" field - vec.push_back(tmp); + tmp.SSRs[ss] = ((*it).isMember(SkillsetToString(ss).c_str()) && (*it).isNull()) ? 0.0f : atof((*it).get(SkillsetToString(ss).c_str(), "0.0").asCString()); + //todo:replays + auto rd = (*it)["replay"]; + auto s = rd.toStyledString(); + if(s.length()>2) + s = s.substr(1, s.length() - 2); + Json::Value rdj; + + if (JsonUtil::LoadFromString(rdj, s, error)) + for (auto itt = rdj.begin(); itt != rdj.end(); itt++) + tmp.replayData.emplace_back(make_pair((*itt)[0u].asDouble(), (*itt)[1 ].asDouble())); + vec.emplace_back(tmp); } MESSAGEMAN->Broadcast("ChartLeaderboardUpdate"); }; @@ -957,6 +972,8 @@ void DownloadManager::StartSession(string user, string pass) FOREACH_ENUM(Skillset, ss) DLMAN->RefreshTop25(ss); DLMAN->UploadScores(); + if (GAMESTATE->m_pCurSteps[PLAYER_1] != nullptr) + DLMAN->RequestChartLeaderBoard(GAMESTATE->m_pCurSteps[PLAYER_1]->GetChartKey()); MESSAGEMAN->Broadcast("Login"); } else { @@ -1232,25 +1249,24 @@ class LunaDownloadManager : public Luna } static int GetTopChartScoreCount(T* p, lua_State* L) { - lua_pushnumber(L, DLMAN->chartLeaderboards[SArg(1)].size()); + string ck = SArg(1); + if (DLMAN->chartLeaderboards.count(ck)) + lua_pushnumber(L, DLMAN->chartLeaderboards[ck].size()); + else + lua_pushnumber(L, 0); return 1; } static int GetTopChartScore(T* p, lua_State* L) { string chartkey = SArg(1); - unsigned int rank = IArg(2); - bool result; - unsigned int index = rank - 1; + int rank = IArg(2); + int index = rank - 1; if (!DLMAN->chartLeaderboards.count(chartkey) || index >= DLMAN->chartLeaderboards[chartkey].size()) { lua_pushnil(L); return 1; } auto& score = DLMAN->chartLeaderboards[chartkey][index]; - if (!result) { - lua_pushnil(L); - return 1; - } - lua_createtable(L, 0, 17 + NUM_Skillset); + lua_createtable(L, 0, 17 + NUM_Skillset + (score.replayData.empty() ? 0 : 1)); FOREACH_ENUM(Skillset, ss) { lua_pushnumber(L, score.SSRs[ss]); lua_setfield(L, -2, SkillsetToString(ss).c_str()); @@ -1289,6 +1305,19 @@ class LunaDownloadManager : public Luna lua_setfield(L, -2, "username"); lua_pushstring(L, score.datetime.GetString().c_str()); lua_setfield(L, -2, "datetime"); + if (!score.replayData.empty()) { + lua_createtable(L, 0, score.replayData.size()); + int i = 1; + for (auto& pair : score.replayData) { + lua_createtable(L, 0, 2); + lua_pushnumber(L, pair.first); + lua_rawseti(L, -2, 1); + lua_pushnumber(L, pair.second); + lua_rawseti(L, -2, 2); + lua_rawseti(L, -2, i++); + } + lua_setfield(L, -2, "replaydata"); + } return 1; } static int GetFilteredAndSearchedPackList(T* p, lua_State* L) diff --git a/src/XMLProfile.cpp b/src/XMLProfile.cpp index 6bb14b6fc7..0f490939a1 100644 --- a/src/XMLProfile.cpp +++ b/src/XMLProfile.cpp @@ -1145,7 +1145,7 @@ XNode *XMLProfile::SaveEttXmlCreateNode(const Profile* profile) const if (!profile->PermaMirrorCharts.empty()) xml->AppendChild(SavePermaMirrorCreateNode(profile)); - if (!loadingProfile->allplaylists.empty()) + if (!profile->allplaylists.empty()) xml->AppendChild(SavePlaylistsCreateNode(profile)); if (!profile->goalmap.empty())