Effect Radar Implementation v1 #46
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue