ExperimentalGear/scripts/result.lua

1006 lines
33 KiB
Lua
Raw Normal View History

local Easing = require('common.easing');
2022-05-06 00:05:20 +02:00
local Charting = require('common.charting');
local Background = require('components.background');
2021-08-09 20:19:11 +02:00
local Footer = require('components.footer');
2022-05-06 00:05:20 +02:00
local Numbers = require('components.numbers')
local DiffRectangle = require('components.diff_rectangle');
2021-10-23 23:20:57 +02:00
local lang = require("language.call")
local DanBadge = require("components.danbadge");
require('common.gameconfig')
2021-07-27 21:18:13 +02:00
2022-05-06 16:39:54 +02:00
local crew = game.GetSkinSetting("single_idol")
local betacrew = game.GetSkinSetting("beta_idol")
2022-06-05 03:12:34 +02:00
local staticcrew = game.GetSkinSetting("static_idol")
2022-05-06 16:39:54 +02:00
local bad = "/bad"
local okay = "/okay"
local veryokay = "/good"
local idle = "/idle"
2022-06-05 03:12:34 +02:00
local static = "/static"
2021-10-25 19:43:11 +02:00
2021-08-12 21:21:42 +02:00
local VolforceWindow = require('components.volforceWindow')
local VolforceAmount = game.GetSkinSetting('_volforce');
2021-08-12 21:21:42 +02:00
-- Window variables
local resX, resY
-- Aspect Ratios
local landscapeWidescreenRatio = 16 / 9
local landscapeStandardRatio = 4 / 3
local portraitWidescreenRatio = 9 / 16
-- Portrait sizes
local fullX, fullY
2021-07-27 20:00:02 +02:00
local desw = 1080
local desh = 1920
2021-07-25 20:10:06 +02:00
local function resolutionChange(x, y)
resX = x
resY = y
fullX = portraitWidescreenRatio * y
fullY = y
end
2021-07-27 20:00:02 +02:00
local bgSfxPlayed = false;
2021-07-25 20:10:06 +02:00
local backgroundImage = gfx.CreateSkinImage("bg_pattern.png", gfx.IMAGE_REPEATX | gfx.IMAGE_REPEATY)
2021-07-27 21:18:13 +02:00
local topBarImage = gfx.CreateSkinImage("result/top_bar.png", 0);
local jacketPanelImage = gfx.CreateSkinImage("result/panels/jacket.png", 0);
local rightPanelImage = gfx.CreateSkinImage("result/panels/right.png", 0);
local bottomPanelImage = gfx.CreateSkinImage("result/panels/bottom.png", 0);
2021-10-23 23:20:57 +02:00
local cMOD = gfx.CreateSkinImage("result/panels/cmod.png",0);
local warn = gfx.CreateSkinImage("result/panels/warning.png",0);
2021-07-27 21:18:13 +02:00
local defaultJacketImage = gfx.CreateSkinImage("result/default_jacket.png", 0);
2021-07-27 21:18:13 +02:00
local bestScoreBadgeImage = gfx.CreateSkinImage("result/best.png", 0);
local defaultCardImage = gfx.CreateSkinImage("result/default_appeal_card.png", 0)
local defaultBadgeImage = gfx.CreateSkinImage("result/default_dan.png", 0)
2021-10-25 21:39:16 +02:00
local appealCardImage = gfx.CreateSkinImage("crew/appeal_card.png", 0);
local danBadgeImage = DanBadge(false)
2021-10-22 21:12:48 +02:00
local badgeLines = gfx.CreateSkinImage("result/badge_lines.png", 0);
2021-10-22 22:00:58 +02:00
local badgeGrade = gfx.CreateSkinImage("result/badge_gradient.png", 0);
2021-07-28 18:50:06 +02:00
local irpanelsB = gfx.CreateSkinImage("result/panels/new_score_blue.png", 0);
local irpanelsO = gfx.CreateSkinImage("result/panels/new_score_orange.png", 0);
local arrow = gfx.CreateSkinImage("result/arrow.png", 0);
local IrPanelBlueW, IrPanelBlueH = gfx.ImageSize(irpanelsB)
local IrPanelOrangeW, IrPanelOrangeH = gfx.ImageSize(irpanelsO)
local ArrowW, ArrowH = gfx.ImageSize(arrow)
local height
2022-07-05 20:44:14 +02:00
local irGB = {
string.upper("New Global ");
string.upper("New Local ");
string.upper(" Score!");
string.upper("New Score!");
string.upper("Update!")
}
local scoreNumber = Numbers.load_number_image("score_num");
2022-01-03 08:42:58 +01:00
2022-05-06 00:05:20 +02:00
local gaugeTypeMirrorImage = gfx.CreateSkinImage("result/gauge_type_badges/mirror.png", 0);
local gaugeTypeRandomImage = gfx.CreateSkinImage("result/gauge_type_badges/random.png", 0);
local gaugeTypeMirrorRandomImage = gfx.CreateSkinImage("result/gauge_type_badges/random_mirror.png", 0);
2021-07-28 16:35:34 +02:00
local gradeImages = {
2021-07-31 16:48:14 +02:00
S = gfx.CreateSkinImage("common/grades/S.png", 0),
AAA_P = gfx.CreateSkinImage("common/grades/AAA+.png", 0),
AAA = gfx.CreateSkinImage("common/grades/AAA.png", 0),
AA_P = gfx.CreateSkinImage("common/grades/AA+.png", 0),
AA = gfx.CreateSkinImage("common/grades/AA.png", 0),
A_P = gfx.CreateSkinImage("common/grades/A+.png", 0),
A = gfx.CreateSkinImage("common/grades/A.png", 0),
B = gfx.CreateSkinImage("common/grades/B.png", 0),
C = gfx.CreateSkinImage("common/grades/C.png", 0),
2021-08-19 20:16:22 +02:00
D = gfx.CreateSkinImage("common/grades/D.png", 0)
2021-07-28 16:35:34 +02:00
}
2022-05-06 16:39:54 +02:00
local grades = {
D = 6900000,
C = 7900000,
B = 8600000,
A = 8900000,
A_P = 9200000,
AA = 9400000,
AA_P = 9600000,
AAA = 9700000,
AAA_P = 9800000,
S = 9900000
}
2022-05-06 16:39:54 +02:00
local gaugeTypeBadgeImages = {
gfx.CreateSkinImage("result/gauge_type_badges/effective.png", 0),
gfx.CreateSkinImage("result/gauge_type_badges/excessive.png", 0),
gfx.CreateSkinImage("result/gauge_type_badges/permissive.png", 0),
2021-10-22 22:00:58 +02:00
gfx.CreateSkinImage("result/gauge_type_badges/blastive.png", 0),
gfx.CreateSkinImage("result/gauge_type_badges/effective.png", 0), -- placeholders in case other types get added
2021-08-19 20:16:22 +02:00
gfx.CreateSkinImage("result/gauge_type_badges/effective.png", 0)
}
local gaugeEffFailFillImage = gfx.CreateSkinImage("gameplay/gauges/effective/gauge_fill_fail.png",0)
local gaugeEffPassFillImage = gfx.CreateSkinImage("gameplay/gauges/effective/gauge_fill_pass.png",0)
local gaugeExcFillImage = gfx.CreateSkinImage("gameplay/gauges/excessive/gauge_result_fill.png", 0)
local gaugePermFillImage = gfx.CreateSkinImage("gameplay/gauges/permissive/gauge_fill.png", 0)
local gaugeBlastiveFillImage = gfx.CreateSkinImage("gameplay/gauges/blastive/gauge_fill.png", 0)
2021-08-06 19:57:00 +02:00
local clearBadgeImages = {
{
image = gfx.CreateSkinImage("result/clears/SAVED.png", 0),
xPos = 970
},
{
image = gfx.CreateSkinImage("result/clears/CRASH.png", 0),
xPos = 970
},
{
image = gfx.CreateSkinImage("result/clears/COMPLETE.png", 0),
xPos = 1090
},
{
image = gfx.CreateSkinImage("result/clears/COMPLETE.png", 0),
xPos = 1090
},
{
image = gfx.CreateSkinImage("result/clears/UC.png", 0),
xPos = 1150
},
{
image = gfx.CreateSkinImage("result/clears/PUC.png", 0),
xPos = 1080
},
{
image = gfx.CreateSkinImage("result/clears/AUTOPLAY.png", 0),
2021-10-22 21:12:48 +02:00
xPos = 1100
},
2021-08-06 19:57:00 +02:00
}
if not idolAnimation then
game.Log("Crew folder crew/anim/"..crew.." does not exist.", game.LOGGER_WARNING)
end
2021-07-27 21:18:13 +02:00
local transitionEnterScale = 0;
2021-07-28 00:02:23 +02:00
local idolAnimTransitionScale = 0;
2021-07-27 21:18:13 +02:00
2021-10-22 21:12:48 +02:00
local badgeLinesAnimScale = 0;
local badgeLinesAnimOffsetX = 0;
local rightPanelX = 0;
local rightPanelY = 910;
2021-07-28 17:40:25 +02:00
local bottomPanelX = 0;
local bottomPanelY = 1170;
2021-07-28 17:40:25 +02:00
2021-07-27 21:18:13 +02:00
local jacketPanelX = 0;
local jacketPanelY = 880;
2021-07-27 21:18:13 +02:00
2021-10-23 23:20:57 +02:00
local AutoPosiX = 260;
local RightLeaderCheckY = rightPanelY - (IrPanelOrangeH / 1.17) - 6
local JACKET_PANEL_TRANSTION_ENTER_OFFSET = -256;
local RIGHT_PANEL_TRANSTION_ENTER_OFFSET = 256;
local BOTTOM_PANEL_TRANSTION_ENTER_OFFSET = 256;
2021-07-27 21:18:13 +02:00
local highScore;
-- gameplay table does not have a current username field, because why would it lmao
-- workaround: retrieve it directly from Main.cfg file
local username = GameConfig["MultiplayerUsername"] or game.GetSkinSetting('username') or '';
local msg = game.GetSkinSetting("MSG");
2021-07-28 18:50:06 +02:00
local earlyLateBarsStats = {
2021-07-27 23:54:17 +02:00
earlyErrors = 0,
earlyNears = 0,
criticals = 0,
lateNears = 0,
lateErrors = 0
};
local objectTypeTimingStats = {
2021-07-27 23:54:17 +02:00
chip = {criticals = 0, nears = 0, errors = 0},
long = {criticals = 0, errors = 0},
vol = {criticals = 0, errors = 0}
}
2021-08-14 13:28:13 +02:00
local irHeartbeatRequested = false;
local irText = ''
2021-07-27 20:00:02 +02:00
game.LoadSkinSample("result")
2021-12-02 04:16:05 +01:00
game.LoadSkinSample("shutter")
2021-07-25 20:10:06 +02:00
2022-05-06 00:05:20 +02:00
local function isHard(result)
if result.flags == nil then
return result.gauge_type == 1
end
return result.flags & 1 == 1
end
2021-07-27 21:18:13 +02:00
local handleSfx = function()
2021-07-27 20:00:02 +02:00
if not bgSfxPlayed then
2021-07-25 20:10:06 +02:00
game.PlaySample("result", true)
2021-07-27 20:00:02 +02:00
bgSfxPlayed = true
game.SetSkinSetting('_musicPlaying', 'result');
2021-07-25 20:10:06 +02:00
end
2021-07-27 21:18:13 +02:00
end
2022-05-06 00:05:20 +02:00
local drawGraph = function(x,y,w,h)
if isHard(result) then
gfx.BeginPath()
gfx.Rect(x,y,w,103)
gfx.FillColor(26,26,26,255)
gfx.Fill()
gfx.FillColor(255,255,255,255)
else
gfx.BeginPath()
gfx.Rect(x,y,w,h-68)
gfx.FillColor(55,27,51,255)
gfx.Fill()
gfx.BeginPath()
gfx.Rect(x,y+30,w,72)
gfx.FillColor(7,24,28,255)
gfx.Fill()
gfx.FillColor(255,255,255,255)
end
gfx.BeginPath()
gfx.MoveTo(x,y + h + 2 - h * result.gaugeSamples[1])
for i = 2, #result.gaugeSamples do
gfx.LineTo(x + i * w / #result.gaugeSamples,y + h + 2 - h * result.gaugeSamples[i])
end
if isHard(result) then
gfx.StrokeWidth(3)
gfx.StrokeColor(232,163,10)
gfx.Stroke()
gfx.Scissor(x, y + h *0.01, w, h*0.98)
gfx.Stroke()
gfx.ResetScissor()
gfx.Scissor(x, y + h * 0.99, w, (h * 0.03) + 4)
gfx.StrokeColor(255,0,0)
gfx.Stroke()
gfx.ResetScissor()
else
gfx.StrokeWidth(3)
gfx.StrokeColor(46,211,241)
gfx.Scissor(x, y + h * 0.3, w, (h * 0.7) + 4)
gfx.Stroke()
gfx.ResetScissor()
gfx.Scissor(x, y, w, h*0.3)
gfx.StrokeColor(215,48,182)
gfx.Stroke()
gfx.ResetScissor()
end
end
2021-07-27 23:54:17 +02:00
function drawTimingBar(y, value, max, type)
gfx.BeginPath();
2021-08-19 20:16:22 +02:00
if type == 'crit' then
2021-09-14 00:25:42 +02:00
gfx.FillColor(255, 255, 84, 255);
2021-07-27 23:54:17 +02:00
elseif type == 'early' then
2021-09-14 00:25:42 +02:00
gfx.FillColor(255, 16, 94, 255);
2021-07-27 23:54:17 +02:00
elseif type == 'late' then
2021-09-14 00:25:42 +02:00
gfx.FillColor(16, 225, 255, 255);
2021-07-27 23:54:17 +02:00
end
2022-05-06 00:05:20 +02:00
gfx.Rect(rightPanelX + 696, rightPanelY + y, 293 * (value / max), 8);
2021-07-27 23:54:17 +02:00
gfx.Fill();
gfx.ClosePath();
end
gettyping = function(animtype)
idolAnimation = gfx.LoadSkinAnimation('crew/anim/' .. crew .. animtype, 1 / 30, loopC, true);
2022-05-06 16:39:54 +02:00
end
2021-08-19 20:16:22 +02:00
local drawIdol = function(deltaTime)
if idolAnimation then
local idolAnimTickRes = gfx.TickAnimation(idolAnimation, deltaTime);
if idolAnimTickRes == 1 then
gfx.GlobalAlpha(idolAnimTransitionScale);
idolAnimTransitionScale = idolAnimTransitionScale + 1 / 60;
if (GameConfig["AutoScoreScreenshot"] or idolAnimTransitionScale > 1) then
idolAnimTransitionScale = 1;
end
gfx.ImageRect(0, 0, desw, desh, idolAnimation, 1, 0);
gfx.GlobalAlpha(1);
2021-08-19 20:16:22 +02:00
end
end
2021-07-28 00:02:23 +02:00
end
2021-10-22 22:00:58 +02:00
local drawbgrade = function()
gfx.BeginPath();
gfx.ImageRect(rightPanelX + 1080 - 531, rightPanelY + 2, 531, 85, badgeGrade, 1, 0);
end
local drawRightBarAni = function(deltaTime)
2021-10-22 21:12:48 +02:00
-- badgeLines
gfx.BeginPath();
gfx.ImageRect(rightPanelX + 1080 - 531 + badgeLinesAnimOffsetX, rightPanelY + 2, 531, 85, badgeLines, 1, 0);
end
2021-10-23 23:20:57 +02:00
local drawmod = function ()
if result.speedModType == 2 then
gfx.BeginPath();
gfx.ImageRect(rightPanelX + 1080 - 250, rightPanelY-35, 254, 35, cMOD, 1, 0);
2021-10-23 23:20:57 +02:00
end
end
local drawarn = function()
2021-10-23 23:20:57 +02:00
if (result.autoplay) then
gfx.BeginPath();
gfx.ImageRect(bottomPanelX + 30, bottomPanelY + 495, 541 * 0.85, 136 * 0.85, warn, 1, 0);
gfx.BeginPath();
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE);
gfx.FontSize(20)
gfx.Text(string.upper(lang.Result.re), bottomPanelX + AutoPosiX + 30, bottomPanelY + 534);
gfx.Text(string.upper(lang.Result.re1), bottomPanelX + AutoPosiX, bottomPanelY + 564);
gfx.Text(string.upper(lang.Result.re2), bottomPanelX + AutoPosiX, bottomPanelY + 584);
2022-07-05 20:44:14 +02:00
end
if not result.autoplay and result.badge == 0 then
gfx.BeginPath();
gfx.ImageRect(bottomPanelX + 30, bottomPanelY + 495, 541 * 0.85, 136 * 0.85, warn, 1, 0);
gfx.BeginPath();
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE);
gfx.FontSize(20)
gfx.Text(string.upper(lang.Result.re3), bottomPanelX + AutoPosiX + 30, bottomPanelY + 534);
gfx.Text(string.upper(lang.Result.re4), bottomPanelX + AutoPosiX, bottomPanelY + 564);
gfx.Text(string.upper(lang.Result.re2), bottomPanelX + AutoPosiX, bottomPanelY + 584);
2021-10-23 23:20:57 +02:00
end
end
2021-07-27 21:18:13 +02:00
local drawTopBar = function()
gfx.BeginPath();
local tw, th = gfx.ImageSize(topBarImage);
2021-08-19 20:16:22 +02:00
th = (desw / tw) * th; -- recalculate the height of the bar to scale it down
2021-08-06 19:34:32 +02:00
2021-07-27 21:18:13 +02:00
gfx.ImageRect(0, -th * (1 - Easing.outQuad(transitionEnterScale)), desw, th,
topBarImage, 1, 0);
2021-07-27 21:18:13 +02:00
end
local drawRightPanel = function()
gfx.BeginPath();
local tw, th = gfx.ImageSize(rightPanelImage);
2022-05-06 00:05:20 +02:00
gfx.ImageRect(rightPanelX, rightPanelY, tw, th, rightPanelImage, 1, 0);
end
2021-07-27 21:18:13 +02:00
local onlinebar = function(x,y, text)
2022-07-05 20:44:14 +02:00
local highScoreScore = 0;
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE)
2022-07-05 20:44:14 +02:00
if highScore then highScoreScore = highScore.score end
gfx.BeginPath();
gfx.ImageRect(x, y, IrPanelOrangeW / 1.17, IrPanelOrangeH / 1.17, irpanelsO, 1, 0)
2022-07-05 20:44:14 +02:00
gfx.FillColor(0, 0, 0)
gfx.Text(text[1] .. text[3], x + 110, y + 16)
gfx.FillColor(255, 255, 255)
2022-07-05 20:44:14 +02:00
gfx.FontSize(26)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
2022-07-05 20:44:14 +02:00
if result.highScores[1] ~= nil then
gfx.Text(string.format("%08d", result.score), x + 45, y + 49)
gfx.Text(string.format("%08d", highScoreScore), x+(IrPanelOrangeW / 1.17) - 370 + 50, y + 49)
if string.format("%08d", result.score) >= string.format("%08d", highScoreScore) then
gfx.Text(text[5], x+(IrPanelOrangeW / 1.17) - 240 + 50, y + 48)
2022-07-05 20:44:14 +02:00
end
gfx.BeginPath();
gfx.ImageRect(x+(IrPanelOrangeW / 1.17) - 360, y + 38, ArrowW * 0.3, ArrowH * 0.3, arrow, 1, 0)
2022-07-05 20:44:14 +02:00
else
gfx.Text(string.sub(string.upper(username),1,7) .. " 'S", x + 50, y + 49)
2022-07-05 20:44:14 +02:00
gfx.Text(string.format("%08d", highScoreScore), x+(IrPanelOrangeW / 1.17) - 330 + 47, y + 49)
2022-07-05 20:44:14 +02:00
if string.format("%08d", result.score) >= string.format("%08d", highScoreScore) then
gfx.Text(text[4], x+(IrPanelOrangeW / 1.17) - 200 + 50, y + 48)
2022-07-05 20:44:14 +02:00
end
end
end
local offlinebar = function(x,y, text)
2022-07-05 20:44:14 +02:00
local highScoreScore = 0;
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE)
2022-07-05 20:44:14 +02:00
if highScore then highScoreScore = highScore.score end
gfx.BeginPath();
gfx.ImageRect(x, y, IrPanelBlueW / 1.17, IrPanelBlueH / 1.17, irpanelsB, 1, 0)
gfx.FillColor(0, 0, 0)
gfx.Text(text[2] .. text[3], x + 110, y + 16)
gfx.FillColor(255, 255, 255)
2022-07-05 20:44:14 +02:00
gfx.FontSize(26)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
if result.highScores[1] ~= nil then
2022-07-05 20:44:14 +02:00
gfx.Text(string.format("%08d", result.score), x + 45, y + 49)
gfx.Text(string.format("%08d", highScoreScore), x+(IrPanelBlueW / 1.17) - 370 + 50, y + 49)
2022-07-05 20:44:14 +02:00
if string.format("%08d", result.score) >= string.format("%08d", highScoreScore) then
gfx.Text(text[5], x+(IrPanelBlueW / 1.17) - 240 + 50, y + 48)
end
2022-07-05 20:44:14 +02:00
gfx.BeginPath();
gfx.ImageRect(x+(IrPanelBlueW / 1.17) - 360, y + 38, ArrowW * 0.3, ArrowH * 0.3, arrow, 1, 0)
2022-07-05 20:44:14 +02:00
else
2022-07-05 20:44:14 +02:00
gfx.Text(string.sub(string.upper(username),1,7) .. " 'S", x + 50, y + 49)
2022-07-05 20:44:14 +02:00
gfx.Text(string.format("%08d", result.score), x+(IrPanelBlueW / 1.17) - 330 + 47, y + 49)
2022-07-05 20:44:14 +02:00
if string.format("%08d", result.score) >= string.format("%08d", highScoreScore) then
gfx.Text(text[4], x+(IrPanelBlueW / 1.17) - 200 + 50, y + 48)
end
2022-07-05 20:44:14 +02:00
end
end
local drawRightLeaderCheck = function()
2022-07-05 20:44:14 +02:00
if result.speedModType == 2 then
height = -35
else
height = 0
end
if result.autoplay and result.badge ~= 0 then
if IRData.Active then
gfx.FontSize(21.5)
onlinebar(-rightPanelX-2+(IrPanelOrangeW / 1.17),((RightLeaderCheckY+ height)-(IrPanelOrangeH / 1.17))-4, irGB)
gfx.FontSize(21.5)
offlinebar(-rightPanelX-2+(IrPanelBlueW / 1.17),RightLeaderCheckY + height, irGB)
else
gfx.FontSize(21.5)
offlinebar(-rightPanelX-2+(IrPanelBlueW / 1.17),RightLeaderCheckY+height, irGB)
end
end
end
2021-07-28 16:35:34 +02:00
2021-07-27 23:54:17 +02:00
local drawRightPanelContent = function()
local highScoreScore = 0;
2021-08-19 20:16:22 +02:00
if highScore then highScoreScore = highScore.score end
local highScoreDelta = result.score - highScoreScore
2022-05-06 00:05:20 +02:00
2021-08-06 19:57:00 +02:00
-- Draw clear badge
local badgeData = clearBadgeImages[result.badge + 1] or clearBadgeImages[1]
2021-08-07 20:29:38 +02:00
if (result.autoplay) then
badgeData = clearBadgeImages[7]; -- Display AUTOPLAY badge
end
2021-08-06 19:57:00 +02:00
local tw, th = gfx.ImageSize(badgeData.image);
gfx.BeginPath();
gfx.ImageRect(rightPanelX + badgeData.xPos - tw, rightPanelY - 10, tw * 0.85,
th * 0.85, badgeData.image, 1, 0);
-- Draw song name and artist
gfx.FontSize(28)
2021-07-27 23:54:17 +02:00
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.Text(result.realTitle, rightPanelX + 435, rightPanelY + 108);
gfx.Text(result.artist, rightPanelX + 435, rightPanelY + 143);
2021-07-27 23:54:17 +02:00
2021-07-28 16:35:34 +02:00
-- Draw score
2021-11-20 23:51:53 +01:00
Numbers.draw_number(rightPanelX + 580, rightPanelY + 192, 1.0,
2021-08-19 20:16:22 +02:00
math.floor(result.score / 10000), 4, scoreNumber, true, 0.40,
1.12)
2021-11-20 23:51:53 +01:00
Numbers.draw_number(rightPanelX + 775, rightPanelY + 200, 1.0, result.score, 4,
2021-08-19 20:16:22 +02:00
scoreNumber, true, 0.25, 1.12)
2021-07-28 16:35:34 +02:00
-- If this is the highscore, draw over the glowing best badge
if highScoreDelta > 0 then
gfx.BeginPath();
2021-08-19 20:16:22 +02:00
gfx.ImageRect(rightPanelX + 364, rightPanelY + 167, 97, 53,
bestScoreBadgeImage, 1, 0);
end
2021-07-28 16:35:34 +02:00
-- Draw grade
local gradeImageKey = string.gsub(result.grade, '+', '_P');
local gradeImage = gradeImages[gradeImageKey] or gradeImages.D
gfx.BeginPath();
2021-08-19 20:16:22 +02:00
gfx.ImageRect(rightPanelX + 890, rightPanelY + 130, 85, 85, gradeImage, 1, 0);
2021-07-28 16:35:34 +02:00
-- Draw best score
gfx.FontSize(20)
2021-07-27 23:54:17 +02:00
gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_MIDDLE)
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
local deltaPrefix = '-'
2021-08-19 20:16:22 +02:00
if highScoreDelta > 0 then deltaPrefix = '+' end
highScoreDelta = math.abs(highScoreDelta);
2021-08-19 20:16:22 +02:00
gfx.Text(string.format("%08d", highScoreScore), rightPanelX + 962,
rightPanelY + 239);
gfx.Text(deltaPrefix .. string.format("%08d", highScoreDelta),
rightPanelX + 962, rightPanelY + 259);
-- Draw gauge type badge
gfx.BeginPath();
2021-08-19 20:16:22 +02:00
gfx.ImageRect(rightPanelX + 722, rightPanelY + 273, 211, 40,
gaugeTypeBadgeImages[result.gauge_type + 1], 1, 0);
2022-05-06 00:05:20 +02:00
-- Draw gauge %
gfx.FontSize(24)
if result.gauge == 1 then
gfx.Text('100%', rightPanelX + 987,
rightPanelY + 294);
else
gfx.Text(math.floor(result.gauge * 100) .. '.', rightPanelX + 964, rightPanelY + 294);
gfx.FontSize(18)
local decimalPortion = math.floor(
(
result.gauge * 100 -
math.floor(result.gauge * 100)
) * 10
);
gfx.Text(decimalPortion .. '%', rightPanelX + 988, rightPanelY + 296);
-- gfx.FontSize(24)
-- gfx.Text('%', rightPanelX + 988, rightPanelY + 294);
end
gfx.FontSize(24)
2021-08-16 18:41:44 +02:00
-- Draw gauge fill
local gaugeFillImage = gaugeEffPassFillImage;
local gaugeBreakpoint = 0;
if result.gauge_type == 0 then
gaugeBreakpoint = 0.7;
if result.gauge <= 0.7 then
gaugeFillImage = gaugeEffFailFillImage;
else
gaugeFillImage = gaugeEffPassFillImage;
end
elseif result.gauge_type == 1 then
gaugeFillImage = gaugeExcFillImage;
elseif result.gauge_type == 2 then
gaugeFillImage = gaugePermFillImage;
elseif result.gauge_type == 3 then -- BLASTIVE RATE
gaugeFillImage = gaugeBlastiveFillImage;
end
2021-08-19 20:16:22 +02:00
local gaugePosX = rightPanelX + 1027;
local gaugePosY = rightPanelY + 309;
local FillW, FillH = 9.5, 236;
2021-08-16 18:41:44 +02:00
gfx.BeginPath();
2021-08-19 20:16:22 +02:00
gfx.Scissor(gaugePosX, gaugePosY + (FillH - (FillH * (result.gauge))),
FillW, FillH * (result.gauge))
2021-08-16 18:41:44 +02:00
gfx.ImageRect(gaugePosX, gaugePosY, FillW, FillH, gaugeFillImage, 1, 0);
gfx.ResetScissor();
-- Draw the breakpoint line if needed
if (gaugeBreakpoint > 0) then
gfx.Save()
2021-08-19 20:16:22 +02:00
gfx.BeginPath()
2021-08-16 18:41:44 +02:00
gfx.GlobalAlpha(0.75);
2021-08-19 20:16:22 +02:00
local lineY = gaugePosY + (FillH - (FillH * (gaugeBreakpoint)))
2021-08-16 18:41:44 +02:00
2021-08-19 20:16:22 +02:00
gfx.MoveTo(gaugePosX, lineY)
gfx.LineTo(gaugePosX + 10, lineY)
gfx.StrokeWidth(2)
gfx.StrokeColor(255, 255, 255)
gfx.Stroke()
2021-08-16 18:41:44 +02:00
gfx.ClosePath()
2021-08-19 20:16:22 +02:00
gfx.Restore()
2021-08-16 18:41:44 +02:00
end
2021-08-19 20:16:22 +02:00
2022-05-06 00:05:20 +02:00
-- Draw the gauge type flags if needed (mirror, random)
if(result.mirror or result.random) then
gfx.BeginPath();
local gaugeTypeFlagPosX = gaugePosX + 10;
local gaugeTypeFlagPosY = gaugePosY - 30;
local flagw, flagh = gfx.ImageSize(gaugeTypeMirrorImage)
if(result.mirror and result.random) then
gfx.ImageRect(gaugeTypeFlagPosX, gaugeTypeFlagPosY, flagw, flagh, gaugeTypeMirrorRandomImage, 1, 0)
elseif(result.mirror) then
gfx.ImageRect(gaugeTypeFlagPosX, gaugeTypeFlagPosY, flagw, flagh, gaugeTypeMirrorImage, 1, 0)
elseif(result.random) then
gfx.ImageRect(gaugeTypeFlagPosX, gaugeTypeFlagPosY, flagw, flagh, gaugeTypeRandomImage, 1, 0)
end
end
-- Draw err/early/critical/late/err texts
2021-07-27 23:54:17 +02:00
gfx.Text(earlyLateBarsStats.earlyErrors, rightPanelX + 683,
rightPanelY + 370);
gfx.Text(earlyLateBarsStats.earlyNears, rightPanelX + 683, rightPanelY + 401);
gfx.Text(earlyLateBarsStats.criticals, rightPanelX + 683, rightPanelY + 432);
gfx.Text(earlyLateBarsStats.lateNears, rightPanelX + 683, rightPanelY + 463);
gfx.Text(earlyLateBarsStats.lateErrors, rightPanelX + 683, rightPanelY + 494);
2021-07-27 23:54:17 +02:00
-- Draw hit timing bars
local totalHits = earlyLateBarsStats.earlyErrors +
earlyLateBarsStats.earlyNears +
earlyLateBarsStats.criticals +
earlyLateBarsStats.lateNears +
earlyLateBarsStats.lateErrors
gfx.Save()
drawTimingBar(365, earlyLateBarsStats.earlyErrors, totalHits, 'early')
drawTimingBar(396, earlyLateBarsStats.earlyNears, totalHits, 'early')
drawTimingBar(427, earlyLateBarsStats.criticals, totalHits, 'crit')
drawTimingBar(458, earlyLateBarsStats.lateNears, totalHits, 'late')
drawTimingBar(489, earlyLateBarsStats.lateErrors, totalHits, 'late')
gfx.Restore()
-- Draw hit stats based on objects
-- CHIP
2021-07-27 23:54:17 +02:00
gfx.Text(objectTypeTimingStats.chip.criticals, rightPanelX + 255,
rightPanelY + 365);
gfx.Text(objectTypeTimingStats.chip.nears, rightPanelX + 255,
rightPanelY + 395);
gfx.Text(objectTypeTimingStats.chip.errors, rightPanelX + 255,
rightPanelY + 425);
-- LONG
2021-08-19 20:16:22 +02:00
gfx.Text(objectTypeTimingStats.long.criticals, rightPanelX + 333,
rightPanelY + 365);
gfx.Text('-', rightPanelX + 333, rightPanelY + 395);
2021-08-19 20:16:22 +02:00
gfx.Text(objectTypeTimingStats.long.errors, rightPanelX + 333,
rightPanelY + 425);
-- VOL
2021-08-19 20:16:22 +02:00
gfx.Text(objectTypeTimingStats.vol.criticals, rightPanelX + 411,
rightPanelY + 365);
gfx.Text('-', rightPanelX + 411, rightPanelY + 395);
2021-08-19 20:16:22 +02:00
gfx.Text(objectTypeTimingStats.vol.errors, rightPanelX + 411,
rightPanelY + 425);
-- Draw max combo
gfx.Text(result.maxCombo, rightPanelX + 371, rightPanelY + 466);
2021-07-27 21:18:13 +02:00
end
2021-07-27 23:54:17 +02:00
local drawBottomPanel = function()
2021-07-27 21:18:13 +02:00
gfx.BeginPath();
local tw, th = gfx.ImageSize(bottomPanelImage);
2022-05-06 00:05:20 +02:00
2021-08-19 20:16:22 +02:00
gfx.ImageRect(bottomPanelX, bottomPanelY, tw, th, bottomPanelImage, 1, 0);
2021-07-27 21:18:13 +02:00
end
2021-08-19 20:16:22 +02:00
local drawBottomPanelContent = function(deltatime)
2021-07-28 18:50:06 +02:00
-- Draw appeal card
gfx.BeginPath();
2021-08-19 20:16:22 +02:00
gfx.ImageRect(bottomPanelX + 58, bottomPanelY + 277, 103, 132,
result.isSelf and appealCardImage or defaultCardImage, 1, 0);
2021-07-28 18:50:06 +02:00
-- Draw description
gfx.FontSize(22)
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.Text(result.isSelf and msg or ("Player "..result.displayIndex), bottomPanelX + 190, bottomPanelY + 282);
2021-07-28 18:50:06 +02:00
-- Draw username
gfx.FontSize(28)
gfx.Text(result.playerName or username, bottomPanelX + 190, bottomPanelY + 314);
2021-07-28 18:50:06 +02:00
-- Draw dan badge
gfx.BeginPath();
2022-05-06 00:05:20 +02:00
gfx.ImageRect(bottomPanelX + 187, bottomPanelY + 362, 107, 29,
result.isSelf and danBadgeImage or defaultBadgeImage, 1, 0);
2021-08-19 20:16:22 +02:00
2021-08-12 21:21:42 +02:00
-- Draw volforce
if result.isSelf then
VolforceWindow.render(0, bottomPanelX + 310, bottomPanelY + 355, 42, VolforceAmount, true, true, true)
end
2021-08-14 13:28:13 +02:00
-- Draw IR text
gfx.FontSize(22)
2021-08-19 20:16:22 +02:00
gfx.Text(irText, bottomPanelX + 80, bottomPanelY + 461);
2022-05-06 00:05:20 +02:00
-- Draw median and mean hit delta
local leftX = bottomPanelX + 600
local rightX = bottomPanelX + 1010
2022-05-06 00:05:20 +02:00
local baseY = bottomPanelY + 440
local detailTextMargin = 25
gfx.FontSize(20)
gfx.Text('Median hit delta', leftX, baseY);
gfx.Text('Mean hit delta', leftX, baseY + detailTextMargin);
gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_MIDDLE)
gfx.Text(result.medianHitDelta.." ms", rightX, baseY);
gfx.Text(math.floor(result.meanHitDelta).." ms", rightX, baseY + detailTextMargin);
2022-05-06 00:05:20 +02:00
--Draw Graph
drawGraph(leftX-22, baseY-18, 454, 98);
--draw Recommended Offset
local delta = math.floor(result.medianHitDelta);
local songOffset = 0;
if (songOffset == nil) then songOffset = 0; end
local offset = tonumber(songOffset) + delta;
gfx.FillColor(255,255,255,255);
gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_TOP)
gfx.Text('RECOMMENDED SONG OFFSET:', leftX + 367, baseY + 89);
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.Text(string.format("%dms", offset), leftX + 370, baseY + 89);
2021-07-28 17:40:25 +02:00
end
2022-05-06 00:05:20 +02:00
2021-07-27 21:18:13 +02:00
local drawJacketPanel = function()
gfx.BeginPath();
local tw, th = gfx.ImageSize(jacketPanelImage);
gfx.ImageRect(jacketPanelX, jacketPanelY, tw, th, jacketPanelImage, 1, 0);
2021-07-27 21:18:13 +02:00
end
local drawJacketPanelContent = function(deltaTime)
gfx.BeginPath();
2022-05-06 00:05:20 +02:00
gfx.ImageRect(jacketPanelX + 13, jacketPanelY + 28, 265, 265, jacketImage or defaultJacketImage, 1, 0);
local adjustedDiff = Charting.GetDisplayDifficulty(result.jacketPath, result.difficulty)
DiffRectangle.render(deltaTime, jacketPanelX+183, jacketPanelY+2.5, 0.67, adjustedDiff, result.level);
-- gfx.BeginPath();
-- gfx.ImageRect(jacketPanelX + 183, jacketPanelY + 2.5, 140 / 1.5, 31 / 1.5,
-- difficultyLabelImages[result.difficulty + 1] or
-- difficultyLabelImages[4], 1, 0);
-- gfx.FontSize(17)
-- gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
-- gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_MIDDLE)
-- gfx.Text(result.level, jacketPanelX + 265, jacketPanelY + 13.5);
2021-07-27 21:18:13 +02:00
end
2021-08-14 13:28:13 +02:00
local IR_HeartbeatResponse = function(res)
if res.statusCode == IRData.States.Success then
irText = res.body.serverName .. ' ' .. res.body.irVersion;
else
game.Log("Can't connect to IR!", game.LOGGER_WARNING)
end
end
local IR_Handle = function()
if not irHeartbeatRequested then
IR.Heartbeat(IR_HeartbeatResponse)
irHeartbeatRequested = true;
end
end
2021-07-27 21:18:13 +02:00
local tickTransitions = function(deltaTime)
if not GameConfig["AutoScoreScreenshot"] and transitionEnterScale < 1 then
transitionEnterScale = transitionEnterScale + deltaTime / 0.66 -- transition should last for that time in seconds
else
transitionEnterScale = 1
end
2021-07-27 21:18:13 +02:00
if transitionEnterScale < 1 then
transitionEnterScale = transitionEnterScale + deltaTime / 0.66 -- transition should last for that time in seconds
2021-07-27 21:18:13 +02:00
else
transitionEnterScale = 1
2021-07-25 20:10:06 +02:00
end
2021-07-27 21:18:13 +02:00
2021-07-27 23:54:17 +02:00
rightPanelX = 0 +
(RIGHT_PANEL_TRANSTION_ENTER_OFFSET *
(1 - Easing.outQuad(transitionEnterScale)))
2021-07-28 17:40:25 +02:00
bottomPanelY = 1170 + (BOTTOM_PANEL_TRANSTION_ENTER_OFFSET *
(1 - Easing.outQuad(transitionEnterScale)))
2021-07-28 17:40:25 +02:00
2021-07-27 23:54:17 +02:00
jacketPanelX = 40 + (JACKET_PANEL_TRANSTION_ENTER_OFFSET *
(1 - Easing.outQuad(transitionEnterScale)))
2021-10-22 21:12:48 +02:00
if not GameConfig["AutoScoreScreenshot"] and badgeLinesAnimScale < 1 then
2021-10-22 21:12:48 +02:00
badgeLinesAnimScale = badgeLinesAnimScale + deltaTime / 0.5 -- transition should last for that time in seconds
else
badgeLinesAnimScale = 0
end
badgeLinesAnimOffsetX = 16 * (1-badgeLinesAnimScale);
2021-07-27 21:18:13 +02:00
end
2021-07-27 23:54:17 +02:00
result_set = function()
2021-07-27 21:18:13 +02:00
if result.jacketPath ~= nil and result.jacketPath ~= "" then
jacketImage = gfx.CreateImage(result.jacketPath, 0)
end
2021-08-19 20:16:22 +02:00
-- Reset stats
earlyLateBarsStats = {
earlyErrors = 0,
earlyNears = 0,
criticals = 0,
lateNears = 0,
lateErrors = 0
};
objectTypeTimingStats = {
chip = {criticals = 0, nears = 0, errors = 0},
long = {criticals = 0, errors = 0},
vol = {criticals = 0, errors = 0}
}
-- Store the highest score so we can use it later for delta and stuff
highScore = result.highScores[1];
2021-08-19 20:16:22 +02:00
-- This check is to prevent errors when these are not available
if (result.noteHitStats and result.holdHitStats and result.laserHitStats) then
-- "CHIP" objects
for hitStatIndex = 1, #result.noteHitStats do
local hitStat = result.noteHitStats[hitStatIndex];
if (hitStat.rating == 0) then -- Errors
objectTypeTimingStats.chip.errors =
objectTypeTimingStats.chip.errors + 1;
if hitStat.delta < 0 then
earlyLateBarsStats.earlyErrors =
earlyLateBarsStats.earlyErrors + 1;
else
earlyLateBarsStats.lateErrors =
earlyLateBarsStats.lateErrors + 1;
end
elseif hitStat.rating == 1 then -- Nears
objectTypeTimingStats.chip.nears =
objectTypeTimingStats.chip.nears + 1;
if hitStat.delta < 0 then
earlyLateBarsStats.earlyNears =
earlyLateBarsStats.earlyNears + 1;
else
earlyLateBarsStats.lateNears =
earlyLateBarsStats.lateNears + 1;
end
else -- Criticals
objectTypeTimingStats.chip.criticals =
objectTypeTimingStats.chip.criticals + 1;
end
2021-08-19 20:16:22 +02:00
end
2021-08-19 20:16:22 +02:00
-- "LONG" objects
for hitStatIndex = 1, #result.holdHitStats do
local hitStat = result.holdHitStats[hitStatIndex];
if (hitStat.rating == 0) then -- Errors
objectTypeTimingStats.long.errors =
objectTypeTimingStats.long.errors + 1;
earlyLateBarsStats.lateErrors =
earlyLateBarsStats.lateErrors + 1;
else -- Criticals
objectTypeTimingStats.long.criticals =
objectTypeTimingStats.long.criticals + 1;
end
end
2021-08-19 20:16:22 +02:00
-- "VOL" a.k.a laser objects
for hitStatIndex = 1, #result.laserHitStats do
local hitStat = result.laserHitStats[hitStatIndex];
if (hitStat.rating == 0) then -- Errors
objectTypeTimingStats.vol.errors =
objectTypeTimingStats.vol.errors + 1;
earlyLateBarsStats.lateErrors =
earlyLateBarsStats.lateErrors + 1;
else -- Criticals
objectTypeTimingStats.vol.criticals =
objectTypeTimingStats.vol.criticals + 1;
end
end
2021-08-19 20:16:22 +02:00
else
objectTypeTimingStats = {
chip = {criticals = 'N/A', nears = 'N/A', errors = 'N/A'},
long = {criticals = 'N/A', errors = 'N/A'},
vol = {criticals = 'N/A', errors = 'N/A'}
}
end
earlyLateBarsStats.criticals = result.perfects -- Criticals are for all objects
2022-06-05 03:12:34 +02:00
if betacrew and not staticcrew then
if result.score > grades.S - 1 then
2022-06-05 03:12:34 +02:00
animtype = veryokay
loopC = 1
elseif result.score > grades.AAA - 1 then
2022-06-05 03:12:34 +02:00
animtype = okay
loopC = 1
elseif result.score < grades.AAA - 1 then
2022-06-05 03:12:34 +02:00
animtype = bad
loopC = 1
end
2022-05-06 16:39:54 +02:00
end
if not betacrew and not staticcrew then
animtype = idle
loopC = 0
elseif not betacrew and staticcrew then
animtype = static
loopC = 0
end
2022-05-06 16:39:54 +02:00
gettyping(animtype)
2021-07-27 21:18:13 +02:00
end
drawResultScreen = function (x, y, w, h, deltaTime)
gfx.BeginPath()
2021-07-27 21:18:13 +02:00
gfx.Translate(x, y);
gfx.Scale(w / 1080, h / 1920);
gfx.Scissor(0, 0, 1080, 1920);
Background.draw(deltaTime)
2021-07-27 21:18:13 +02:00
2021-07-28 00:02:23 +02:00
drawIdol(deltaTime)
2021-07-27 21:18:13 +02:00
drawTopBar()
2021-07-28 18:50:06 +02:00
gfx.GlobalAlpha(Easing.outQuad(transitionEnterScale))
2021-07-27 21:18:13 +02:00
drawBottomPanel()
2021-08-12 21:21:42 +02:00
drawBottomPanelContent(deltaTime)
2022-07-05 20:44:14 +02:00
drawRightLeaderCheck()
2021-07-27 21:18:13 +02:00
drawRightPanel()
drawRightBarAni(deltaTime)
2021-10-22 22:00:58 +02:00
drawbgrade()
2021-10-23 23:20:57 +02:00
drawmod()
drawRightPanelContent()
2021-07-28 18:50:06 +02:00
2021-07-27 21:18:13 +02:00
drawJacketPanel()
drawJacketPanelContent(deltaTime)
2021-10-23 23:20:57 +02:00
drawarn()
gfx.GlobalAlpha(1)
Footer.draw(deltaTime);
2021-08-09 20:19:11 +02:00
2021-08-14 13:28:13 +02:00
handleSfx();
IR_Handle();
2021-07-27 21:18:13 +02:00
gfx.ResetTransform()
end
render = function(deltaTime, showStats)
-- detect resolution change
local resx, resy = game.GetResolution()
if resx ~= resX or resy ~= resY then
resolutionChange(resx, resy)
end
gfx.BeginPath()
local bgImageWidth, bgImageHeight = gfx.ImageSize(backgroundImage)
gfx.Rect(0, 0, resX, resY)
gfx.FillPaint(gfx.ImagePattern(0, 0, bgImageWidth, bgImageHeight, 0, backgroundImage, 0.2))
gfx.Fill()
drawResultScreen((resX - fullX) / 2, 0, fullX, fullY, deltaTime)
2021-07-27 21:18:13 +02:00
-- debug
gfx.FontSize(18)
2021-07-27 23:54:17 +02:00
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
2022-05-06 00:05:20 +02:00
if game.GetSkinSetting('debug_showInformation') then
gfx.Text('DELTA: ' .. deltaTime .. ' // TRANSITION_ENTER_SCALE: ' ..
transitionEnterScale .. ' // EASING_OUT_QUAD: ' ..
Easing.outQuad(transitionEnterScale), 8, 8);
end
2021-07-27 21:18:13 +02:00
tickTransitions(deltaTime)
end
2021-12-02 04:16:05 +01:00
get_capture_rect = function ()
return (resX - fullX) / 2, 0, fullX, fullY
end
screenshot_captured = function(path)
game.PlaySample("shutter")
end