ExperimentalGear/scripts/result.lua

829 lines
27 KiB
Lua
Raw Normal View History

local Easing = require('common.easing');
local Charting = require('common.charting');
local Background = require('components.background');
2021-08-09 20:19:11 +02:00
local Footer = require('components.footer');
local Numbers = require('components.numbers')
local DiffRectangle = require('components.diff_rectangle');
2021-10-23 23:20:57 +02:00
local lang = require("language.call")
2021-07-27 21:18:13 +02:00
require('common.gameconfig')
2021-10-25 19:43:11 +02:00
local creww = game.GetSkinSetting("single_idol")
2021-08-12 21:21:42 +02:00
local VolforceWindow = require('components.volforceWindow')
-- 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);
local warntxt = gfx.CreateSkinImage("result/warnings/AUTOPLAY.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);
2021-10-25 21:39:16 +02:00
local appealCardImage = gfx.CreateSkinImage("crew/appeal_card.png", 0);
2021-07-28 18:50:06 +02:00
local danBadgeImage = gfx.CreateSkinImage("dan/inf.png", 0);
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
2022-03-14 23:40:33 +01: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
}
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)
}
2021-08-19 20:16:22 +02:00
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)
2021-08-19 20:16:22 +02:00
local gaugePermFillImage = gfx.CreateSkinImage(
"gameplay/gauges/permissive/gauge_fill.png", 0)
local gaugeBlastiveFillImage = gfx.CreateSkinImage(
"gameplay/gauges/blastive/gauge_fill.png", 0)
2021-08-16 18:41:44 +02:00
local difficultyLabelImages = {
gfx.CreateSkinImage("diff/1 novice.png", 0),
gfx.CreateSkinImage("diff/2 advanced.png", 0),
gfx.CreateSkinImage("diff/3 exhaust.png", 0),
gfx.CreateSkinImage("diff/4 maximum.png", 0),
gfx.CreateSkinImage("diff/5 infinite.png", 0),
gfx.CreateSkinImage("diff/6 gravity.png", 0),
gfx.CreateSkinImage("diff/7 heavenly.png", 0),
2022-05-30 02:51:24 +02:00
gfx.CreateSkinImage("diff/8 vivid.png", 0),
gfx.CreateSkinImage("diff/9 exceed.png", 0)
}
2021-08-06 19:57:00 +02:00
local clearBadgeImages = {
{
image = gfx.CreateSkinImage("result/clears/CRASH.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
}
2021-07-28 00:02:23 +02:00
-- ANIMS
2021-10-25 19:43:11 +02:00
local idolAnimation = gfx.LoadSkinAnimation('crew/anim/'..creww, 1 / 30, 0, true);
2021-10-22 21:12:48 +02:00
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 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;
2021-07-28 18:50:06 +02:00
local username = game.GetSkinSetting('username');
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
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
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
2021-08-19 20:16:22 +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
2021-08-19 20:16:22 +02:00
local drawIdol = function(deltaTime)
2021-07-28 00:02:23 +02:00
local idolAnimTickRes = gfx.TickAnimation(idolAnimation, deltaTime);
2021-08-19 20:16:22 +02:00
if idolAnimTickRes == 1 then
gfx.GlobalAlpha(idolAnimTransitionScale);
2021-07-28 00:02:23 +02:00
2021-08-19 20:16:22 +02:00
idolAnimTransitionScale = idolAnimTransitionScale + 1 / 60;
if (GameConfig["AutoScoreScreenshot"] or idolAnimTransitionScale > 1) then
2021-08-19 20:16:22 +02:00
idolAnimTransitionScale = 1;
end
2021-07-28 00:02:23 +02:00
2021-08-19 20:16:22 +02:00
gfx.ImageRect(0, 0, desw, desh, idolAnimation, 1, 0);
gfx.GlobalAlpha(1);
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);
end
end
local drawarn = function ()
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(lang.Result.re,bottomPanelX + AutoPosiX + 30, bottomPanelY+534);
gfx.Text(lang.Result.re1,bottomPanelX + AutoPosiX, bottomPanelY+564);
gfx.Text(lang.Result.re2,bottomPanelX + AutoPosiX, bottomPanelY+584);
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);
end
local drawRightPanel = function()
gfx.BeginPath();
local tw, th = gfx.ImageSize(rightPanelImage);
gfx.ImageRect(rightPanelX, rightPanelY, tw, th, rightPanelImage, 1, 0);
end
2021-07-27 21:18:13 +02:00
2021-11-20 23:51:53 +01:00
local scoreNumber = Numbers.load_number_image("score_num");
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
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
2021-08-19 20:16:22 +02:00
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);
-- Draw gauge %
2021-07-28 17:22:25 +02:00
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-03-14 23:40:33 +01: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);
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,
appealCardImage, 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(msg, bottomPanelX + 190, bottomPanelY + 282);
2021-07-28 18:50:06 +02:00
-- Draw username
gfx.FontSize(28)
2021-08-19 20:16:22 +02:00
gfx.Text(username, bottomPanelX + 190, bottomPanelY + 314);
2021-07-28 18:50:06 +02:00
-- Draw dan badge
gfx.BeginPath();
2021-08-19 20:16:22 +02:00
gfx.ImageRect(bottomPanelX + 187, bottomPanelY + 362, 107, 29,
danBadgeImage, 1, 0);
2021-08-12 21:21:42 +02:00
-- Draw volforce
2021-08-19 20:16:22 +02:00
VolforceWindow.render(0, bottomPanelX + 310, bottomPanelY + 355)
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);
-- Draw median and mean hit delta
2021-08-19 20:16:22 +02:00
local leftX = bottomPanelX + 600
local rightX = bottomPanelX + 1010
local baseY = bottomPanelY + 440
local detailTextMargin = 25
gfx.FontSize(20)
gfx.Text('Median hit delta', leftX, baseY);
2021-08-19 20:16:22 +02:00
gfx.Text('Mean hit delta', leftX, baseY + detailTextMargin);
gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_MIDDLE)
2021-10-23 23:20:57 +02:00
gfx.Text(result.medianHitDelta.." ms", rightX, baseY);
gfx.Text(math.floor(result.meanHitDelta).." ms", rightX, baseY + detailTextMargin);
--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
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();
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
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 *
2021-08-19 20:16:22 +02:00
(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
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)
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)
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