Merge branch 'feature/local-highscores-usernames'

This commit is contained in:
Hersi 2023-11-10 08:00:24 +01:00
commit 7694a23368
6 changed files with 1460 additions and 421 deletions

BIN
CHANGELOG Normal file

Binary file not shown.

View File

@ -1,29 +1,62 @@
-- songwheel `songwheel` table
---@class Difficulty
---@class SongWheelScore
---@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 # Max combo
---@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 isLocal integer # `0` = false, `1` = true
---@field lates integer # Total late hits
---@field mirror integer # Mirror mode flag
---@field misses integer # Total errors
---@field playerName string # 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
SongWheelScore = {}
---@class SongWheelDifficulty
---@field difficulty integer # Difficulty index
---@field effector string # Name of charter
---@field hash string # Difficulty hash
---@field id integer # Difficulty id, unique static identifier
---@field illustrator string # Difficulty jacket illustrator
---@field jacketPath string # Full filepath to the jacket image on the disk
---@field level integer # Difficulty level
---@field scores Score[] # Scores for the current difficulty
---@field scores SongWheelScore[] # Scores for the current difficulty
---@field topBadge integer # `0 = Never Played`, `1 = Played`, `2 = Cleared`, `3 = Hard Cleared`, `4 = Full Chain`, `5 = Perfect Chain`
Difficulty = {};
SongWheelDifficulty = {}
---@class Song
---@class SongWheelSong
---@field artist string # Chart artist
---@field difficulties Difficulty[] # Array of difficulties for the current song
---@field difficulties SongWheelDifficulty[] # Array of difficulties for the current song
---@field bpm number # Chart BPM
---@field id integer # Song id, unique static identifier
---@field path string # Full filepath to the chart folder on the disk
---@field title string # Chart title
Song = {};
SongWheelSong = {}
---@class songwheel
---@field allSongs Song[] # Array of all available songs
---@field allSongs SongWheelSong[] # Array of all available songs
---@field searchInputActive boolean # Search status
---@field searchStatus string # Current song database status
---@field searchText string # Search input text
---@field songs Song[] # Array of songs with the current filters/sorting applied
songwheel = {};
---@field songs SongWheelSong[] # Array of songs with the current filters/sorting applied
songwheel = {}
---Render, called every frame
---@param deltaTime number # time in seconds between frames
render = function (deltaTime) end
---Called when selected difficulty changes
---@param diff integer # Difficulty level
set_diff = function (diff) end
---Called when song database changes
---@param withAll boolean # Reload all songs
songs_changed = function (withAll) end

View File

@ -1,6 +1,6 @@
local MAJOR = 0
local MINOR = 2
local PATCH = 3
local MINOR = 3
local PATCH = 0
local function getLongVersion()
return "USC:E:G:S:" .. MAJOR .. MINOR .. PATCH

View File

