ExperimentalGear/scripts/result.lua

913 lines
29 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")
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")
local bad = "/bad"
local okay = "/okay"
local veryokay = "/good"
local idle = "/idle"
2021-10-25 19:43:11 +02:00
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);
2022-05-06 00:05:20 +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-12-27 20:30:48 +01:00
local timming = gfx.CreateSkinImage("result/timing.png", 0);
2021-07-28 18:50:06 +02:00
2022-01-03 08:42:58 +01:00
local irpanelsB = gfx.CreateSkinImage("result/panels/new_score_blue.png",0);
local irpanelsO = gfx.CreateSkinImage("result/panels/new_score_orange.png",0)
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
}
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-06 00:05:20 +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-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
2022-05-06 00:05:20 +02:00
local timmingX = 575;
local timmingY = 1472;
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
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
2022-05-06 16:39:54 +02:00
gettyping = function (animtype)
idolAnimation = gfx.LoadSkinAnimation('crew/anim/'..crew..animtype, 1 / 30, 0, true);
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 (idolAnimTransitionScale > 1) then
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);
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
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
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
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);
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);
2022-05-06 00:05:20 +02:00
-- 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();
2022-05-06 00:05:20 +02:00
-- Draw median and mean hit delta
local addX = 418.5
local leftX = timmingX + addX
local rightX = timmingX + addX
local baseY = timmingY + 33
local detailTextMargin = 25.5
local tmw, tmh = gfx.ImageSize(timming);
gfx.BeginPath()
gfx.ImageRect(timmingX, timmingY, tmw/1.1, tmh/1.1, timming, 1, 0);
local Fillmhd, Fillmihd = math.floor(result.meanHitDelta), result.medianHitDelta;
-- result.meanHitDelta up210 down
gfx.BeginPath();
gfx.FillColor(255, 100, 0, 255);
gfx.Rect(timmingX + 210, timmingY + 27.2 , Fillmhd, 12);
gfx.Fill();
if Fillmhd >= 210 then
gfx.Rect(timmingX + 210, timmingY + 27.2 , 210, 12);
gfx.Fill();
elseif Fillmhd <= -196 then
gfx.Rect(timmingX + 210, timmingY + 27.2 , -196, 12);
gfx.Fill();
elseif Fillmhd == 0 then
gfx.Rect(timmingX + 210, timmingY + 27.2 , 1, 12);
gfx.Fill();
end
-- result.medianHitDelta
gfx.BeginPath();
gfx.FillColor(255, 136, 0, 255);
gfx.Rect(timmingX + 210, timmingY + 27.2 + detailTextMargin, Fillmihd, 12);
gfx.Fill();
if Fillmihd >= 210 then
gfx.Rect(timmingX + 210, timmingY + 27.2 + detailTextMargin, 210, 12);
gfx.Fill();
elseif Fillmihd <= -196 then
gfx.Rect(timmingX + 210, timmingY + 27.2 + detailTextMargin, -196, 12);
gfx.Fill();
elseif Fillmihd == 0 then
gfx.Rect(timmingX + 210, timmingY + 27.2 + detailTextMargin, 1, 12);
gfx.Fill();
end
gfx.ClosePath();
gfx.FillColor(255, 255, 255, 255);
gfx.FontSize(19.25)
gfx.Text(Fillmihd.."ms",timmingX + 420,timmingY + 9 + detailTextMargin)
gfx.Text(Fillmhd.."ms",timmingX + 420,timmingY + 9 + 25 + detailTextMargin)
gfx.FontSize(24)
2021-08-16 18:41:44 +02:00
-- 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,
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();
2022-05-06 00:05:20 +02:00
gfx.ImageRect(bottomPanelX + 187, bottomPanelY + 362, 107, 29,
danBadgeImage, 1, 0);
2021-08-19 20:16:22 +02:00
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);
2022-05-06 00:05:20 +02:00
-- Draw median and mean hit delta
local leftX = bottomPanelX + 600
local baseY = bottomPanelY + 440
--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 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 badgeLinesAnimScale < 1 then
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-05-06 16:39:54 +02:00
if betacrew == true then
2022-05-06 18:03:43 +02:00
if result.score < grades.S then
2022-05-06 16:39:54 +02:00
animtype = veryokay
2022-05-06 18:03:43 +02:00
elseif result.score < grades.AAA then
2022-05-06 16:39:54 +02:00
animtype = okay
2022-05-06 18:03:43 +02:00
elseif result.score < grades.A_P then
2022-05-06 16:39:54 +02:00
animtype = bad
elseif result.score < grades.A_P then
animtype = bad
2022-05-06 00:05:20 +02:00
end
2022-05-06 16:39:54 +02:00
else
animtype = idle
end
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)
2021-07-27 21:18:13 +02:00
drawRightPanel()
drawRightBarAni(deltaTime)
2022-05-06 16:39:54 +02:00
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