Effect Radar Implementation v1 #46

Merged
hersi merged 12 commits from feature/radar into master 2023-11-23 07:41:15 +01:00
1 changed files with 253 additions and 274 deletions
Showing only changes of commit a0ceb0bd01 - Show all commits

View File

@ -135,7 +135,7 @@ local top50diffs = {}
local irRequestStatus = 1 -- 0=unused, 1=not requested, 2=loading, others are status codes
local irRequestTimeout = 2
local irLeaderboard = {}
local irLeaderboard = {} ---@type ServerScore[]|{}
local irLeaderboardsCache = {}
local transitionScrollScale = 0
@ -162,6 +162,7 @@ local transitionSearchInfoEnterScale = 0
local transitionSearchBackgroundAlpha = 0
local transitionSearchbarOffsetY = 0
local transitionSearchInfoOffsetY = 0
local transitionSearchBackgroundInfoAlpha = Easing.inOutQuad(transitionSearchInfoEnterScale)
local transitionLaserScale = 0
local transitionLaserY = 0
@ -199,32 +200,32 @@ local resolutionChange = function(x, y)
game.Log('resX:' .. resX .. ' // resY:' .. resY .. ' // fullX:' .. fullX .. ' // fullY:' .. fullY, game.LOGGER_ERROR)
end
function getCorrectedIndex(from, offset)
total = #songwheel.songs
local function getCorrectedIndex(from, offset)
local total = #songwheel.songs
if (math.abs(offset) > total) then
if (offset < 0) then
if (offset < 0) then
offset = offset + total*math.floor(math.abs(offset)/total)
else
offset = offset - total*math.floor(math.abs(offset)/total)
end
end
index = from + offset
local index = from + offset
if index < 1 then
index = total + (from+offset) -- this only happens if the offset is negative
end
if index < 1 then
index = total + (from+offset) -- this only happens if the offset is negative
end
if index > total then
indexesUntilEnd = total - from
index = offset - indexesUntilEnd -- this only happens if the offset is positive
end
if index > total then
local indexesUntilEnd = total - from
index = offset - indexesUntilEnd -- this only happens if the offset is positive
end
return index
return index
end
function getJacketImage(song)
local function getJacketImage(song)
if not jacketCache[song.id] or jacketCache[song.id]==defaultJacketImage then
jacketCache[song.id] = gfx.LoadImageJob(song.difficulties[
math.min(selectedDifficulty, #song.difficulties)
@ -234,12 +235,12 @@ function getJacketImage(song)
return jacketCache[song.id]
end
function getGradeImageForScore(score)
local function getGradeImageForScore(score)
local gradeImage = gradeImages.none
local bestGradeCutoff = 0
for gradeName, scoreCutoff in pairs(gradeCutoffs) do
if scoreCutoff <= score then
if scoreCutoff > bestGradeCutoff then
if scoreCutoff > bestGradeCutoff then
gradeImage = gradeImages[gradeName]
bestGradeCutoff = scoreCutoff
end
@ -249,31 +250,30 @@ function getGradeImageForScore(score)
return gradeImage
end
function drawLaserAnim()
local function drawLaserAnim()
gfx.Save()
gfx.BeginPath()
gfx.Scissor(0, transitionLaserY, desw, 100)
gfx.ImageRect(0, 0, desw, desh, laserAnimBaseImage, 1, 0)
gfx.Restore()
end
function drawBackground(deltaTime)
local function drawBackground(deltaTime)
Background.draw(deltaTime)
local song = songwheel.songs[selectedIndex]
local diff = song and song.difficulties[selectedDifficulty] or false
if (not isFilterWheelActive and transitionLeaveReappearTimer == 0) then
-- If the score for song exists
if song and diff then
if song and diff then
local jacketImage = getJacketImage(song)
gfx.BeginPath()
gfx.ImageRect(transitionJacketBgScrollPosX, 0, 900, 900, jacketImage or defaultJacketImage, transitionJacketBgScrollAlpha, 0)
gfx.BeginPath()
gfx.FillColor(0,0,0,math.floor(transitionJacketBgScrollAlpha*64))
gfx.Rect(0,0,900,900)
@ -287,7 +287,7 @@ function drawBackground(deltaTime)
drawLaserAnim()
if song and diff and (not isFilterWheelActive and transitionLeaveReappearTimer == 0) then
if song and diff and (not isFilterWheelActive and transitionLeaveReappearTimer == 0) then
gfx.BeginPath()
gfx.ImageRect(0, 0, desw, desh, dataGlowOverlayImage, transitionAfterscrollDataOverlayAlpha, 0)
gfx.BeginPath()
@ -304,7 +304,9 @@ function drawBackground(deltaTime)
end
function drawSong(song, y)
---@param song SongWheelSong
---@param y number
local function drawSong(song, y)
if (not song) then return end
local songX = desw/2+28
@ -315,14 +317,14 @@ function drawSong(song, y)
end
local bestScore
if selectedSongDifficulty.scores then
if selectedSongDifficulty.scores then
bestScore = selectedSongDifficulty.scores[1]
end
-- Draw the bg for the song plate
gfx.BeginPath()
gfx.ImageRect(songX, y, 515, 172, songPlateBg, 1, 0)
-- Draw jacket
local jacketImage = getJacketImage(song)
gfx.BeginPath()
@ -331,7 +333,7 @@ function drawSong(song, y)
-- Draw the overlay for the song plate (that bottom black bar)
gfx.BeginPath()
gfx.ImageRect(songX, y, 515, 172, songPlateBottomBarOverlayImage, 1, 0)
-- Draw the difficulty notch background
gfx.BeginPath()
local diffIndex = Charting.GetDisplayDifficulty(selectedSongDifficulty.jacketPath, selectedSongDifficulty.difficulty)
@ -351,7 +353,7 @@ function drawSong(song, y)
if selectedSongDifficulty.topBadge then
badgeImage = badgeImages[selectedSongDifficulty.topBadge+1]
end
local badgeAlpha = 1
if (selectedSongDifficulty.topBadge >= 3) then
badgeAlpha = transitionFlashAlpha -- If hard clear or above, flash the badge
@ -364,7 +366,7 @@ function drawSong(song, y)
local gradeImage = gradeImages.none
local gradeAlpha = 1
if bestScore then
if bestScore then
gradeImage = getGradeImageForScore(bestScore.score)
if (bestScore.score >= gradeCutoffs.S) then
@ -376,13 +378,13 @@ function drawSong(song, y)
gfx.ImageRect(songX+391, y+47, 60, 60, gradeImage, gradeAlpha, 0)
-- Draw top 50 label if applicable
if (top50diffs[selectedSongDifficulty.id]) then
if (top50diffs[selectedSongDifficulty.hash]) then
gfx.BeginPath()
gfx.ImageRect(songX+82, y+109, 506*0.85, 26*0.85, top50OverlayImage, 1, 0)
end
end
function drawSongList()
local function drawSongList()
gfx.GlobalAlpha(1-transitionLeaveScale)
local numOfSongsAround = 7 -- How many songs should be up and how many should be down of the selected one
@ -395,7 +397,7 @@ function drawSongList()
drawSong(songwheel.songs[songIndex], desh/2-songPlateHeight/2-songPlateHeight*i + yOffset)
i=i+1
end
-- Draw the selected song
drawSong(songwheel.songs[selectedIndex], desh/2-songPlateHeight/2 + yOffset)
@ -409,131 +411,8 @@ function drawSongList()
gfx.GlobalAlpha(1)
end
function drawData() -- Draws the song data on the left panel
if isFilterWheelActive or transitionLeaveReappearTimer ~= 0 then return false end
local song = songwheel.songs[selectedIndex]
local diff = song and song.difficulties[selectedDifficulty] or false
local bestScore = diff and diff.scores[1]
if not song then return false end
local jacketImage = getJacketImage(song)
gfx.BeginPath()
gfx.ImageRect(96, 324, 348, 348, jacketImage or defaultJacketImage, 1, 0)
if (top50diffs[diff.id]) then
gfx.BeginPath()
gfx.ImageRect(96, 529, 410*0.85, 168*0.85, top50JacketOverlayImage, 1, 0)
end
-- Draw best score
gfx.Save()
gfx.BeginPath()
local scoreNumber = 0
if bestScore then
scoreNumber = bestScore.score
end
Numbers.draw_number(100, 793, 1.0, math.floor(scoreNumber / 10000), 4, scoreNumbers, true, 0.3, 1.12)
Numbers.draw_number(253, 798, 1.0, scoreNumber, 4, scoreNumbers, true, 0.22, 1.12)
-- Draw grade
local gradeImage = gradeImages.none
local gradeAlpha = transitionAfterscrollGradeAlpha
if bestScore then
gradeImage = getGradeImageForScore(bestScore.score)
if (transitionAfterscrollGradeAlpha == 1 and bestScore.score >= gradeCutoffs.S) then
gradeAlpha = transitionFlashAlpha -- If S, flash the badge
end
end
gfx.BeginPath()
gfx.ImageRect(360, 773, 45, 45, gradeImage, gradeAlpha, 0)
-- Draw badge
badgeImage = badgeImages[diff.topBadge+1]
local badgeAlpha = transitionAfterscrollBadgeAlpha
if (transitionAfterscrollBadgeAlpha == 1 and diff.topBadge >= 3) then
badgeAlpha = transitionFlashAlpha -- If hard clear or above, flash the badge, but only after the initial transition
end
gfx.BeginPath()
gfx.ImageRect(425, 724, 93/1.1, 81/1.1, badgeImage, badgeAlpha, 0)
gfx.Restore()
-- Draw BPM
gfx.Save()
gfx.BeginPath()
gfx.FontSize(24)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha) -- TODO: split this out
gfx.Text(song.bpm, 85, 920)
gfx.Restore()
-- Draw song title
gfx.Save()
gfx.FontSize(28)
gfx.GlobalAlpha(transitionAfterscrollTextSongTitle)
gfx.Text(song.title, 30+(1-transitionAfterscrollTextSongTitle)*20, 955)
gfx.Restore()
-- Draw artist
gfx.Save()
gfx.GlobalAlpha(transitionAfterscrollTextSongArtist)
gfx.Text(song.artist, 30+(1-transitionAfterscrollTextSongArtist)*30, 997)
gfx.Restore()
-- Draw difficulties
local DIFF_X_START = 98.5
local DIFF_GAP = 114.8
gfx.Save()
gfx.GlobalAlpha(transitionAfterscrollDifficultiesAlpha)
for i, diff in ipairs(song.difficulties) do
gfx.BeginPath()
local index = diff.difficulty+1
if i == selectedDifficulty then
gfx.ImageRect(DIFF_X_START+(index-1)*DIFF_GAP-(163*0.8)/2, 1028, 163*0.8, 163*0.8, diffCursorImage, 1, 0)
end
Numbers.draw_number(85+(index-1)*DIFF_GAP, 1085, 1.0, diff.level, 2, difficultyNumbers, false, 0.8, 1)
local diffLabelImage = difficultyLabelUnderImages[
Charting.GetDisplayDifficulty(diff.jacketPath, diff.difficulty)
]
local tw, th = gfx.ImageSize(diffLabelImage)
tw=tw*0.9
th=th*0.9
gfx.BeginPath()
gfx.ImageRect(DIFF_X_START+(index-1)*DIFF_GAP-tw/2, 1050, tw, th, diffLabelImage, 1, 0)
end
gfx.Restore()
-- Scoreboard
drawLocalLeaderboard(diff)
drawIrLeaderboard()
gfx.Save()
gfx.FontSize(22)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha)
gfx.Text(diff.effector, 270, 1180) -- effected by
gfx.Text(diff.illustrator, 270, 1210) -- illustrated by
gfx.Restore()
end
---@param diff SongWheelDifficulty
function drawLocalLeaderboard(diff)
local function drawLocalLeaderboard(diff)
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.FontSize(26)
@ -575,31 +454,32 @@ function drawLocalLeaderboard(diff)
gfx.Text(username or "-", sbBarContentLeftX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight)
gfx.BeginPath()
gfx.Text(score or "- - - - - - - -", sbBarContentRightX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight)
local scoreText = score and tostring(score) or "- - - - - - - -"
gfx.Text(scoreText, sbBarContentRightX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight)
end
end
function drawIrLeaderboard()
local function drawIrLeaderboard()
if not IRData.Active then
return
end
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.FontSize(26)
local scoreBoardX = 75
local scoreBoardY = 1500
local sbBarWidth = 336*1.2
local sbBarHeight = 33
local sbBarContentLeftX = scoreBoardX + 80
local sbBarContentRightX = scoreBoardX + sbBarWidth/2 + 30
-- Draw the header
gfx.BeginPath()
gfx.ImageRect(scoreBoardX, scoreBoardY, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0)
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE)
gfx.BeginPath()
@ -635,8 +515,8 @@ function drawIrLeaderboard()
-- Becuase the scores are in "random order", we have to do this
for index, irScore in ipairs(irLeaderboard) do
-- local irScore = irLeaderboard[i]
if irScore then
if irScore then
local rank = index
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE)
gfx.BeginPath()
@ -645,7 +525,7 @@ function drawIrLeaderboard()
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.BeginPath()
gfx.Text(string.upper(irScore.username), sbBarContentLeftX, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight)
gfx.BeginPath()
gfx.Text(string.format("%d", irScore.score), sbBarContentRightX, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight)
@ -656,7 +536,130 @@ function drawIrLeaderboard()
end
end
function drawFilterInfo(deltatime)
local function drawData() -- Draws the song data on the left panel
if isFilterWheelActive or transitionLeaveReappearTimer ~= 0 then return false end
local song = songwheel.songs[selectedIndex]
local diff = song and song.difficulties[selectedDifficulty] or false
local bestScore = diff and diff.scores[1]
if not song then return false end
local jacketImage = getJacketImage(song)
gfx.BeginPath()
gfx.ImageRect(96, 324, 348, 348, jacketImage or defaultJacketImage, 1, 0)
if (top50diffs[diff.hash]) then
gfx.BeginPath()
gfx.ImageRect(96, 529, 410*0.85, 168*0.85, top50JacketOverlayImage, 1, 0)
end
-- Draw best score
gfx.Save()
gfx.BeginPath()
local scoreNumber = 0
if bestScore then
scoreNumber = bestScore.score
end
Numbers.draw_number(100, 793, 1.0, math.floor(scoreNumber / 10000), 4, scoreNumbers, true, 0.3, 1.12)
Numbers.draw_number(253, 798, 1.0, scoreNumber, 4, scoreNumbers, true, 0.22, 1.12)
-- Draw grade
local gradeImage = gradeImages.none
local gradeAlpha = transitionAfterscrollGradeAlpha
if bestScore then
gradeImage = getGradeImageForScore(bestScore.score)
if (transitionAfterscrollGradeAlpha == 1 and bestScore.score >= gradeCutoffs.S) then
gradeAlpha = transitionFlashAlpha -- If S, flash the badge
end
end
gfx.BeginPath()
gfx.ImageRect(360, 773, 45, 45, gradeImage, gradeAlpha, 0)
-- Draw badge
local badgeImage = badgeImages[diff.topBadge+1]
local badgeAlpha = transitionAfterscrollBadgeAlpha
if (transitionAfterscrollBadgeAlpha == 1 and diff.topBadge >= 3) then
badgeAlpha = transitionFlashAlpha -- If hard clear or above, flash the badge, but only after the initial transition
end
gfx.BeginPath()
gfx.ImageRect(425, 724, 93/1.1, 81/1.1, badgeImage, badgeAlpha, 0)
gfx.Restore()
-- Draw BPM
gfx.Save()
gfx.BeginPath()
gfx.FontSize(24)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha) -- TODO: split this out
gfx.Text(song.bpm, 85, 920)
gfx.Restore()
-- Draw song title
gfx.Save()
gfx.FontSize(28)
gfx.GlobalAlpha(transitionAfterscrollTextSongTitle)
gfx.Text(song.title, 30+(1-transitionAfterscrollTextSongTitle)*20, 955)
gfx.Restore()
-- Draw artist
gfx.Save()
gfx.GlobalAlpha(transitionAfterscrollTextSongArtist)
gfx.Text(song.artist, 30+(1-transitionAfterscrollTextSongArtist)*30, 997)
gfx.Restore()
-- Draw difficulties
local DIFF_X_START = 98.5
local DIFF_GAP = 114.8
gfx.Save()
gfx.GlobalAlpha(transitionAfterscrollDifficultiesAlpha)
for i, diff in ipairs(song.difficulties) do
gfx.BeginPath()
local index = diff.difficulty+1
if i == selectedDifficulty then
gfx.ImageRect(DIFF_X_START+(index-1)*DIFF_GAP-(163*0.8)/2, 1028, 163*0.8, 163*0.8, diffCursorImage, 1, 0)
end
Numbers.draw_number(85+(index-1)*DIFF_GAP, 1085, 1.0, diff.level, 2, difficultyNumbers, false, 0.8, 1)
local diffLabelImage = difficultyLabelUnderImages[
Charting.GetDisplayDifficulty(diff.jacketPath, diff.difficulty)
]
local tw, th = gfx.ImageSize(diffLabelImage)
tw=tw*0.9
th=th*0.9
gfx.BeginPath()
gfx.ImageRect(DIFF_X_START+(index-1)*DIFF_GAP-tw/2, 1050, tw, th, diffLabelImage, 1, 0)
end
gfx.Restore()
-- Scoreboard
drawLocalLeaderboard(diff)
drawIrLeaderboard()
gfx.Save()
gfx.FontSize(22)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha)
gfx.Text(diff.effector, 270, 1180) -- effected by
gfx.Text(diff.illustrator, 270, 1210) -- illustrated by
gfx.Restore()
end
local function drawFilterInfo(deltatime)
gfx.LoadSkinFont('NotoSans-Regular.ttf')
if (songwheel.searchInputActive) then
@ -665,17 +668,17 @@ function drawFilterInfo(deltatime)
gfx.BeginPath()
gfx.ImageRect(5, 95, 417*0.85, 163*0.85, filterInfoBgImage, 1, 0)
local folderLabel = game.GetSkinSetting('_songWheelActiveFolderLabel')
local subFolderLabel = game.GetSkinSetting('_songWheelActiveSubFolderLabel')
local sortOptionLabel = game.GetSkinSetting('_songWheelActiveSortOptionLabel')
gfx.FontSize(24)
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE)
gfx.BeginPath()
gfx.Text(folderLabel or '', 167, 131)
gfx.BeginPath()
gfx.Text(subFolderLabel or '', 195, 166)
@ -686,7 +689,7 @@ function drawFilterInfo(deltatime)
gfx.Text(sortOptionLabel or '', desw-150, 130)
end
function drawCursor()
local function drawCursor()
if isFilterWheelActive or transitionLeaveScale ~= 0 then return false end
gfx.BeginPath()
@ -697,7 +700,7 @@ function drawCursor()
gfx.ImageRect(desw / 2 - 14, desh / 2 - 213 / 2, 555, 213, cursorImage, 1, 0)
end
function drawSearch()
local function drawSearch()
if (not songwheel.searchInputActive and searchPreviousActiveState) then
searchPreviousActiveState = false
game.PlaySample('sort_wheel/enter.wav')
@ -705,7 +708,7 @@ function drawSearch()
searchPreviousActiveState = true
game.PlaySample('sort_wheel/leave.wav')
end
if (songwheel.searchText ~= '' and searchInfoPreviousActiveState == true) then
searchInfoPreviousActiveState = false
elseif (songwheel.searchText == '' and searchInfoPreviousActiveState == false) then
@ -731,7 +734,7 @@ function drawSearch()
local infoXPos = 0
local infoYStartPos = desh - sh - 772 + 242
local infoYPos = infoYStartPos + transitionSearchInfoOffsetY
if (game.GetSkinSetting('gameplay_showSearchControls')) then
gfx.ImageRect(infoXPos, infoYPos, sw, sh, searchInfoPanelImage, transitionSearchBackgroundInfoAlpha, 0)
end
@ -767,7 +770,7 @@ function drawSearch()
gfx.Text(songwheel.searchText, xPos + 160, yPos + 83.2)
end
function drawScrollbar()
local function drawScrollbar()
if isFilterWheelActive or transitionLeaveScale ~= 0 then return end
-- Scrollbar Background
@ -810,7 +813,33 @@ function drawScrollbar()
end
end
function refreshIrLeaderboard(deltaTime)
---Called on IR Leaderboard fetch complete
---@param res IRLeaderboardResponse
local function onIrLeaderboardFetched(res)
irRequestStatus = res.statusCode
local song = songwheel.songs[selectedIndex]
local diff = song and song.difficulties[selectedDifficulty] or false
if res.statusCode == IRData.States.Success then
local tempIrLB = res.body
table.sort(tempIrLB, function (a,b)
return a.score > b.score
end)
irLeaderboard = tempIrLB
irLeaderboardsCache[diff.hash] = irLeaderboard
else
local httpStatus = (res.statusCode // 10) * 100 + res.statusCode % 10 -- convert to 100 range
game.Log("IR error (" .. httpStatus .. "): " .. res.description, game.LOGGER_ERROR)
if res.body then
game.Log(common.dump(res.body), game.LOGGER_ERROR)
end
end
end
local function refreshIrLeaderboard(deltaTime)
if not IRData.Active then
return
end
@ -839,56 +868,10 @@ function refreshIrLeaderboard(deltaTime)
end
irRequestStatus = 2 -- Loading
-- onIrLeaderboardFetched({
-- statusCode = 20,
-- body = {}
-- })
IR.Leaderboard(diff.hash, 'best', 4, onIrLeaderboardFetched)
end
function dump(o)
if type(o) == 'table' then
local s = '{ '
for k,v in pairs(o) do
if type(k) ~= 'number' then k = '"'..k..'"' end
s = s .. '['..k..'] = ' .. dump(v) .. ','
end
return s .. '} '
else
return tostring(o)
end
end
function onIrLeaderboardFetched(res)
irRequestStatus = res.statusCode
local song = songwheel.songs[selectedIndex]
local diff = song and song.difficulties[selectedDifficulty] or false
game.Log(diff.hash, game.LOGGER_ERROR)
if res.statusCode == IRData.States.Success then
game.Log('Raw IR reposonse: ' .. dump(res.body), game.LOGGER_ERROR)
local tempIrLB = res.body
table.sort(tempIrLB, function (a,b)
-- game.Log(a.score .. ' ?? ' .. b.score, game.LOGGER_ERROR)
return a.score > b.score
end)
-- for i, tempScore in ipairs(tempIrLeaderboard) do
-- irLeaderboard[tempScore.ranking] = tempScore
-- end
irLeaderboard = tempIrLB
irLeaderboardsCache[diff.hash] = irLeaderboard
game.Log(dump(irLeaderboard), game.LOGGER_ERROR)
else
game.Log("IR error " .. res.statusCode, game.LOGGER_ERROR)
end
end
function tickTransitions(deltaTime)
local function tickTransitions(deltaTime)
if transitionScrollScale < 1 then
transitionScrollScale = transitionScrollScale + deltaTime / 0.1 -- transition should last for that time in seconds
else
@ -904,7 +887,7 @@ function tickTransitions(deltaTime)
transitionAfterscrollScale = 1
end
if scrollingUp then
if scrollingUp then
transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * songPlateHeight
else
transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * -songPlateHeight
@ -949,8 +932,6 @@ function tickTransitions(deltaTime)
end
end
transitionSearchBackgroundInfoAlpha = Easing.inOutQuad(transitionSearchInfoEnterScale)
-- Grade alpha
if transitionAfterscrollScale >= 0.03 and transitionAfterscrollScale < 0.033 then
transitionAfterscrollGradeAlpha = 0.5
@ -959,7 +940,7 @@ function tickTransitions(deltaTime)
else
transitionAfterscrollGradeAlpha = 0
end
-- Badge alpha
if transitionAfterscrollScale >= 0.032 and transitionAfterscrollScale < 0.035 then
transitionAfterscrollBadgeAlpha = 0.5
@ -981,7 +962,7 @@ function tickTransitions(deltaTime)
else
transitionAfterscrollTextSongArtist = 1
end
-- Difficulties alpha
if transitionAfterscrollScale < 0.025 then
transitionAfterscrollDifficultiesAlpha = math.min(1, transitionAfterscrollScale / 0.025)
@ -1001,7 +982,7 @@ function tickTransitions(deltaTime)
elseif transitionJacketBgScrollScale >= 0.05 and transitionJacketBgScrollScale < 0.1 then
transitionJacketBgScrollAlpha = math.min(1, (transitionJacketBgScrollScale-0.05) / 0.05)
elseif transitionJacketBgScrollScale >= 0.8 and transitionJacketBgScrollScale < 1 then
transitionJacketBgScrollAlpha = math.max(0,
transitionJacketBgScrollAlpha = math.max(0,
math.min(1, 1-((transitionJacketBgScrollScale-0.8) / 0.05))
)
else
@ -1018,25 +999,17 @@ function tickTransitions(deltaTime)
end
transitionLaserY = desh - math.min(transitionLaserScale * 2 * desh, desh)
-- Flash transition
if transitionFlashScale < 1 then
---@type number|string
local songBpm = 120
if (songwheel.songs[selectedIndex] and game.GetSkinSetting('animations_affectWithBPM')) then
songBpm = songwheel.songs[selectedIndex].bpm
-- Is a variable BPM
if (type(songBpm) == "string") then
local s = common.split(songBpm, '-')
songBpm = tonumber(s[1]) -- Lowest bpm value
end
end
-- If the original songBpm is "2021.04.01" for example, the above code can produce `nil` in the songBpm
-- since it cannot parse the number out of that string. Here we implement a fallback, to not crash
-- USC on whacky charts. Whacky charters, quit using batshit insane bpm values. It makes me angery >:(
if (songBpm == nil) then
songBpm = 120
local songBpmStr = songwheel.songs[selectedIndex].bpm
local songBpmStrs = common.split(songBpmStr, '-')
local minBpm = tonumber(songBpmStrs[1]) -- Lowest bpm value
songBpm = minBpm or songBpm
end
transitionFlashScale = transitionFlashScale + deltaTime / (60/songBpm) -- transition should last for that time in seconds
@ -1107,7 +1080,7 @@ local function drawRadar()
gfx.Restore()
end
draw_songwheel = function(deltaTime)
local draw_songwheel = function(deltaTime)
drawBackground(deltaTime)
drawSongList()
@ -1132,13 +1105,14 @@ draw_songwheel = function(deltaTime)
local debugScrollingUp= "FALSE"
if scrollingUp then debugScrollingUp = "TRUE" end
if game.GetSkinSetting('debug_showInformation') then
if game.GetSkinSetting('debug_showInformation') then
gfx.Text('S_I: ' .. selectedIndex .. ' // S_D: ' .. selectedDifficulty .. ' // S_UP: ' .. debugScrollingUp .. ' // AC_TS: ' .. transitionAfterscrollScale .. ' // L_TS: ' .. transitionLeaveScale .. ' // IR_CODE: ' .. irRequestStatus .. ' // IR_T: ' .. irRequestTimeout, 8, 8)
end
gfx.ResetTransform()
end
---@diagnostic disable-next-line:lowercase-global
render = function (deltaTime)
tickTransitions(deltaTime)
@ -1164,6 +1138,7 @@ render = function (deltaTime)
refreshIrLeaderboard(deltaTime)
end
---@diagnostic disable-next-line:lowercase-global
songs_changed = function (withAll)
irLeaderboardsCache = {} -- Reset LB cache
@ -1173,30 +1148,33 @@ songs_changed = function (withAll)
game.SetSkinSetting('_songWheelScrollbarTotal', #songwheel.songs)
game.SetSkinSetting('_songWheelScrollbarIndex', selectedIndex)
local diffs = {}
for i = 1, #songwheel.allSongs do
local song = songwheel.allSongs[i]
for j = 1, #song.difficulties do
local diff = song.difficulties[j]
diff.force = VolforceCalc.calc(diff)
table.insert(diffs, diff)
end
end
table.sort(diffs, function (l, r)
return l.force > r.force
end)
totalForce = 0
for i = 1, 50 do
if diffs[i] then
top50diffs[diffs[i].id] = true
totalForce = totalForce + diffs[i].force
end
end
local diffs = {}
for i = 1, #songwheel.allSongs do
local song = songwheel.allSongs[i]
for j = 1, #song.difficulties do
local diff = song.difficulties[j]
table.insert(diffs, {hash = diff.hash, force = VolforceCalc.calc(diff)})
end
end
table.sort(diffs, function (l, r)
return l.force > r.force
end)
local totalForce = 0
for i = 1, 50 do
local diff = diffs[i]
if not diff then
break
end
top50diffs[diff.hash] = true
totalForce = totalForce + diff.force
end
game.SetSkinSetting('_volforce', totalForce)
end
---@diagnostic disable-next-line:lowercase-global
set_index = function(newIndex)
transitionScrollScale = 0
transitionAfterscrollScale = 0
@ -1206,22 +1184,23 @@ set_index = function(newIndex)
game.SetSkinSetting('_songWheelScrollbarTotal', #songwheel.songs)
game.SetSkinSetting('_songWheelScrollbarIndex', newIndex)
scrollingUp = false
if ((newIndex > selectedIndex and not (newIndex == #songwheel.songs and selectedIndex == 1)) or (newIndex == 1 and selectedIndex == #songwheel.songs)) then
scrollingUp = true
end
scrollingUp = false
if ((newIndex > selectedIndex and not (newIndex == #songwheel.songs and selectedIndex == 1)) or (newIndex == 1 and selectedIndex == #songwheel.songs)) then
scrollingUp = true
end
updateRadar = true
game.PlaySample('song_wheel/cursor_change.wav')
game.PlaySample('song_wheel/cursor_change.wav')
selectedIndex = newIndex
end
local json = require("common.json")
---@diagnostic disable-next-line:lowercase-global
set_diff = function(newDiff)
if newDiff ~= selectedDifficulty then
if newDiff ~= selectedDifficulty then
jacketCache = {} -- Clear the jacket cache for the new diff jackets
game.PlaySample('song_wheel/diff_change.wav')