@ -1,38 +1,6 @@
local json = require("common.json")
local common = require('common.util');
local Sound = require("common.sound")
local difbar = require("components.diff_rectangle");
local spinnybg = require('components.background');
local msg = game.GetSkinSetting("MSG");
local normname = game.GetSkinSetting("username")
local crew = game.GetSkinSetting("single_idol")
local m_jacket = gfx.CreateSkinImage("multi/lobby/multi_jacket.png", 1);
local m_base_panel = gfx.CreateSkinImage("multi/lobby/multi_base_panel.png", 1);
local m_anim = gfx.CreateSkinImage("multi/lobby/panel_laser.png", 1);
local m_panel = gfx.CreateSkinImage("multi/lobby/matching_panel.png", 1);
local m_s_panel = gfx.CreateSkinImage("multi/lobby/song_panel.png", 1);
local m_host_panel = gfx.CreateSkinImage("multi/lobby/user_panel.png", 1);
local m_bpm_panel = gfx.CreateSkinImage("multi/lobby/lane_speed_panel.png", 1);
local m_info_panel = gfx.CreateSkinImage("multi/lobby/button_panel.png", 1);
local headerMatchingImage = gfx.CreateSkinImage("titlescreen/entry.png", 1);
local m_4pb_panels = gfx.CreateSkinImage("multi/lobby/user_panel_2.png", 1);
local ready_bt = gfx.CreateSkinImage("multi/lobby/READY.png", 1);
local bg = gfx.CreateSkinImage("multi/lobby/bg.png", 1);
local bg_graid1 = gfx.CreateSkinImage("multi/lobby/gradient_bottom.png", 1);
local bg_graid2 = gfx.CreateSkinImage("multi/lobby/gradient_top.png", 1);
local idolAnimation = gfx.LoadSkinAnimation('crew/anim/'..crew, 1 / 30, 0, true);
local idolAnimTransitionScale = 0;
if not idolAnimation then
game.Log("Crew folder crew/anim/"..crew.." does not exist.", game.LOGGER_WARNING)
end
local sound = require('common.sound');
local resX,resY = game.GetResolution()
@ -43,15 +11,6 @@ local buttonWidth = resX*(3/4);
local buttonHeight = 75;
local buttonBorder = 2;
local portrait
local jacket_size;
local BAR_ALPHA = 191;
local HEADER_HEIGHT = 100
local resx, resy = game.GetResolution()
local desw = 1080
local desh = 1920
local scale;
game.LoadSkinSample("click-02")
game.LoadSkinSample("click-01")
@ -65,7 +24,6 @@ local user_id = nil;
local jacket = 0;
local all_ready;
local user_ready;
local go;
local hard_mode = false;
local rotate_host = false;
local start_game_soon = false;
@ -75,20 +33,19 @@ local missing_song = false;
local placeholderJacket = gfx.CreateSkinImage("song_select/loading.png", 0)
local did_exit = false;
local irHeartbeatRequested = false;
local irText = ''
local diffColors = {{0,0,255}, {0,255,0}, {255,0,0}, {255, 0, 255}}
local grades = {
{["max"] = 6900000, ["image"] = gfx.CreateSkinImage("common/grades/D.png", 0)},
{["max"] = 7900000, ["image"] = gfx.CreateSkinImage("common/grades/C.png", 0)},
{["max"] = 8600000, ["image"] = gfx.CreateSkinImage("common/grades/B.png", 0)},
{["max"] = 8900000, ["image"] = gfx.CreateSkinImage("common/grades/A.png", 0)},
{["max"] = 9200000, ["image"] = gfx.CreateSkinImage("common/grades/A+.png", 0)},
{["max"] = 9400000, ["image"] = gfx.CreateSkinImage("common/grades/AA.png", 0)},
{["max"] = 9600000, ["image"] = gfx.CreateSkinImage("common/grades/AA+.png", 0)},
{["max"] = 9700000, ["image"] = gfx.CreateSkinImage("common/grades/AAA.png", 0)},
{["max"] = 9800000, ["image"] = gfx.CreateSkinImage("common/grades/AAA+.png", 0)},
{["max"] = 9900000, ["image"] = gfx.CreateSkinImage("common/grades/S.png", 0)}
{["max"] = 6999999, ["image"] = gfx.CreateSkinImage("common/grades/D.png", 0)},
{["max"] = 7999999, ["image"] = gfx.CreateSkinImage("common/grades/C.png", 0)},
{["max"] = 8699999, ["image"] = gfx.CreateSkinImage("common/grades/B.png", 0)},
{["max"] = 8999999, ["image"] = gfx.CreateSkinImage("common/grades/A.png", 0)},
{["max"] = 9299999, ["image"] = gfx.CreateSkinImage("common/grades/A+.png", 0)},
{["max"] = 9499999, ["image"] = gfx.CreateSkinImage("common/grades/AA.png", 0)},
{["max"] = 9699999, ["image"] = gfx.CreateSkinImage("common/grades/AA+.png", 0)},
{["max"] = 9799999, ["image"] = gfx.CreateSkinImage("common/grades/AAA.png", 0)},
{["max"] = 9899999, ["image"] = gfx.CreateSkinImage("common/grades/AAA+.png", 0)},
{["max"] = 99999999, ["image"] = gfx.CreateSkinImage("common/grades/S.png", 0)}
}
local badges = {
@ -119,262 +76,9 @@ end
local SERVER = game.GetSkinSetting("multi.server")
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 (idolAnimTransitionScale > 1) then
idolAnimTransitionScale = 1;
end
gfx.ImageRect(0, 0, resX,resY, idolAnimation, 1, 0);
gfx.GlobalAlpha(1);
end
end
end
songjacket = function() -- self explanatory
if portrait then
split = resX
jacket_size = math.min(resX/4, resY/4);
song_x_off = 0;
else
split = resX/2
jacket_size = math.min(resX/2, resY/2);
song_x_off = 1/2*resX;
end
local jw , jh = gfx.ImageSize(m_jacket);
gfx.BeginPath();
gfx.ImageRect(333, 1284, jw/1.18, jh/1.18, m_jacket,1,0);
end
m_own_info = function()
local x = 0
local y = 1310
gfx.BeginPath();
gfx.FontSize(40)
gfx.ImageRect(x, y, 343/1.18, 361/1.18,m_host_panel,1,0)
gfx.Text(normname, x+20, y+78)
gfx.FontSize(22)
gfx.Text(irText, x+5, y+288);
end
m_base_part = function() -- just the images which slide up
local jw , jh = gfx.ImageSize(m_base_panel);
gfx.BeginPath();
gfx.ImageRect(1, 1250, jw/1.17, jh/1.18, m_base_panel,1,0);
gfx.BeginPath();
gfx.ImageRect(1, 1250, jw/1.17, jh/1.18, m_anim,1,0);
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.FillColor(255,255,255)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT, gfx.TEXT_ALIGN_LEFT)
gfx.FontSize(24)
end
m_part = function() -- room name part
local jw , jh = gfx.ImageSize(m_panel);
gfx.BeginPath();
gfx.ImageRect(429, 1142, jw/1.175, jh/1.18, m_panel,1,0);
gfx.FontSize(32);
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT, gfx.TEXT_ALIGN_MIDDLE)
gfx.Text(selected_room.name, 575, 1179)
end
m_s_part = function () -- song info panel
local jw , jh = gfx.ImageSize(m_s_panel);
gfx.BeginPath();
gfx.ImageRect(283, 1187, jw/1.175, jh/1.18, m_s_panel,1,0);
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_LEFT);
gfx.FillColor(255,255,255)
gfx.FontSize(32)
if selected_song == nil then
if host == user_id then
gfx.Text("NO SONG", 535, 1236)
gfx.Text("NO ARIST", 535, 1275)
gfx.FontSize(24)
gfx.Text("NO EFFECTOR", 746, 1378)
gfx.Text("NO ILLUSTRATOR", 746, 1406)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.FontSize(22)
gfx.Text("BPM ?",780, 1307)
else
if missing_song then
gfx.Text("MISSING SONG!!!!", 535, 1235)
gfx.Text("MISSING ARIST!!!!", 535, 1275)
gfx.FontSize(24)
gfx.Text("MISSING EFFECTOR!!!!", 744, 1378)
gfx.Text("MISSING ILLUSTRATOR!!!!", 744, 1406)
else
gfx.Text("HOST IS SELECTING SONG", 535, 1235)
gfx.Text(" ", 535, 1275)
gfx.FontSize(24)
gfx.Text(" ", 746, 1378)
gfx.Text(" ", 746, 1406)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.FontSize(22)
gfx.Text("BPM ?",780, 1307)
end
end
else
if selected_song.min_bpm ~= selected_song.max_bpm then
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.FontSize(22);
gfx.Text("BPM",777, 1307)
gfx.FontSize(26);
gfx.Text(string.format("%.0f - %.0f",
selected_song.min_bpm, selected_song.max_bpm),
780 + 77, 1307)
else
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.FontSize(22);
gfx.Text("BPM",777, 1307)
gfx.Text(string.format("%.0f",
selected_song.min_bpm),
780 + 77, 1307)
end
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_LEFT);
gfx.FontSize(32);
gfx.Text(selected_song.title, 535, 1236)
gfx.Text(selected_song.artist, 535, 1275)
gfx.FontSize(24)
gfx.Text(selected_song.effector, 746, 1377)
gfx.Text(selected_song.illustrator, 746, 1406)
end
end
m_bpm_part = function () -- bpm and lane speed
local jw , jh = gfx.ImageSize(m_bpm_panel);
gfx.BeginPath();
gfx.ImageRect(0, 1692, jw/1.18, jh/1.18, m_bpm_panel,1,0);
gfx.FontSize(32)
if selected_song == nil then
if host == user_id then
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.FontSize(32)
gfx.Text("BPM ?",76, 1788)
gfx.Text("LANE-SPEED ?",76, 1832)
else
if missing_song then
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.FontSize(32)
gfx.Text("BPM ?",76, 1788)
gfx.Text("LANE-SPEED ?",76, 1832)
else
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.FontSize(32)
gfx.Text("BPM ?",76, 1788)
gfx.Text("LANE-SPEED ?",76, 1832)
end
end
end
if selected_song ~= nil then
gfx.FillColor(255,255,255)
gfx.FontSize(32);
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
if selected_song.min_bpm ~= selected_song.max_bpm then
gfx.Text("BPM",76, 1788)
gfx.Text(string.format("%.0f - %.0f",
selected_song.min_bpm, selected_song.max_bpm),
76 + 75, 1788)
gfx.Text("LANE-SPEED",76, 1832)
gfx.Text(string.format("%.2f = %.0f",
selected_song.hispeed, selected_song.speed_bpm * selected_song.hispeed),
76 + 175, 1832)
else
gfx.FontSize(32);
gfx.Text("BPM",76, 1788)
gfx.Text(string.format("%.0f",
selected_song.min_bpm),
76 + 75, 1788)
gfx.Text("LANE-SPEED",76, 1832)
gfx.Text(string.format("%.2f = %.0f",
selected_song.hispeed, selected_song.speed_bpm * selected_song.hispeed),
76 + 175, 1832)
end
end
end
m_info_part = function () -- the info panel
local jw , jh = gfx.ImageSize(m_info_panel);
gfx.BeginPath();
gfx.ImageRect(475, 1590, jw/1.18, jh/1.18, m_info_panel,1,0);
local check = 770
draw_checkbox("Excessive", check - 200, 1625, toggle_hard, hard_mode, not start_game_soon)
draw_checkbox("Mirror Mode",check - 15, 1625, toggle_mirror, mirror_mode, not start_game_soon)
draw_checkbox("Rotate Host",check + 175, 1625, toggle_rotate, do_rotate,
(owner == user_id or host == user_id) and not start_game_soon)
for i, user in ipairs(lobby_users) do
buttonY = 1775
local side_button_off = 0
if owner == user_id and user.id ~= user_id then
draw_button("K",525+side_button_off, buttonY, 50, function()
kick_user(user);
end)
side_button_off = 60;
end
if (owner == user_id or host == user_id) and user.id ~= host then
draw_button("H",525+side_button_off, buttonY+85, 50, function()
change_host(user);
end)
end
end
end
user_setup = function () -- (semi new) user layering
local distance = 350
for i, user in ipairs(lobby_users) do
if i == 1 then
draw_user(user, -distance, 1142-360/1.2, 420/1.2, 330/1.2, i,215,245.5)
elseif i == 2 then
draw_user(user, 16, 1142-360/1.2, 420/1.2, 330/1.2, i,215,245.5)
elseif i == 3 then
draw_user(user, 16+distance, 1142-360/1.2, 420/1.2, 330/1.2, i,215,245.5)
elseif i == 4 then
draw_user(user, 16+distance+distance, 1142-360/1.2, 420/1.2, 330/1.2, i,215,245.5)
elseif i > 4 then
draw_user(user, 16+distance+distance+distance+distance, 1142-360/1.2, 420/1.2, 330/1.2, i,215,245.5)
end
end
end
function drawHeader()
gfx.BeginPath();
gfx.FillColor(0, 0, 0, BAR_ALPHA);
gfx.Rect(0, 0, desw, HEADER_HEIGHT);
gfx.Fill();
gfx.ClosePath()
gfx.ImageRect(desw/2 - 200, HEADER_HEIGHT/2 - 20, 400, 40, headerMatchingImage, 1, 0)
end
mouse_clipped = function(x,y,w,h)
return mposx > x and mposy > y and mposx < x+w and mposy < y+h;
@ -441,6 +145,8 @@ draw_button_color = function(name, x, y, buttonWidth, hoverindex,r,g,b, olr,olg,
end;
draw_checkbox = function(text, x, y, hoverindex, current, can_click)
local rx = x - (buttonWidth / 2);
local ty = y - (buttonHeight / 2);
gfx.BeginPath();
if can_click then
@ -450,7 +156,6 @@ draw_checkbox = function(text, x, y, hoverindex, current, can_click)
end
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE);
gfx.FontSize(35);
gfx.FillColor(201,0,0);
gfx.Text(text, x, y)
local xmin,ymin,xmax,ymax = gfx.TextBounds(x, y, text);
@ -458,55 +163,121 @@ draw_checkbox = function(text, x, y, hoverindex, current, can_click)
local sx = xmin - 40;
local sy = y - 15;
if can_click and mouse_clipped(xmin-10, ymin, xmax-xmin, ymax-ymin) then
gfx.StrokeColor(0,128,255);
if can_click and (mouse_clipped(sx, sy, 31, 30) or mouse_clipped(xmin-10, ymin, xmax-xmin, ymax-ymin)) then
hovered = hoverindex;
gfx.StrokeColor(255,128,0);
end
gfx.Rect(sx, y - 15, 30, 30)
gfx.StrokeWidth(2)
gfx.Stroke()
if current then
-- Draw checkmark
gfx.BeginPath();
gfx.FillColor(0, 236, 0);
gfx.Text(text, x, y)
gfx.Fill();
gfx.MoveTo(sx+5, sy+10);
gfx.LineTo(sx+15, y+5);
gfx.LineTo(sx+35, y-15);
gfx.StrokeWidth(5)
gfx.StrokeColor(0,255,0);
gfx.Stroke()
end
end;
--look into user changing -- IMPORTANT !!!
draw_user = function(user, x, y , w, h, rank, breadx,bready)
local name = user.name
local showthing = false
local userHeight = 100
draw_user = function(user, x, y, buttonWidth, rank)
local buttonHeight = userHeight;
local rx = x - (buttonWidth / 2);
local ty = y - (buttonHeight / 2);
gfx.BeginPath();
gfx.FillColor(256,128,255);
gfx.Rect(rx - buttonBorder,
ty - buttonBorder,
buttonWidth + (buttonBorder * 2),
buttonHeight + (buttonBorder * 2));
gfx.Fill();
gfx.BeginPath();
if host == user.id then
gfx.FillColor(80,0,0);
else
gfx.FillColor(0,0,40);
end
gfx.Rect(rx, ty, buttonWidth, buttonHeight);
gfx.Fill();
gfx.BeginPath();
gfx.FillColor(255,255,255);
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE);
gfx.FontSize(40);
local name = user.name;
if user.id == user_id then
name = name
end
if user.id == host then
name = name
name = name..' (host)'
elseif user.missing_map then
name = name..' (NO CHART)'
elseif user.ready then
showthing = true
elseif not user.ready then
showthing = false
end
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE);
gfx.FillColor(255,255,255)
gfx.FontSize(42)
gfx.FontSize(30)
gfx.BeginPath();
gfx.ImageRect(x, y ,w, h,m_4pb_panels,1,0)
gfx.Text(name, x+135, y+51)
if showthing == true then
local jw , jh = gfx.ImageSize(ready_bt);
gfx.BeginPath();
gfx.ImageRect(x+breadx, y+bready, jw/1.18, jh/1.18, ready_bt,1,0);
elseif showthing == false then
local jw , jh = gfx.ImageSize(ready_bt);
gfx.BeginPath();
gfx.ImageRect(x+breadx, y+bready, jw/1.18, jh/1.18, ready_bt,0,0);
name = name..' (ready)'
end
if user.score ~= nil then
name = '#'..rank..' '..name
end
first_y = y - 28
second_y = y + 28
gfx.Text(name, x - buttonWidth/2 + 5, first_y);
if user.score ~= nil then
gfx.FillColor(255,255,0)
gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_MIDDLE);
local combo_text = ' '..user.combo..'x'
gfx.Text(combo_text, x+buttonWidth/2 - 5, second_y-5);
local xmin,ymin,xmax,ymax = gfx.TextBounds(x+buttonWidth/2 - 5, second_y-5, combo_text);
local score_text = ' '..string.format("%08d",user.score);
gfx.FillColor(255,255,255)
gfx.Text(score_text, xmin, second_y-5);
xmin,ymin,xmax,ymax = gfx.TextBounds(xmin, second_y-5, score_text);
if user.grade == nil then
for i,v in ipairs(grades) do
if v.max > user.score then
user.grade = v.image
break
end
end
end
if user.badge == nil and user.clear > 1 then
user.badge = badges[user.clear];
end
gfx.BeginPath()
local iw, ih = gfx.ImageSize(user.grade)
local iar = iw/ih
local grade_height = buttonHeight/2 - 10
gfx.ImageRect(xmin - iar * grade_height, second_y - buttonHeight/4 , iar * grade_height, grade_height, user.grade, 1, 0)
end
if user.level ~= 0 then
gfx.FillColor(255,255,0)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE);
local level_text = 'Lvl '..user.level..' '
gfx.Text(level_text, x-buttonWidth/2 + 5, second_y-5)
local xmin,ymin,xmax,ymax = gfx.TextBounds(x-buttonWidth/2 + 5, second_y-5, level_text);
if user.badge then
gfx.BeginPath()
local iw, ih = gfx.ImageSize(user.badge)
local iar = iw/ih;
local badge_height = buttonHeight/2 - 10
gfx.ImageRect(xmax+5, second_y - buttonHeight/4 , iar * badge_height, badge_height, user.badge, 1, 0)
end
end
end;
function render_loading()
@ -529,38 +300,89 @@ function render_loading()
end
function render_info()
if searchStatus then
gfx.Save()
gfx.ResetTransform()
gfx.BeginPath()
gfx.MoveTo(0, resY)
gfx.LineTo(550, resY)
gfx.LineTo(500, resY - 65)
gfx.LineTo(0, resY - 65)
gfx.ClosePath()
gfx.FillColor(33,33,33)
gfx.Fill()
gfx.FillColor(255,255,255)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT, gfx.TEXT_ALIGN_BOTTOM)
gfx.FontSize(70)
gfx.Text("Multiplayer", 3, resY - 15)
local xmin,ymin,xmax,ymax = gfx.TextBounds(3, resY - 3, "Multiplayer")
gfx.FontSize(20)
gfx.Text(MULTIPLAYER_VERSION, xmax + 13, resY - 15)
--gfx.Text('Server: '..'', xmax + 13, resY - 15)
draw_button_color("Settings", 500-60, resY-25, 120, function()
mpScreen.OpenSettings();
end, 33,33,33, 33,33,33)
gfx.Restore()
if searchStatus then
gfx.BeginPath()
gfx.FillColor(255,255,255)
gfx.FontSize(20);
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP)
gfx.Text(searchStatus, 3, 3)
end
end
draw_diff_icon = function(diff, x, y, w, h)
difbar.render(deltaTime, x, y, 1, diff.difficulty, diff.level);
draw_diff_icon = function(diff, x, y, w, h, selected)
local shrinkX = w/4
local shrinkY = h/4
if selected then
gfx.FontSize(h/2)
shrinkX = w/6
shrinkY = h/6
else
gfx.FontSize(math.floor(h / 3))
end
gfx.BeginPath()
gfx.RoundedRectVarying(x+shrinkX,y+shrinkY,w-shrinkX*2,h-shrinkY*2,0,0,0,0)
gfx.FillColor(15,15,15)
gfx.StrokeColor(table.unpack(diffColors[diff.difficulty + 1]))
gfx.StrokeWidth(2)
gfx.Fill()
gfx.Stroke()
gfx.FillColor(255,255,255)
gfx.TextAlign(gfx.TEXT_ALIGN_MIDDLE + gfx.TEXT_ALIGN_CENTER)
gfx.FastText(tostring(diff.level), x+(w/2),y+(h/2))
end
local doffset = 0;
local timer = 0;
local possy = 1095;
local possx = 150;
draw_cursor = function(x,y,rotation,width)
gfx.Save()
gfx.BeginPath();
gfx.Translate(x,y)
gfx.Rotate(rotation)
gfx.StrokeColor(255,128,0)
gfx.StrokeWidth(4)
gfx.Rect(-width/2, -width/2, width, width)
gfx.Stroke()
gfx.Restore()
end
draw_diffs = function(diffs, x, y, w, h, selectedDiff)
local diffWidth = w/2
local diffHeight = w/2
local diffWidth = w/2.5
local diffHeight = w/2.5
local diffCount = #diffs
gfx.Scissor(x+84 + possx,y + possy,w/2.451,h)
gfx.Scissor(x,y,w,h)
for i = math.max(selectedDiff - 2, 1), math.max(selectedDiff - 1,1) do
local diff = diffs[i]
local xpos = x + ((w/2 - diffWidth/2) + (selectedDiff - i + doffset)*(-0.8*diffWidth))
if i ~= selectedDiff then
draw_diff_icon(diff, xpos + possx, y + possy, diffWidth, diffHeight, false)
draw_diff_icon(diff, xpos, y, diffWidth, diffHeight, false)
end
end
@ -569,14 +391,21 @@ draw_diffs = function(diffs, x, y, w, h, selectedDiff)
local diff = diffs[i]
local xpos = x + ((w/2 - diffWidth/2) + (selectedDiff - i + doffset)*(-0.8*diffWidth))
if i ~= selectedDiff then
draw_diff_icon(diff, xpos + possx, y + possy, diffWidth, diffHeight, false)
draw_diff_icon(diff, xpos, y, diffWidth, diffHeight, false)
end
end
local diff = diffs[selectedDiff]
local xpos = x + ((w/2 - diffWidth/2) + (doffset)*(-0.8*diffWidth))
draw_diff_icon(diff, xpos + possx, y + possy, diffWidth, diffHeight, true)
draw_diff_icon(diff, xpos, y, diffWidth, diffHeight, true)
gfx.BeginPath()
gfx.FillColor(0,128,255)
gfx.Rect(x,y+10,2,diffHeight-h/6)
gfx.Fill()
gfx.BeginPath()
gfx.Rect(x+w-2,y+10,2,diffHeight-h/6)
gfx.Fill()
gfx.ResetScissor()
draw_cursor(x + w/2, y +diffHeight/2, timer * math.pi, diffHeight / 1.5)
end
set_diff = function(oldDiff, newDiff)
@ -621,7 +450,7 @@ function draw_rooms(y, h)
local ypos = y + (h/2) - offsetY;
local status = room.current..'/'..room.max
if room.ingame then
status = status..' (IN MATCH)'
status = status..' (In Game)'
end
if room.password then
status = status..' <P>'
@ -658,51 +487,75 @@ change_selected_room = function(off)
selected_room_index = new_index;
end
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
function render_lobby(deltaTime)
local jw , jh = gfx.ImageSize(bg);
gfx.BeginPath();
gfx.ImageRect(0, 0, resX, resY, bg,1,0);
drawIdol(deltaTime)
gfx.BeginPath();
gfx.ImageRect(0, 0, resX, resY, bg_graid1,1,0);
gfx.ImageRect(0, 0, resX, resY, bg_graid2,1,0);
drawHeader()
gfx.BeginPath();
m_base_part()
local jacket_size;
m_own_info()
user_setup()
-- split is how the screen is split or not
if portrait then
split = resX
jacket_size = math.min(resX/3, resY/3);
user_y_off = 375+jacket_size + 70
song_x_off = 0;
else
split = resX/2
jacket_size = math.min(resX/2, resY/2);
user_y_off = 0
song_x_off = 1/2*resX;
end
m_info_part()
m_part()
m_s_part()
m_bpm_part()
songjacket()
gfx.FillColor(255,255,255)
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER, gfx.TEXT_ALIGN_BOTTOM)
gfx.FontSize(70)
gfx.Text(selected_room.name, resX/2, 50)
-- === Users ===
gfx.Text("Users", split/2, user_y_off+100)
buttonY = user_y_off + 125 + userHeight/2
for i, user in ipairs(lobby_users) do
draw_user(user, split/2, buttonY, split*3/4, i)
local side_button_off = 0
if owner == user_id and user.id ~= user_id then
draw_button("K",split/2 + split*3/8+10+25, buttonY, 50, function()
kick_user(user);
end)
side_button_off = 60;
end
if (owner == user_id or host == user_id) and user.id ~= host then
draw_button("H",split/2 + split*3/8+10+25+side_button_off, buttonY, 50, function()
change_host(user);
end)
end
buttonY = buttonY + userHeight
end
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE);
gfx.FillColor(255,255,255)
-- === song select ===
gfx.FontSize(60)
gfx.Text("Selected Song:", split/2 + song_x_off, 100)
gfx.FontSize(40)
if selected_song == nil then
if host == user_id then
gfx.Text("Select song:", split/2 + song_x_off, 175)
else
if missing_song then
gfx.Text("Missing song!!!!", split/2 + song_x_off, 175)
else
gfx.Text("Host is selecting song", split/2 + song_x_off, 175)
end
end
if jacket == 0 then
jacket = placeholderJacket
end
else
gfx.Text(selected_song.title, split/2 + song_x_off, 175)
draw_diffs(selected_song.all_difficulties, split/2 + song_x_off - 150, 200, 300, 100, selected_song.diff_index+1)
if selected_song.jacket == nil or selected_song.jacket == placeholderJacket then
selected_song.jacket = gfx.LoadImageJob(selected_song.jacketPath, placeholderJacket)
jacket = selected_song.jacket
@ -710,22 +563,75 @@ function render_lobby(deltaTime)
end
gfx.Save()
gfx.BeginPath()
gfx.Translate(481, 1303+jacket_size/2)
gfx.Translate(split/2 + song_x_off, 325+jacket_size/2)
gfx.ImageRect(-jacket_size/2,-jacket_size/2,jacket_size,jacket_size,jacket,1,0)
if mouse_clipped(481-jacket_size/2,1423+-jacket_size/2,jacket_size,jacket_size) and host == user_id then
if mouse_clipped(split/2 + song_x_off-jacket_size/2, 325, jacket_size,jacket_size) and host == user_id then
hovered = function()
missing_song = false
mpScreen.SelectSong()
end
end
gfx.Restore()
if start_game_soon then
draw_button("Game starting...", split/2 + song_x_off, 375+jacket_size, 600, function() end);
else
if host == user_id then
if selected_song == nil or not selected_song.self_picked then
draw_button_color("Select song", split/2 + song_x_off, 375+jacket_size, 600, function()
missing_song = false
mpScreen.SelectSong()
end, 0, math.min(255, 128 + math.floor(32 * math.cos(timer * math.pi))), 0, 0,128,255);
elseif user_ready and all_ready then
draw_button("Start game", split/2 + song_x_off, 375+jacket_size, 600, start_game)
elseif user_ready and not all_ready then
draw_button("Waiting for others", split/2 + song_x_off, 375+jacket_size, 600, function()
missing_song = false
mpScreen.SelectSong()
end)
else
draw_button("Ready", split/2 + song_x_off, 375+jacket_size, 600, ready_up);
end
elseif host == nil then
draw_button("Waiting for game to end", split/2 + song_x_off, 375+jacket_size, 600, function() end);
elseif missing_song then
draw_button("Missing Song!", split/2 + song_x_off, 375+jacket_size, 600, function() end);
elseif selected_song ~= nil then
if user_ready then
draw_button("Cancel", split/2 + song_x_off, 375+jacket_size, 600, ready_up);
else
draw_button("Ready", split/2 + song_x_off, 375+jacket_size, 600, ready_up);
end
else
draw_button("Waiting for host", split/2 + song_x_off, 375+jacket_size, 600, function() end);
end
end
draw_checkbox("Excessive", split/2 + song_x_off - 150, 375+jacket_size + 70, toggle_hard, hard_mode, not start_game_soon)
draw_checkbox("Mirror", split/2 + song_x_off, 375+jacket_size + 70, toggle_mirror, mirror_mode, not start_game_soon)
draw_checkbox("Rotate Host", split/2 + song_x_off + 150 + 20, 375+jacket_size + 70, toggle_rotate, do_rotate,
(owner == user_id or host == user_id) and not start_game_soon)
if selected_song ~= nil then
gfx.FillColor(255,255,255)
gfx.FontSize(20);
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_TOP)
if selected_song.min_bpm ~= selected_song.max_bpm then
gfx.Text(string.format("BPM: %.0f-%.0f, Start BPM: %.0f, Hispeed: %.0f x %.1f = %.0f",
selected_song.min_bpm, selected_song.max_bpm, selected_song.start_bpm,
selected_song.speed_bpm, selected_song.hispeed, selected_song.speed_bpm * selected_song.hispeed),
split/2 + song_x_off, 375+jacket_size + 70 + 30)
else
gfx.Text(string.format("BPM: %.0f, Hispeed: %.0f x %.1f = %.0f",
selected_song.min_bpm,
selected_song.speed_bpm, selected_song.hispeed, selected_song.speed_bpm * selected_song.hispeed),
split/2 + song_x_off, 375+jacket_size + 70 + 30)
end
end
end
function render_room_list(deltaTime)
spinnybg.draw(deltaTime);
draw_rooms(175, resY - 290);
-- Draw cover for rooms out of view
@ -793,18 +699,19 @@ function render_new_room_password(delta_time)
gfx.Text(string.rep("*",#textInput.text), resX/2, resY/2+40)
draw_button("Create Room", resX/2, resY*3/4, resX/2, mpScreen.NewRoomStep);
end
--here
function render_new_room_name(deltaTime)
gfx.BeginPath();
gfx.LoadSkinFont("segoeui.ttf")
gfx.FillColor(255,255,255)
gfx.TextAlign(gfx.TEXT_ALIGN_CENTER, gfx.TEXT_ALIGN_BOTTOM)
gfx.FontSize(70)
gfx.Text("Create New Room", resX/2, resY/4)
gfx.FillColor(50,50,50)
gfx.BeginPath()
gfx.Rect(0, resY/2-10, resX, 60)
gfx.Fill();
gfx.FillColor(255,255,255)
gfx.Text("Please enter room name:", resX/2, resY/2-40)
gfx.Text(textInput.text, resX/2, resY/2+40)
draw_button("Next", resX/2, resY*3/4, resX/2, mpScreen.NewRoomStep);
@ -837,8 +744,7 @@ render = function(deltaTime)
mposx,mposy = game.GetMousePos();
portrait = resY > resX
IR_Handle()
Sound.stopMusic();
sound.stopMusic();
doffset = doffset * 0.9
ioffset = ioffset * 0.9
@ -931,11 +837,10 @@ function join_room(room)
mpScreen.JoinWithoutPassword(room.id)
end
end
local que1 = 0
-- Handle button presses to advance the UI
button_pressed = function(button)
if button == game.BUTTON_FXL and game.BUTTON_FXR then
if button == game.BUTTON_STA then
if start_game_soon then
return
end
@ -965,10 +870,10 @@ button_pressed = function(button)
end
end
if button == game.BUTTON_BTA then
if button == game.BUTTON_FXL then
toggle_hard();
end
if button == game.BUTTON_BTB then
if button == game.BUTTON_FXR then
toggle_mirror();
end
end

File diff suppressed because it is too large Load Diff

View File

@ -525,6 +525,7 @@ function drawData() -- Draws the song data on the left panel
end
---@param diff SongWheelDifficulty
function drawLocalLeaderboard(diff)
gfx.LoadSkinFont('Digital-Serial-Bold.ttf')
gfx.FontSize(26)
@ -550,15 +551,19 @@ function drawLocalLeaderboard(diff)
gfx.Text("LOCAL TOP", sbBarContentRightX, scoreBoardY + sbBarHeight/2)
for i = 1, 5, 1 do
local scoreTable = diff.scores[i]
local username = scoreTable and scoreTable.playerName or game.GetSkinSetting("username") or "Unknown"
local score = scoreTable and scoreTable.score or "- - - - - - - -"
gfx.BeginPath()
gfx.ImageRect(scoreBoardX, scoreBoardY + i*sbBarHeight, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0)
gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE)
gfx.BeginPath()
gfx.Text(game.GetSkinSetting("username"), sbBarContentLeftX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight)
gfx.Text(username, sbBarContentLeftX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight)
gfx.BeginPath()
gfx.Text((diff.scores[i]) and diff.scores[i].score or "- - - - - - - -", sbBarContentRightX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight)
gfx.Text(score, sbBarContentRightX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight)
end
end