diff --git a/docs/lua_api/challengeresult.lua b/docs/lua_api/challengeresult.lua new file mode 100644 index 0000000..335a311 --- /dev/null +++ b/docs/lua_api/challengeresult.lua @@ -0,0 +1,121 @@ +-- challengeresult `result` table + +---@diagnostic disable:lowercase-global +---@diagnostic disable:missing-return + +---@class ChallengeHitStat +---@field timeFrac number -- Fraction of when in the chart the note was hit, `0.0` to `1.0` +---@field lane integer -- `0` = A, `1` = B, `2` = C, `3` = D, `4` = L, `5` = R, `6` = Left Laser, `7` = Right Laser +---@field time integer -- When in the chart the note was hit, in milliseconds +---@field delta integer -- Delta value of the hit from 0 +---@field rating integer -- `0 = Miss`, `1 = Near`, `2 = Crit` + +---@class ChallengeHitWindow +---@field good integer # Near window, default `92` +---@field hold integer -- Hold window, default `138` +---@field miss integer -- Miss window, default `250` +---@field perfect integer -- Critical window, default `46` +---@field slam integer -- Slam window, default `84` +---@field type integer -- `1 = Normal` default, `2 = Hard` default values halved + +---@class ChartResultScore +---@field auto_flags integer # Autoplay flag +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field combo integer # Best combo reached +---@field earlies integer # Total early hits +---@field gauge number # Ending gauge percentage, `0.0` to `1.0` +---@field gauge_option integer # Gauge option e.g. ARS +---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive +---@field goods integer # Total near hits +---@field hitWindow ChallengeHitWindow # Hit windows of the score +---@field lates integer # Total late hits +---@field mirror integer # Mirror mode flag +---@field misses integer # Total errors +---@field perfects integer # Total critical hits +---@field random integer # Random mode flag +---@field score integer # Result score +---@field timestamp integer # Unix timestamp of the score + +---@class ChartResult +---@field artist string # Chart artist +---@field autoplay boolean # Autoplay bool, always false +---@field auto_flags integer # Autoplay flag +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field bpm number # Chart BPM +---@field difficulty integer # Difficulty index +---@field duration integer # Chart duration, in milliseconds +---@field earlies integer # Total early hits +---@field effector string # Chart effector +---@field failReason string # Reason for failing the chart +---@field gauge number # Ending gauge percentage, `0.0` to `1.0` +---@field gaugeSamples number[] # Gauge values sampled (256 total) throughout the play +---@field gauge_option integer # Gauge option e.g. ARS +---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive +---@field goods integer # Total near hits +---@field grade string # Result grade +---@field highScores ChartResultScore[] # All scores +---@field hitWindow ChallengeHitWindow # Result hit windows +---@field illustrator string # Chart jacket illustrator +---@field isSelf boolean # Always true +---@field jacketPath string # Full filepath to the jacket image on the disk +---@field lates integer # Total late hits +---@field level integer # Chart level +---@field maxCombo integer # Result max chain +---@field meanHitDelta number # Mean hit delta +---@field meanHitDeltaAbs number # Absolute value of mean hit delta +---@field medianHitDelta integer # Median hit delta +---@field medianHitDeltaAbs integer # Absolute value of median hit delta +---@field mirror boolean # Mirror mode bool +---@field misses integer # Total errors +---@field mission string # Always empty string +---@field noteHitStats ChallengeHitStat[] # Hit stats for every chip hit +---@field passed boolean # Chart passed +---@field percent integer # Chart challenge percent +---@field perfects integer # Total critical hits +---@field playbackSpeed number # Always 1.0 +---@field random boolean # Random mode bool, +---@field realTitle string # Chart title, always without player name +---@field retryCount integer # Always 0 +---@field score integer # Result score +---@field speedModType integer # `0` = XMOD, `1` = MMOD, `2` = CMOD +---@field speedModValue number # `HiSpeed` for `XMOD`, `ModSpeed` otherwise +---@field title string # Chart title + +---@class ChallengeResult +---@field avgCrits integer # Average number of critical hits across the charts +---@field avgErrors integer # Average number of error hits across the charts +---@field avgGauge number # Average gauge percentage across the charts +---@field avgNears integer # Average number of near hits of the charts +---@field avgPercentage integer # Average completion percentage across the charts +---@field avgScore integer # Average score across the charts +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field charts ChartResult[] # array of result information for all played charts (note: might not be all charts in course) +---@field failReason string # Reason for failing the challenge +---@field grade string # Result grade +---@field isSelf boolean # Always true +---@field level integer # Chart or challenge level +---@field overallCrits integer # Total number of critical hits across the charts +---@field overallErrors integer # Total number of error hits across the charts +---@field overallNears integer # Total number of near hits across the charts +---@field passed boolean # Whether or not the challenge was passed +---@field requirement_text string # The challenge requirements separated by newline character `"\n"` +---@field title string # Challenge title + +---Render, called every frame +---@param deltaTime number # time in seconds between frames +---@param showStats boolean # true when left FX is pressed +render = function (deltaTime, showStats) end + +---This is called right after result is set, either for initial display or when the player whose score is being displayed is changed. +result_set = function () end + +---The region of the screen to be saved in score screenshots. +---@return number x # top left X coordinate +---@return number y # top left Y coordinate +---@return number w # width +---@return number h # height +get_capture_rect = function () end + +---Called when a screenshot has been captured successfully. +---@param path string # path to the saved screenshot +screenshot_captured = function (path) end diff --git a/docs/lua_api/result.lua b/docs/lua_api/result.lua index aa17fb9..7af03a7 100644 --- a/docs/lua_api/result.lua +++ b/docs/lua_api/result.lua @@ -1,4 +1,7 @@ --- result and challengeresult `result` table +-- result `result` table + +---@diagnostic disable:lowercase-global +---@diagnostic disable:missing-return ---@class HitStat ---@field timeFrac number -- Fraction of when in the chart the note was hit, `0.0` to `1.0` @@ -7,7 +10,6 @@ ---@field delta integer -- Delta value of the hit from 0 ---@field hold integer -- `0` for chip/laser, otherwise `# Ticks` of hold ---@field rating integer -- `0 = Miss`, `1 = Near`, `2 = Crit` -HitStat = {}; ---@class HitWindow ---@field good integer # Near window, default `92` @@ -16,7 +18,6 @@ HitStat = {}; ---@field perfect integer -- Critical window, default `46` ---@field slam integer -- Slam window, default `84` ---@field type integer -- `1 = Normal` default, `2 = Hard` default values halved -HitWindow = {}; ---@class Score ---@field auto_flags integer # Autoplay flag @@ -25,21 +26,25 @@ HitWindow = {}; ---@field gauge_option integer # Gauge option e.g. ARS ---@field gauge_type integer # `0` = Normal, `1` = Hard, `2` = Permissive, `3` = Blastive ---@field goods integer # Total near hits ----@field hitWindow HitWindow|nil # Hit windows of the score, only for singleplayer results screen +---@field hitWindow HitWindow # Hit windows of the score ---@field mirror integer # Mirror mode flag ---@field misses integer # Total errors ----@field name nil|string # Only for multiplayer results, name of the player ---@field perfects integer # Total critical hits ---@field random integer # Random mode flag ---@field score integer # Result score ---@field timestamp integer # Unix timestamp of the score ----@field uid nil|string # Only for multiplayer results, UID of the player -Score = {}; ----@class ChartResult : result ----@field passed boolean # Whether or not challenge requirements were met for this chart ----@field failReason string # Fail reason if a challenge requirement was not met -ChartResult = {}; +---@class MultiplayerScore +---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain +---@field flags integer # Autoplay flag +---@field gauge number # Ending gauge percentage, `0.0` to `1.0` +---@field goods integer # Total near hits +---@field misses integer # Total errors +---@field name string # Name of the player +---@field perfects integer # Total critical hits +---@field score integer # Result score +---@field timestamp integer # Unix timestamp of the score +---@field uid string # UID of the player ---@class ServerScoreOptions ---@field gaugeType integer # An enum value representing the gauge type used. 0 = normal, 1 = hard. Further values are not currently specified. @@ -47,7 +52,6 @@ ChartResult = {}; ---@field mirror boolean # Mirror mode enabled ---@field random boolean # Note shuffle enabled ---@field autoFlags integer # A bitfield of elements of the game that are automated. Any non-zero value means that the score was at least partially auto. -ServerScoreOptions = {} ---@class ServerScore ---@field score integer # Submitted score @@ -63,28 +67,19 @@ ServerScoreOptions = {} ---@field windows table # {perfect, good, hold, miss, slam} hit windows in milliseconds ---@field yours boolean # This score belongs to the current player ---@field justSet boolean # This score belongs to the current player, and is the score that was just achieved -ServerScore = {} ----@class result +---@class Result ---@field artist string # Chart artist ---@field auto_flags integer # Autoplay flag ---@field autoplay boolean # Autoplay bool ----@field avgCrits integer # Only for challenge results, average number of critical hits across the charts ----@field avgErrors integer # Only for challenge results, average number of error hits across the charts ----@field avgGauge number # Only for challenge results, average gauge percentage across the charts ----@field avgNears integer # Only for challenge results, average number of near hits of the charts ----@field avgPercentage integer # Only for challenge results, average completion percentage across the charts ----@field avgScore integer # Only for challenge results, average score across the charts ---@field badge integer # `0` = Manual Exit, `1` = Played, `2` = Cleared, `3` = Hard Cleared, `4` = Full Chain, `5` = Perfect Chain ---@field bpm number # Chart BPM ----@field charts ChartResult[] # Only for challenge results, array of chart results ---@field chartHash string # Chart hash ---@field difficulty integer # Difficulty index ---@field displayIndex nil|integer # Only for multiplayer results, the index of the score being viewed ---@field duration integer # Chart duration, in milliseconds ---@field earlies integer # Total early hits ---@field effector string # Chart effector ----@field failReason string # Reason for failing the challenge ---@field flags integer # Gameplay option flags e.g. gauge type, mirror/random mode ---@field gauge number # Ending gauge percentage, `0.0` to `1.0` ---@field gauge_option integer # Gauge option e.g. ARS @@ -92,7 +87,7 @@ ServerScore = {} ---@field gaugeSamples number[] # Gauge values sampled (256 total) throughout the play ---@field goods integer # Total near hits ---@field grade string # Result grade ----@field highScores Score[] # All scores +---@field highScores (Score|MultiplayerScore)[] # All scores ---@field hitWindow HitWindow # Result hit windows ---@field holdHitStats HitStat[]|nil # Hit stats for every hold object, only available for singleplayer if `isSelf = true` ---@field illustrator string # Chart jacket illustrator @@ -103,7 +98,7 @@ ServerScore = {} ---@field jacketPath string # Full filepath to the jacket image on the disk ---@field laserHitStats HitStat[]|nil # Hit stats for every laser object, only available for singleplayer if `isSelf = true` ---@field lates integer # Total late hits ----@field level integer # Chart or challenge level +---@field level integer # Chart level ---@field maxCombo integer # Result max chain ---@field meanHitDelta number # Mean hit delta ---@field meanHitDeltaAbs number # Absolute value of mean hit delta @@ -113,20 +108,34 @@ ServerScore = {} ---@field misses integer # Total errors ---@field mission string # Only for practice mode ---@field noteHitStats HitStat[]|nil # Hit stats for every chip hit, only available for singleplayer if `isSelf = true` ----@field overallCrits integer # Only for challenge results, total number of critical hits across the charts ----@field overallErrors integer # Only for challenge results, total number of error hits across the charts ----@field overallNears integer # Only for challenge results, total number of near hits across the charts ----@field passed boolean # Only for challenge results, whether or not the challenge was passed ---@field perfects integer # Total critical hits ---@field playbackSpeed number # Only for practice mode, percentage from 0.25 to 1.0 ---@field playerName nil|string # Only for multiplayer ---@field random boolean # Random mode bool, ---@field realTitle string # Chart title, always without player name ----@field requirement_text string # Only for challenge results, the challenge requirements separated by newline character `"\n"` ---@field retryCount integer # Only for practice mode ---@field score integer # Result score ---@field speedModType integer # Only for singleplayer, `0` = XMOD, `1` = MMOD, `2` = CMOD ---@field speedModValue number # Only for singleplayer, `HiSpeed` for `XMOD`, `ModSpeed` otherwise ----@field title string # Chart (with player name in multiplayer) or challenge title ----@field uid nil|string # Only for multiplayer, UID of the player -result = {}; +---@field title string # Chart (with player name in multiplayer) +---@field uid nil|string # Only for multiplayer, UID of the __viewer__ +result = {} + +---Render, called every frame +---@param deltaTime number # time in seconds between frames +---@param showStats boolean # true when left FX is pressed +render = function (deltaTime, showStats) end + +---This is called right after result is set, either for initial display or when the player whose score is being displayed is changed. +result_set = function () end + +---The region of the screen to be saved in score screenshots. +---@return number x # top left X coordinate +---@return number y # top left Y coordinate +---@return number w # width +---@return number h # height +get_capture_rect = function () end + +---Called when a screenshot has been captured successfully. +---@param path string # path to the saved screenshot +screenshot_captured = function (path) end diff --git a/scripts/challengeresult.lua b/scripts/challengeresult.lua index 533ee17..506bf92 100644 --- a/scripts/challengeresult.lua +++ b/scripts/challengeresult.lua @@ -7,6 +7,11 @@ local Sound = require("common.sound") local Numbers = require('components.numbers') local VolforceWindow = require("components.volforceWindow") +-- Lua code completion annotation + +---@diagnostic disable-next-line +---@cast result ChallengeResult + -- Window variables local resX, resY diff --git a/scripts/gameplay/user_panel.lua b/scripts/gameplay/user_panel.lua index 1b8b997..d20815c 100644 --- a/scripts/gameplay/user_panel.lua +++ b/scripts/gameplay/user_panel.lua @@ -1,4 +1,4 @@ - +require("common.gameconfig") local VolforceWindow = require('components.volforceWindow'); local desw = 1080; @@ -13,7 +13,9 @@ local danBadgeImage = gfx.CreateSkinImage("dan.png", 0); local idolFrameImage = gfx.CreateSkinImage("crew/frame.png", 0); -local username = game.GetSkinSetting('username') or ''; +-- 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 drawBestDiff = function (deltaTime, score, bestReplay, y) if not bestReplay then return end @@ -138,4 +140,4 @@ end return { render=render -} \ No newline at end of file +} diff --git a/scripts/result.lua b/scripts/result.lua index 40a6540..d5e1b89 100644 --- a/scripts/result.lua +++ b/scripts/result.lua @@ -48,6 +48,8 @@ local defaultJacketImage = gfx.CreateSkinImage("result/default_jacket.png", 0); 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) local appealCardImage = gfx.CreateSkinImage("crew/appeal_card.png", 0); local danBadgeImage = gfx.CreateSkinImage("dan/inf.png", 0); @@ -166,7 +168,7 @@ local BOTTOM_PANEL_TRANSTION_ENTER_OFFSET = 256; local highScore; -local username = game.GetSkinSetting('username'); +local username = GameConfig["MultiplayerUsername"] or game.GetSkinSetting('username') or ''; local msg = game.GetSkinSetting("MSG"); local earlyLateBarsStats = { @@ -545,25 +547,27 @@ local drawBottomPanelContent = function(deltatime) -- Draw appeal card gfx.BeginPath(); gfx.ImageRect(bottomPanelX + 58, bottomPanelY + 277, 103, 132, - appealCardImage, 1, 0); + result.isSelf and appealCardImage or defaultCardImage, 1, 0); -- 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); + gfx.Text(result.isSelf and msg or ("Player "..result.displayIndex), bottomPanelX + 190, bottomPanelY + 282); -- Draw username gfx.FontSize(28) - gfx.Text(username, bottomPanelX + 190, bottomPanelY + 314); + gfx.Text(result.playerName or username, bottomPanelX + 190, bottomPanelY + 314); -- Draw dan badge gfx.BeginPath(); gfx.ImageRect(bottomPanelX + 187, bottomPanelY + 362, 107, 29, - danBadgeImage, 1, 0); + result.isSelf and danBadgeImage or defaultBadgeImage, 1, 0); -- Draw volforce - VolforceWindow.render(0, bottomPanelX + 310, bottomPanelY + 355) + if result.isSelf then + VolforceWindow.render(0, bottomPanelX + 310, bottomPanelY + 355) + end -- Draw IR text gfx.FontSize(22) diff --git a/textures/result/default_appeal_card.png b/textures/result/default_appeal_card.png new file mode 100644 index 0000000..1d12535 Binary files /dev/null and b/textures/result/default_appeal_card.png differ diff --git a/textures/result/default_dan.png b/textures/result/default_dan.png new file mode 100644 index 0000000..33413c1 Binary files /dev/null and b/textures/result/default_dan.png differ