diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..2125666 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto \ No newline at end of file diff --git a/.gitignore b/.gitignore index 7e70a9d..8912bcc 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,21 @@ +# IDE files +.vscode + +# secret(?) assets _asset song-assets skin-assets + +# generated skin files nautica.json skin.cfg -.vscode -/textures/crew/ \ No newline at end of file + +# any crew that's not the default one, we do not package crew +textures/crew/* +!textures/crew/appeal_card.png +!textures/crew/frame.png +!textures/crew/portrait.png +!textures/crew/make-a-crew/frame_glow.png +!textures/crew/make-a-crew/frame_metal.png +!textures/crew/make-a-crew/instructions.txt +!textures/crew/anim/nothing \ No newline at end of file diff --git a/README.md b/README.md index 92be837..1550b33 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,14 @@ Project Starter: GSK Bladez ## Coding -- FajsiEx +- [REDACTED] - Hersi +- RealFD - fdigl - Hoshikara - GSK Bladez - Local +- Kuenaimaku ## Graphics - GSK Bladez diff --git a/audio/temp audio folder/Title/3 intro.wav b/audio/temp audio folder/Title/3 intro.wav new file mode 100644 index 0000000..7fb186c Binary files /dev/null and b/audio/temp audio folder/Title/3 intro.wav differ diff --git a/audio/titlescreen/ksm.wav b/audio/titlescreen/ksm.wav new file mode 100644 index 0000000..e57df8b Binary files /dev/null and b/audio/titlescreen/ksm.wav differ diff --git a/audio/titlescreen/splash/splash1.wav b/audio/titlescreen/splash/splash1.wav new file mode 100644 index 0000000..e57df8b Binary files /dev/null and b/audio/titlescreen/splash/splash1.wav differ diff --git a/backgrounds/fallback/bg.lua b/backgrounds/fallback/bg.lua index 038905b..de76dbf 100644 --- a/backgrounds/fallback/bg.lua +++ b/backgrounds/fallback/bg.lua @@ -205,7 +205,7 @@ local bgs = { -- Layer={Tex={"electro1.jpg", "electro1-c.jpg"}, brightenLayer=0.6}, u={Pivot=0.35}} -- }, -- electro2={Bg={Layer={Tex={"electro2.jpg", "electro2-c.jpg"} }, u={Pivot=0.3}}}, - plasmaTunnel={Bg={Layer={Tex={"plasmatunnel.jpg", "plasmatunnel-c.jpg"}, }, u={Pivot=0.37}}, speed=0.75, bright=true}, + -- plasmaTunnel={Bg={Layer={Tex={"plasmatunnel.jpg", "plasmatunnel-c.jpg"}, }, u={Pivot=0.37}}, speed=0.75, bright=true}, -- my eyes are burning -- xcalibur={Bg={Base={Tex={"anim/xcalibur.jpg", "anim/xcalibur-c.jpg"}}, u={Pivot=0.36}}, speed=0.3}, goldleaves={ Bg={Base={Tex={"anim/goldleaves.jpg", "anim/goldleaves-c.jpg"}}}, diff --git a/backgrounds/fallback/textures/background/anim/eye-thomas.jpg b/backgrounds/fallback/textures/background/anim/eye-thomas.jpg index 1000622..a41538f 100644 Binary files a/backgrounds/fallback/textures/background/anim/eye-thomas.jpg and b/backgrounds/fallback/textures/background/anim/eye-thomas.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/goldleaves-c.jpg b/backgrounds/fallback/textures/background/anim/goldleaves-c.jpg index 1d805b7..fa8cf2f 100644 Binary files a/backgrounds/fallback/textures/background/anim/goldleaves-c.jpg and b/backgrounds/fallback/textures/background/anim/goldleaves-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/goldleaves.jpg b/backgrounds/fallback/textures/background/anim/goldleaves.jpg index 5fccbc2..4a37fd3 100644 Binary files a/backgrounds/fallback/textures/background/anim/goldleaves.jpg and b/backgrounds/fallback/textures/background/anim/goldleaves.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/sakura1-c.jpg b/backgrounds/fallback/textures/background/anim/sakura1-c.jpg index 904663f..c878783 100644 Binary files a/backgrounds/fallback/textures/background/anim/sakura1-c.jpg and b/backgrounds/fallback/textures/background/anim/sakura1-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/sakura1.jpg b/backgrounds/fallback/textures/background/anim/sakura1.jpg index d5047ef..f8ad28d 100644 Binary files a/backgrounds/fallback/textures/background/anim/sakura1.jpg and b/backgrounds/fallback/textures/background/anim/sakura1.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/snow-c.jpg b/backgrounds/fallback/textures/background/anim/snow-c.jpg index e053ecf..8ccd829 100644 Binary files a/backgrounds/fallback/textures/background/anim/snow-c.jpg and b/backgrounds/fallback/textures/background/anim/snow-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/snow.jpg b/backgrounds/fallback/textures/background/anim/snow.jpg index 3d14405..9a23a00 100644 Binary files a/backgrounds/fallback/textures/background/anim/snow.jpg and b/backgrounds/fallback/textures/background/anim/snow.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/specific1-c.jpg b/backgrounds/fallback/textures/background/anim/specific1-c.jpg index a2438a0..7d3ca41 100644 Binary files a/backgrounds/fallback/textures/background/anim/specific1-c.jpg and b/backgrounds/fallback/textures/background/anim/specific1-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/specific1.jpg b/backgrounds/fallback/textures/background/anim/specific1.jpg index b6a41a9..e23c02c 100644 Binary files a/backgrounds/fallback/textures/background/anim/specific1.jpg and b/backgrounds/fallback/textures/background/anim/specific1.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/specific12-c.jpg b/backgrounds/fallback/textures/background/anim/specific12-c.jpg index fa8a398..02cd37a 100644 Binary files a/backgrounds/fallback/textures/background/anim/specific12-c.jpg and b/backgrounds/fallback/textures/background/anim/specific12-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/specific12.jpg b/backgrounds/fallback/textures/background/anim/specific12.jpg index 2034619..3d7248b 100644 Binary files a/backgrounds/fallback/textures/background/anim/specific12.jpg and b/backgrounds/fallback/textures/background/anim/specific12.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/specific13-c.jpg b/backgrounds/fallback/textures/background/anim/specific13-c.jpg index 4e73cee..430b878 100644 Binary files a/backgrounds/fallback/textures/background/anim/specific13-c.jpg and b/backgrounds/fallback/textures/background/anim/specific13-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/specific13.jpg b/backgrounds/fallback/textures/background/anim/specific13.jpg index 3ac85e9..510da74 100644 Binary files a/backgrounds/fallback/textures/background/anim/specific13.jpg and b/backgrounds/fallback/textures/background/anim/specific13.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/technocircle-c.jpg b/backgrounds/fallback/textures/background/anim/technocircle-c.jpg index 122e9d5..cac553d 100644 Binary files a/backgrounds/fallback/textures/background/anim/technocircle-c.jpg and b/backgrounds/fallback/textures/background/anim/technocircle-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/technocircle.jpg b/backgrounds/fallback/textures/background/anim/technocircle.jpg index e7fd09c..7e43717 100644 Binary files a/backgrounds/fallback/textures/background/anim/technocircle.jpg and b/backgrounds/fallback/textures/background/anim/technocircle.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/xcalibur-c.jpg b/backgrounds/fallback/textures/background/anim/xcalibur-c.jpg index c3e9037..b6a3e29 100644 Binary files a/backgrounds/fallback/textures/background/anim/xcalibur-c.jpg and b/backgrounds/fallback/textures/background/anim/xcalibur-c.jpg differ diff --git a/backgrounds/fallback/textures/background/anim/xcalibur.jpg b/backgrounds/fallback/textures/background/anim/xcalibur.jpg index 6e198d9..832a326 100644 Binary files a/backgrounds/fallback/textures/background/anim/xcalibur.jpg and b/backgrounds/fallback/textures/background/anim/xcalibur.jpg differ diff --git a/backgrounds/fallback/textures/background/beach.png b/backgrounds/fallback/textures/background/beach.png index b4feb3d..7af0d44 100644 Binary files a/backgrounds/fallback/textures/background/beach.png and b/backgrounds/fallback/textures/background/beach.png differ diff --git a/backgrounds/fallback/textures/background/bedroom-c.jpg b/backgrounds/fallback/textures/background/bedroom-c.jpg index 888ab2d..2dc31ee 100644 Binary files a/backgrounds/fallback/textures/background/bedroom-c.jpg and b/backgrounds/fallback/textures/background/bedroom-c.jpg differ diff --git a/backgrounds/fallback/textures/background/bedroom.jpg b/backgrounds/fallback/textures/background/bedroom.jpg index 5d67282..f4a4708 100644 Binary files a/backgrounds/fallback/textures/background/bedroom.jpg and b/backgrounds/fallback/textures/background/bedroom.jpg differ diff --git a/backgrounds/fallback/textures/background/brown_planet.jpg b/backgrounds/fallback/textures/background/brown_planet.jpg index 3dd9f3c..65f49ff 100644 Binary files a/backgrounds/fallback/textures/background/brown_planet.jpg and b/backgrounds/fallback/textures/background/brown_planet.jpg differ diff --git a/backgrounds/fallback/textures/background/city.png b/backgrounds/fallback/textures/background/city.png index 1e9d0e4..8706882 100644 Binary files a/backgrounds/fallback/textures/background/city.png and b/backgrounds/fallback/textures/background/city.png differ diff --git a/backgrounds/fallback/textures/background/cloudy-c.jpg b/backgrounds/fallback/textures/background/cloudy-c.jpg index 26bf071..ec7bfc1 100644 Binary files a/backgrounds/fallback/textures/background/cloudy-c.jpg and b/backgrounds/fallback/textures/background/cloudy-c.jpg differ diff --git a/backgrounds/fallback/textures/background/cloudy.jpg b/backgrounds/fallback/textures/background/cloudy.jpg index f8c199e..bfd2435 100644 Binary files a/backgrounds/fallback/textures/background/cloudy.jpg and b/backgrounds/fallback/textures/background/cloudy.jpg differ diff --git a/backgrounds/fallback/textures/background/cyber-c.jpg b/backgrounds/fallback/textures/background/cyber-c.jpg index ea386f9..1982883 100644 Binary files a/backgrounds/fallback/textures/background/cyber-c.jpg and b/backgrounds/fallback/textures/background/cyber-c.jpg differ diff --git a/backgrounds/fallback/textures/background/cyber.jpg b/backgrounds/fallback/textures/background/cyber.jpg index 5129ee5..f4c6ab5 100644 Binary files a/backgrounds/fallback/textures/background/cyber.jpg and b/backgrounds/fallback/textures/background/cyber.jpg differ diff --git a/backgrounds/fallback/textures/background/cyberspace-c.jpg b/backgrounds/fallback/textures/background/cyberspace-c.jpg index 7f2db0b..6a7a84e 100644 Binary files a/backgrounds/fallback/textures/background/cyberspace-c.jpg and b/backgrounds/fallback/textures/background/cyberspace-c.jpg differ diff --git a/backgrounds/fallback/textures/background/cyberspace.jpg b/backgrounds/fallback/textures/background/cyberspace.jpg index 84d64e4..663247e 100644 Binary files a/backgrounds/fallback/textures/background/cyberspace.jpg and b/backgrounds/fallback/textures/background/cyberspace.jpg differ diff --git a/backgrounds/fallback/textures/background/cyberspace_night.png b/backgrounds/fallback/textures/background/cyberspace_night.png index 070b39c..6b16b6e 100644 Binary files a/backgrounds/fallback/textures/background/cyberspace_night.png and b/backgrounds/fallback/textures/background/cyberspace_night.png differ diff --git a/backgrounds/fallback/textures/background/cyberspace_night_starburst.png b/backgrounds/fallback/textures/background/cyberspace_night_starburst.png index 61b7b28..9a47550 100644 Binary files a/backgrounds/fallback/textures/background/cyberspace_night_starburst.png and b/backgrounds/fallback/textures/background/cyberspace_night_starburst.png differ diff --git a/backgrounds/fallback/textures/background/cyberspace_sunrise-f.png b/backgrounds/fallback/textures/background/cyberspace_sunrise-f.png index 8f8b36f..3bf08eb 100644 Binary files a/backgrounds/fallback/textures/background/cyberspace_sunrise-f.png and b/backgrounds/fallback/textures/background/cyberspace_sunrise-f.png differ diff --git a/backgrounds/fallback/textures/background/cyberspace_sunrise.png b/backgrounds/fallback/textures/background/cyberspace_sunrise.png index 42e114d..1cbaa67 100644 Binary files a/backgrounds/fallback/textures/background/cyberspace_sunrise.png and b/backgrounds/fallback/textures/background/cyberspace_sunrise.png differ diff --git a/backgrounds/fallback/textures/background/deepsea-c.jpg b/backgrounds/fallback/textures/background/deepsea-c.jpg index 88e1eb2..7a663eb 100644 Binary files a/backgrounds/fallback/textures/background/deepsea-c.jpg and b/backgrounds/fallback/textures/background/deepsea-c.jpg differ diff --git a/backgrounds/fallback/textures/background/deepsea.jpg b/backgrounds/fallback/textures/background/deepsea.jpg index 9351938..fa6ca69 100644 Binary files a/backgrounds/fallback/textures/background/deepsea.jpg and b/backgrounds/fallback/textures/background/deepsea.jpg differ diff --git a/backgrounds/fallback/textures/background/desert-c.jpg b/backgrounds/fallback/textures/background/desert-c.jpg index 8634ba4..9e30a16 100644 Binary files a/backgrounds/fallback/textures/background/desert-c.jpg and b/backgrounds/fallback/textures/background/desert-c.jpg differ diff --git a/backgrounds/fallback/textures/background/desert-c2.jpg b/backgrounds/fallback/textures/background/desert-c2.jpg index 619e193..a8d1571 100644 Binary files a/backgrounds/fallback/textures/background/desert-c2.jpg and b/backgrounds/fallback/textures/background/desert-c2.jpg differ diff --git a/backgrounds/fallback/textures/background/desert.jpg b/backgrounds/fallback/textures/background/desert.jpg index 04d0f0f..73cdb49 100644 Binary files a/backgrounds/fallback/textures/background/desert.jpg and b/backgrounds/fallback/textures/background/desert.jpg differ diff --git a/backgrounds/fallback/textures/background/fantasy-c.jpg b/backgrounds/fallback/textures/background/fantasy-c.jpg index f8ec236..94a0b11 100644 Binary files a/backgrounds/fallback/textures/background/fantasy-c.jpg and b/backgrounds/fallback/textures/background/fantasy-c.jpg differ diff --git a/backgrounds/fallback/textures/background/fantasy.jpg b/backgrounds/fallback/textures/background/fantasy.jpg index 5853650..6751fdf 100644 Binary files a/backgrounds/fallback/textures/background/fantasy.jpg and b/backgrounds/fallback/textures/background/fantasy.jpg differ diff --git a/backgrounds/fallback/textures/background/flame-c.jpg b/backgrounds/fallback/textures/background/flame-c.jpg index ee63b35..431f659 100644 Binary files a/backgrounds/fallback/textures/background/flame-c.jpg and b/backgrounds/fallback/textures/background/flame-c.jpg differ diff --git a/backgrounds/fallback/textures/background/flame.jpg b/backgrounds/fallback/textures/background/flame.jpg index 5242e22..f215ab8 100644 Binary files a/backgrounds/fallback/textures/background/flame.jpg and b/backgrounds/fallback/textures/background/flame.jpg differ diff --git a/backgrounds/fallback/textures/background/galaxy-c.jpg b/backgrounds/fallback/textures/background/galaxy-c.jpg index b86bce1..5757271 100644 Binary files a/backgrounds/fallback/textures/background/galaxy-c.jpg and b/backgrounds/fallback/textures/background/galaxy-c.jpg differ diff --git a/backgrounds/fallback/textures/background/game-f.png b/backgrounds/fallback/textures/background/game-f.png index 8941642..28a3134 100644 Binary files a/backgrounds/fallback/textures/background/game-f.png and b/backgrounds/fallback/textures/background/game-f.png differ diff --git a/backgrounds/fallback/textures/background/grass-c.jpg b/backgrounds/fallback/textures/background/grass-c.jpg index 939c4ba..45daf6e 100644 Binary files a/backgrounds/fallback/textures/background/grass-c.jpg and b/backgrounds/fallback/textures/background/grass-c.jpg differ diff --git a/backgrounds/fallback/textures/background/grass.jpg b/backgrounds/fallback/textures/background/grass.jpg index d89d931..d181264 100644 Binary files a/backgrounds/fallback/textures/background/grass.jpg and b/backgrounds/fallback/textures/background/grass.jpg differ diff --git a/backgrounds/fallback/textures/background/jomanda.png b/backgrounds/fallback/textures/background/jomanda.png index 9ae7adf..9aa3aaf 100644 Binary files a/backgrounds/fallback/textures/background/jomanda.png and b/backgrounds/fallback/textures/background/jomanda.png differ diff --git a/backgrounds/fallback/textures/background/mars-c.jpg b/backgrounds/fallback/textures/background/mars-c.jpg index 42cb365..67fdf97 100644 Binary files a/backgrounds/fallback/textures/background/mars-c.jpg and b/backgrounds/fallback/textures/background/mars-c.jpg differ diff --git a/backgrounds/fallback/textures/background/mars.jpg b/backgrounds/fallback/textures/background/mars.jpg index 91d574d..d671fb6 100644 Binary files a/backgrounds/fallback/textures/background/mars.jpg and b/backgrounds/fallback/textures/background/mars.jpg differ diff --git a/backgrounds/fallback/textures/background/moon_blue-c.jpg b/backgrounds/fallback/textures/background/moon_blue-c.jpg index cda0710..862f7a6 100644 Binary files a/backgrounds/fallback/textures/background/moon_blue-c.jpg and b/backgrounds/fallback/textures/background/moon_blue-c.jpg differ diff --git a/backgrounds/fallback/textures/background/moon_blue.jpg b/backgrounds/fallback/textures/background/moon_blue.jpg index 332a026..53afe74 100644 Binary files a/backgrounds/fallback/textures/background/moon_blue.jpg and b/backgrounds/fallback/textures/background/moon_blue.jpg differ diff --git a/backgrounds/fallback/textures/background/moon_purple-c.jpg b/backgrounds/fallback/textures/background/moon_purple-c.jpg index bffe18b..f0ba815 100644 Binary files a/backgrounds/fallback/textures/background/moon_purple-c.jpg and b/backgrounds/fallback/textures/background/moon_purple-c.jpg differ diff --git a/backgrounds/fallback/textures/background/moon_purple.jpg b/backgrounds/fallback/textures/background/moon_purple.jpg index af4c20b..6334de8 100644 Binary files a/backgrounds/fallback/textures/background/moon_purple.jpg and b/backgrounds/fallback/textures/background/moon_purple.jpg differ diff --git a/backgrounds/fallback/textures/background/night-c.jpg b/backgrounds/fallback/textures/background/night-c.jpg index 3e385b0..2554bed 100644 Binary files a/backgrounds/fallback/textures/background/night-c.jpg and b/backgrounds/fallback/textures/background/night-c.jpg differ diff --git a/backgrounds/fallback/textures/background/night.jpg b/backgrounds/fallback/textures/background/night.jpg index 8778234..d8d3fd3 100644 Binary files a/backgrounds/fallback/textures/background/night.jpg and b/backgrounds/fallback/textures/background/night.jpg differ diff --git a/backgrounds/fallback/textures/background/ocean-c.jpg b/backgrounds/fallback/textures/background/ocean-c.jpg index 1b032f2..bf81458 100644 Binary files a/backgrounds/fallback/textures/background/ocean-c.jpg and b/backgrounds/fallback/textures/background/ocean-c.jpg differ diff --git a/backgrounds/fallback/textures/background/ocean.jpg b/backgrounds/fallback/textures/background/ocean.jpg index 6bb2269..54f1e62 100644 Binary files a/backgrounds/fallback/textures/background/ocean.jpg and b/backgrounds/fallback/textures/background/ocean.jpg differ diff --git a/backgrounds/fallback/textures/background/prettygalaxy-c.jpg b/backgrounds/fallback/textures/background/prettygalaxy-c.jpg index e209bb1..3006056 100644 Binary files a/backgrounds/fallback/textures/background/prettygalaxy-c.jpg and b/backgrounds/fallback/textures/background/prettygalaxy-c.jpg differ diff --git a/backgrounds/fallback/textures/background/prettygalaxy.jpg b/backgrounds/fallback/textures/background/prettygalaxy.jpg index 91afb13..25a3da6 100644 Binary files a/backgrounds/fallback/textures/background/prettygalaxy.jpg and b/backgrounds/fallback/textures/background/prettygalaxy.jpg differ diff --git a/backgrounds/fallback/textures/background/red_dusk-c.jpg b/backgrounds/fallback/textures/background/red_dusk-c.jpg index 76e052a..34099de 100644 Binary files a/backgrounds/fallback/textures/background/red_dusk-c.jpg and b/backgrounds/fallback/textures/background/red_dusk-c.jpg differ diff --git a/backgrounds/fallback/textures/background/red_dusk.jpg b/backgrounds/fallback/textures/background/red_dusk.jpg index ea4e17f..4790166 100644 Binary files a/backgrounds/fallback/textures/background/red_dusk.jpg and b/backgrounds/fallback/textures/background/red_dusk.jpg differ diff --git a/backgrounds/fallback/textures/background/redblur-c.jpg b/backgrounds/fallback/textures/background/redblur-c.jpg index a61db5c..3df54f4 100644 Binary files a/backgrounds/fallback/textures/background/redblur-c.jpg and b/backgrounds/fallback/textures/background/redblur-c.jpg differ diff --git a/backgrounds/fallback/textures/background/redblur.jpg b/backgrounds/fallback/textures/background/redblur.jpg index b9e908e..3bda6e1 100644 Binary files a/backgrounds/fallback/textures/background/redblur.jpg and b/backgrounds/fallback/textures/background/redblur.jpg differ diff --git a/backgrounds/fallback/textures/background/redgradient.jpg b/backgrounds/fallback/textures/background/redgradient.jpg index 7939d75..4bdde1b 100644 Binary files a/backgrounds/fallback/textures/background/redgradient.jpg and b/backgrounds/fallback/textures/background/redgradient.jpg differ diff --git a/backgrounds/fallback/textures/background/sakura-c.jpg b/backgrounds/fallback/textures/background/sakura-c.jpg index 4ce1ec1..ce2efeb 100644 Binary files a/backgrounds/fallback/textures/background/sakura-c.jpg and b/backgrounds/fallback/textures/background/sakura-c.jpg differ diff --git a/backgrounds/fallback/textures/background/sakura.jpg b/backgrounds/fallback/textures/background/sakura.jpg index be9af0f..d3c2db6 100644 Binary files a/backgrounds/fallback/textures/background/sakura.jpg and b/backgrounds/fallback/textures/background/sakura.jpg differ diff --git a/backgrounds/fallback/textures/background/sea-day-f.png b/backgrounds/fallback/textures/background/sea-day-f.png index d468753..38eac66 100644 Binary files a/backgrounds/fallback/textures/background/sea-day-f.png and b/backgrounds/fallback/textures/background/sea-day-f.png differ diff --git a/backgrounds/fallback/textures/background/sea-day.png b/backgrounds/fallback/textures/background/sea-day.png index 28e82f2..454a671 100644 Binary files a/backgrounds/fallback/textures/background/sea-day.png and b/backgrounds/fallback/textures/background/sea-day.png differ diff --git a/backgrounds/fallback/textures/background/sea-ice-f.png b/backgrounds/fallback/textures/background/sea-ice-f.png index 4ac5a17..bdfb803 100644 Binary files a/backgrounds/fallback/textures/background/sea-ice-f.png and b/backgrounds/fallback/textures/background/sea-ice-f.png differ diff --git a/backgrounds/fallback/textures/background/sea-ice.png b/backgrounds/fallback/textures/background/sea-ice.png index 2a97991..4e02263 100644 Binary files a/backgrounds/fallback/textures/background/sea-ice.png and b/backgrounds/fallback/textures/background/sea-ice.png differ diff --git a/backgrounds/fallback/textures/background/sea-night-f.png b/backgrounds/fallback/textures/background/sea-night-f.png index e6adb09..f6c8465 100644 Binary files a/backgrounds/fallback/textures/background/sea-night-f.png and b/backgrounds/fallback/textures/background/sea-night-f.png differ diff --git a/backgrounds/fallback/textures/background/sea-night.png b/backgrounds/fallback/textures/background/sea-night.png index 18838c4..7196a14 100644 Binary files a/backgrounds/fallback/textures/background/sea-night.png and b/backgrounds/fallback/textures/background/sea-night.png differ diff --git a/backgrounds/fallback/textures/background/sea-storm-f.png b/backgrounds/fallback/textures/background/sea-storm-f.png index 5293550..d77d03d 100644 Binary files a/backgrounds/fallback/textures/background/sea-storm-f.png and b/backgrounds/fallback/textures/background/sea-storm-f.png differ diff --git a/backgrounds/fallback/textures/background/sea-storm.png b/backgrounds/fallback/textures/background/sea-storm.png index 26be8cf..086e080 100644 Binary files a/backgrounds/fallback/textures/background/sea-storm.png and b/backgrounds/fallback/textures/background/sea-storm.png differ diff --git a/backgrounds/fallback/textures/background/sea-thunder-f.png b/backgrounds/fallback/textures/background/sea-thunder-f.png index 91026a2..f160e4c 100644 Binary files a/backgrounds/fallback/textures/background/sea-thunder-f.png and b/backgrounds/fallback/textures/background/sea-thunder-f.png differ diff --git a/backgrounds/fallback/textures/background/sea-thunder.png b/backgrounds/fallback/textures/background/sea-thunder.png index a2ee02e..8e4cc7d 100644 Binary files a/backgrounds/fallback/textures/background/sea-thunder.png and b/backgrounds/fallback/textures/background/sea-thunder.png differ diff --git a/backgrounds/fallback/textures/background/sky-c.jpg b/backgrounds/fallback/textures/background/sky-c.jpg index 9b61185..8c22f52 100644 Binary files a/backgrounds/fallback/textures/background/sky-c.jpg and b/backgrounds/fallback/textures/background/sky-c.jpg differ diff --git a/backgrounds/fallback/textures/background/sky-iv-c.jpg b/backgrounds/fallback/textures/background/sky-iv-c.jpg index 4ea0f82..15cf491 100644 Binary files a/backgrounds/fallback/textures/background/sky-iv-c.jpg and b/backgrounds/fallback/textures/background/sky-iv-c.jpg differ diff --git a/backgrounds/fallback/textures/background/sky-iv-dark.jpg b/backgrounds/fallback/textures/background/sky-iv-dark.jpg index 2ded8cc..e15c756 100644 Binary files a/backgrounds/fallback/textures/background/sky-iv-dark.jpg and b/backgrounds/fallback/textures/background/sky-iv-dark.jpg differ diff --git a/backgrounds/fallback/textures/background/sky-iv.jpg b/backgrounds/fallback/textures/background/sky-iv.jpg index 5530115..297b0c8 100644 Binary files a/backgrounds/fallback/textures/background/sky-iv.jpg and b/backgrounds/fallback/textures/background/sky-iv.jpg differ diff --git a/backgrounds/fallback/textures/background/sky.jpg b/backgrounds/fallback/textures/background/sky.jpg index a75f570..3865177 100644 Binary files a/backgrounds/fallback/textures/background/sky.jpg and b/backgrounds/fallback/textures/background/sky.jpg differ diff --git a/backgrounds/fallback/textures/background/sky_iv_2-c.png b/backgrounds/fallback/textures/background/sky_iv_2-c.png index 2166991..c5080ab 100644 Binary files a/backgrounds/fallback/textures/background/sky_iv_2-c.png and b/backgrounds/fallback/textures/background/sky_iv_2-c.png differ diff --git a/backgrounds/fallback/textures/background/sky_iv_2.png b/backgrounds/fallback/textures/background/sky_iv_2.png index e6c6672..6afd759 100644 Binary files a/backgrounds/fallback/textures/background/sky_iv_2.png and b/backgrounds/fallback/textures/background/sky_iv_2.png differ diff --git a/backgrounds/fallback/textures/background/star-c.png b/backgrounds/fallback/textures/background/star-c.png index 212e29c..2979788 100644 Binary files a/backgrounds/fallback/textures/background/star-c.png and b/backgrounds/fallback/textures/background/star-c.png differ diff --git a/backgrounds/fallback/textures/background/star.png b/backgrounds/fallback/textures/background/star.png index 0f988b1..06de084 100644 Binary files a/backgrounds/fallback/textures/background/star.png and b/backgrounds/fallback/textures/background/star.png differ diff --git a/backgrounds/fallback/textures/background/sunset-c.jpg b/backgrounds/fallback/textures/background/sunset-c.jpg index eda49fe..1cb6b07 100644 Binary files a/backgrounds/fallback/textures/background/sunset-c.jpg and b/backgrounds/fallback/textures/background/sunset-c.jpg differ diff --git a/backgrounds/fallback/textures/background/sunset.jpg b/backgrounds/fallback/textures/background/sunset.jpg index 1081fd9..552453f 100644 Binary files a/backgrounds/fallback/textures/background/sunset.jpg and b/backgrounds/fallback/textures/background/sunset.jpg differ diff --git a/backgrounds/fallback/textures/background/twilight-c.png b/backgrounds/fallback/textures/background/twilight-c.png index 9fad729..2ca8220 100644 Binary files a/backgrounds/fallback/textures/background/twilight-c.png and b/backgrounds/fallback/textures/background/twilight-c.png differ diff --git a/backgrounds/fallback/textures/background/twilight.png b/backgrounds/fallback/textures/background/twilight.png index 7c21217..5909b57 100644 Binary files a/backgrounds/fallback/textures/background/twilight.png and b/backgrounds/fallback/textures/background/twilight.png differ diff --git a/backgrounds/fallback/textures/background/undersea-c.png b/backgrounds/fallback/textures/background/undersea-c.png index 79bb58a..a6d9ac2 100644 Binary files a/backgrounds/fallback/textures/background/undersea-c.png and b/backgrounds/fallback/textures/background/undersea-c.png differ diff --git a/backgrounds/fallback/textures/background/undersea.png b/backgrounds/fallback/textures/background/undersea.png index 2bc7c80..011c162 100644 Binary files a/backgrounds/fallback/textures/background/undersea.png and b/backgrounds/fallback/textures/background/undersea.png differ diff --git a/backgrounds/fallback/textures/background/underwater-c.jpg b/backgrounds/fallback/textures/background/underwater-c.jpg index 8e9d1b4..f0bfac1 100644 Binary files a/backgrounds/fallback/textures/background/underwater-c.jpg and b/backgrounds/fallback/textures/background/underwater-c.jpg differ diff --git a/backgrounds/fallback/textures/background/underwater.jpg b/backgrounds/fallback/textures/background/underwater.jpg index 30cf8fc..2703e4b 100644 Binary files a/backgrounds/fallback/textures/background/underwater.jpg and b/backgrounds/fallback/textures/background/underwater.jpg differ diff --git a/backgrounds/fallback/textures/background/watervault-c.jpg b/backgrounds/fallback/textures/background/watervault-c.jpg index c06299b..7ff642e 100644 Binary files a/backgrounds/fallback/textures/background/watervault-c.jpg and b/backgrounds/fallback/textures/background/watervault-c.jpg differ diff --git a/backgrounds/fallback/textures/background/watervault.jpg b/backgrounds/fallback/textures/background/watervault.jpg index dd941cb..9ea3004 100644 Binary files a/backgrounds/fallback/textures/background/watervault.jpg and b/backgrounds/fallback/textures/background/watervault.jpg differ diff --git a/backgrounds/fallback/textures/center/anim/hiyuki.png b/backgrounds/fallback/textures/center/anim/hiyuki.png index 5f74170..54c6818 100644 Binary files a/backgrounds/fallback/textures/center/anim/hiyuki.png and b/backgrounds/fallback/textures/center/anim/hiyuki.png differ diff --git a/backgrounds/fallback/textures/center/chikyu.png b/backgrounds/fallback/textures/center/chikyu.png index b244f4b..925c9db 100644 Binary files a/backgrounds/fallback/textures/center/chikyu.png and b/backgrounds/fallback/textures/center/chikyu.png differ diff --git a/backgrounds/fallback/textures/center/cyberspace_shine.png b/backgrounds/fallback/textures/center/cyberspace_shine.png index 11e1fea..00d8e8d 100644 Binary files a/backgrounds/fallback/textures/center/cyberspace_shine.png and b/backgrounds/fallback/textures/center/cyberspace_shine.png differ diff --git a/backgrounds/fallback/textures/center/glowshine.png b/backgrounds/fallback/textures/center/glowshine.png index 992ed82..704a24d 100644 Binary files a/backgrounds/fallback/textures/center/glowshine.png and b/backgrounds/fallback/textures/center/glowshine.png differ diff --git a/backgrounds/fallback/textures/center/glowshine_cyan.png b/backgrounds/fallback/textures/center/glowshine_cyan.png index 5566c0d..74a7984 100644 Binary files a/backgrounds/fallback/textures/center/glowshine_cyan.png and b/backgrounds/fallback/textures/center/glowshine_cyan.png differ diff --git a/backgrounds/fallback/textures/center/glowshine_green.png b/backgrounds/fallback/textures/center/glowshine_green.png index 21f3ec3..aa0224a 100644 Binary files a/backgrounds/fallback/textures/center/glowshine_green.png and b/backgrounds/fallback/textures/center/glowshine_green.png differ diff --git a/backgrounds/fallback/textures/center/glowshine_orange.png b/backgrounds/fallback/textures/center/glowshine_orange.png index f95c061..a3b7024 100644 Binary files a/backgrounds/fallback/textures/center/glowshine_orange.png and b/backgrounds/fallback/textures/center/glowshine_orange.png differ diff --git a/backgrounds/fallback/textures/center/glowshine_partial.png b/backgrounds/fallback/textures/center/glowshine_partial.png index 447a8a0..cffd1f9 100644 Binary files a/backgrounds/fallback/textures/center/glowshine_partial.png and b/backgrounds/fallback/textures/center/glowshine_partial.png differ diff --git a/backgrounds/fallback/textures/center/glowshine_pink.png b/backgrounds/fallback/textures/center/glowshine_pink.png index 4d31618..5583e3f 100644 Binary files a/backgrounds/fallback/textures/center/glowshine_pink.png and b/backgrounds/fallback/textures/center/glowshine_pink.png differ diff --git a/backgrounds/fallback/textures/center/glowshine_sun.png b/backgrounds/fallback/textures/center/glowshine_sun.png index ba6a139..8a2d721 100644 Binary files a/backgrounds/fallback/textures/center/glowshine_sun.png and b/backgrounds/fallback/textures/center/glowshine_sun.png differ diff --git a/backgrounds/fallback/textures/center/kac-hikari-2.png b/backgrounds/fallback/textures/center/kac-hikari-2.png index 814cd46..6bdcfe4 100644 Binary files a/backgrounds/fallback/textures/center/kac-hikari-2.png and b/backgrounds/fallback/textures/center/kac-hikari-2.png differ diff --git a/backgrounds/fallback/textures/center/kac-hikari.png b/backgrounds/fallback/textures/center/kac-hikari.png index 321960b..a8f15cf 100644 Binary files a/backgrounds/fallback/textures/center/kac-hikari.png and b/backgrounds/fallback/textures/center/kac-hikari.png differ diff --git a/backgrounds/fallback/textures/center/kac_hikari_3.png b/backgrounds/fallback/textures/center/kac_hikari_3.png index b887c5f..aa87257 100644 Binary files a/backgrounds/fallback/textures/center/kac_hikari_3.png and b/backgrounds/fallback/textures/center/kac_hikari_3.png differ diff --git a/backgrounds/fallback/textures/center/kac_hikari_cyan.png b/backgrounds/fallback/textures/center/kac_hikari_cyan.png index 3589e9f..49f3917 100644 Binary files a/backgrounds/fallback/textures/center/kac_hikari_cyan.png and b/backgrounds/fallback/textures/center/kac_hikari_cyan.png differ diff --git a/backgrounds/fallback/textures/center/kac_hikari_iseki.png b/backgrounds/fallback/textures/center/kac_hikari_iseki.png index 01f7fb2..fba46fd 100644 Binary files a/backgrounds/fallback/textures/center/kac_hikari_iseki.png and b/backgrounds/fallback/textures/center/kac_hikari_iseki.png differ diff --git a/backgrounds/fallback/textures/center/kac_hikari_pink.png b/backgrounds/fallback/textures/center/kac_hikari_pink.png index 227eb59..9e13e80 100644 Binary files a/backgrounds/fallback/textures/center/kac_hikari_pink.png and b/backgrounds/fallback/textures/center/kac_hikari_pink.png differ diff --git a/backgrounds/fallback/textures/center/kac_hikari_sakura.png b/backgrounds/fallback/textures/center/kac_hikari_sakura.png index 29fd64d..4050953 100644 Binary files a/backgrounds/fallback/textures/center/kac_hikari_sakura.png and b/backgrounds/fallback/textures/center/kac_hikari_sakura.png differ diff --git a/backgrounds/fallback/textures/center/kac_maxima_gold.png b/backgrounds/fallback/textures/center/kac_maxima_gold.png index 0e7199d..47feea5 100644 Binary files a/backgrounds/fallback/textures/center/kac_maxima_gold.png and b/backgrounds/fallback/textures/center/kac_maxima_gold.png differ diff --git a/backgrounds/fallback/textures/center/kirari.png b/backgrounds/fallback/textures/center/kirari.png index 105dc34..90053af 100644 Binary files a/backgrounds/fallback/textures/center/kirari.png and b/backgrounds/fallback/textures/center/kirari.png differ diff --git a/backgrounds/fallback/textures/center/kouhai_i_eab.png b/backgrounds/fallback/textures/center/kouhai_i_eab.png index 8cb6826..b859445 100644 Binary files a/backgrounds/fallback/textures/center/kouhai_i_eab.png and b/backgrounds/fallback/textures/center/kouhai_i_eab.png differ diff --git a/backgrounds/fallback/textures/center/logo-c.png b/backgrounds/fallback/textures/center/logo-c.png index 37011fe..1c4fcef 100644 Binary files a/backgrounds/fallback/textures/center/logo-c.png and b/backgrounds/fallback/textures/center/logo-c.png differ diff --git a/backgrounds/fallback/textures/center/logo.png b/backgrounds/fallback/textures/center/logo.png index fee6dd3..64bbc5c 100644 Binary files a/backgrounds/fallback/textures/center/logo.png and b/backgrounds/fallback/textures/center/logo.png differ diff --git a/backgrounds/fallback/textures/center/magic_circle-c.png b/backgrounds/fallback/textures/center/magic_circle-c.png index 096bc3e..34bd1c9 100644 Binary files a/backgrounds/fallback/textures/center/magic_circle-c.png and b/backgrounds/fallback/textures/center/magic_circle-c.png differ diff --git a/backgrounds/fallback/textures/center/maid.png b/backgrounds/fallback/textures/center/maid.png index c30cb84..5c6cabe 100644 Binary files a/backgrounds/fallback/textures/center/maid.png and b/backgrounds/fallback/textures/center/maid.png differ diff --git a/backgrounds/fallback/textures/center/maxma.png b/backgrounds/fallback/textures/center/maxma.png index 45f8068..a35932a 100644 Binary files a/backgrounds/fallback/textures/center/maxma.png and b/backgrounds/fallback/textures/center/maxma.png differ diff --git a/backgrounds/fallback/textures/center/moon1.png b/backgrounds/fallback/textures/center/moon1.png index b648d04..75543b7 100644 Binary files a/backgrounds/fallback/textures/center/moon1.png and b/backgrounds/fallback/textures/center/moon1.png differ diff --git a/backgrounds/fallback/textures/center/moon2-c.png b/backgrounds/fallback/textures/center/moon2-c.png index 98058c3..de0375d 100644 Binary files a/backgrounds/fallback/textures/center/moon2-c.png and b/backgrounds/fallback/textures/center/moon2-c.png differ diff --git a/backgrounds/fallback/textures/center/moon2.png b/backgrounds/fallback/textures/center/moon2.png index 50b9c9a..a10c0a4 100644 Binary files a/backgrounds/fallback/textures/center/moon2.png and b/backgrounds/fallback/textures/center/moon2.png differ diff --git a/backgrounds/fallback/textures/center/moon2_shine.png b/backgrounds/fallback/textures/center/moon2_shine.png index 8367e24..5ecced8 100644 Binary files a/backgrounds/fallback/textures/center/moon2_shine.png and b/backgrounds/fallback/textures/center/moon2_shine.png differ diff --git a/backgrounds/fallback/textures/center/moon_orange-c.png b/backgrounds/fallback/textures/center/moon_orange-c.png index ffea28f..83e7615 100644 Binary files a/backgrounds/fallback/textures/center/moon_orange-c.png and b/backgrounds/fallback/textures/center/moon_orange-c.png differ diff --git a/backgrounds/fallback/textures/center/moon_orange.png b/backgrounds/fallback/textures/center/moon_orange.png index 712a7f4..9e353c6 100644 Binary files a/backgrounds/fallback/textures/center/moon_orange.png and b/backgrounds/fallback/textures/center/moon_orange.png differ diff --git a/backgrounds/fallback/textures/center/moon_orange_shine.png b/backgrounds/fallback/textures/center/moon_orange_shine.png index 2df0eca..492890f 100644 Binary files a/backgrounds/fallback/textures/center/moon_orange_shine.png and b/backgrounds/fallback/textures/center/moon_orange_shine.png differ diff --git a/backgrounds/fallback/textures/center/moon_pink-c.png b/backgrounds/fallback/textures/center/moon_pink-c.png index d1626fe..f02fa38 100644 Binary files a/backgrounds/fallback/textures/center/moon_pink-c.png and b/backgrounds/fallback/textures/center/moon_pink-c.png differ diff --git a/backgrounds/fallback/textures/center/moon_pink.png b/backgrounds/fallback/textures/center/moon_pink.png index 2fe338c..648a272 100644 Binary files a/backgrounds/fallback/textures/center/moon_pink.png and b/backgrounds/fallback/textures/center/moon_pink.png differ diff --git a/backgrounds/fallback/textures/center/moon_pink_shine.png b/backgrounds/fallback/textures/center/moon_pink_shine.png index 1391247..cfe72a4 100644 Binary files a/backgrounds/fallback/textures/center/moon_pink_shine.png and b/backgrounds/fallback/textures/center/moon_pink_shine.png differ diff --git a/backgrounds/fallback/textures/center/moon_pink_shine2.png b/backgrounds/fallback/textures/center/moon_pink_shine2.png index fd9c1b4..c85433f 100644 Binary files a/backgrounds/fallback/textures/center/moon_pink_shine2.png and b/backgrounds/fallback/textures/center/moon_pink_shine2.png differ diff --git a/backgrounds/fallback/textures/center/moon_twilight.png b/backgrounds/fallback/textures/center/moon_twilight.png index a478223..957fdf0 100644 Binary files a/backgrounds/fallback/textures/center/moon_twilight.png and b/backgrounds/fallback/textures/center/moon_twilight.png differ diff --git a/backgrounds/fallback/textures/center/moon_twilight_shine.png b/backgrounds/fallback/textures/center/moon_twilight_shine.png index bc067cc..f106df6 100644 Binary files a/backgrounds/fallback/textures/center/moon_twilight_shine.png and b/backgrounds/fallback/textures/center/moon_twilight_shine.png differ diff --git a/backgrounds/fallback/textures/center/rainbow.png b/backgrounds/fallback/textures/center/rainbow.png index d019d8f..9b8bfa9 100644 Binary files a/backgrounds/fallback/textures/center/rainbow.png and b/backgrounds/fallback/textures/center/rainbow.png differ diff --git a/backgrounds/fallback/textures/center/rainbow2.png b/backgrounds/fallback/textures/center/rainbow2.png index 2239c55..af66894 100644 Binary files a/backgrounds/fallback/textures/center/rainbow2.png and b/backgrounds/fallback/textures/center/rainbow2.png differ diff --git a/backgrounds/fallback/textures/center/sdvx_iv.png b/backgrounds/fallback/textures/center/sdvx_iv.png index 07a7b7e..084afbb 100644 Binary files a/backgrounds/fallback/textures/center/sdvx_iv.png and b/backgrounds/fallback/textures/center/sdvx_iv.png differ diff --git a/backgrounds/fallback/textures/center/shinwa.png b/backgrounds/fallback/textures/center/shinwa.png index 61d0a00..7e18acc 100644 Binary files a/backgrounds/fallback/textures/center/shinwa.png and b/backgrounds/fallback/textures/center/shinwa.png differ diff --git a/backgrounds/fallback/textures/center/ship-day.png b/backgrounds/fallback/textures/center/ship-day.png index 4cb814f..04d0da6 100644 Binary files a/backgrounds/fallback/textures/center/ship-day.png and b/backgrounds/fallback/textures/center/ship-day.png differ diff --git a/backgrounds/fallback/textures/center/ship-ice.png b/backgrounds/fallback/textures/center/ship-ice.png index dd308d3..be652d1 100644 Binary files a/backgrounds/fallback/textures/center/ship-ice.png and b/backgrounds/fallback/textures/center/ship-ice.png differ diff --git a/backgrounds/fallback/textures/center/ship-night.png b/backgrounds/fallback/textures/center/ship-night.png index 9eaa21d..3450c7c 100644 Binary files a/backgrounds/fallback/textures/center/ship-night.png and b/backgrounds/fallback/textures/center/ship-night.png differ diff --git a/backgrounds/fallback/textures/center/ship-storm.png b/backgrounds/fallback/textures/center/ship-storm.png index 337e941..88c3bc9 100644 Binary files a/backgrounds/fallback/textures/center/ship-storm.png and b/backgrounds/fallback/textures/center/ship-storm.png differ diff --git a/backgrounds/fallback/textures/center/sonar.png b/backgrounds/fallback/textures/center/sonar.png index c13761d..ae4e633 100644 Binary files a/backgrounds/fallback/textures/center/sonar.png and b/backgrounds/fallback/textures/center/sonar.png differ diff --git a/backgrounds/fallback/textures/center/star_core.png b/backgrounds/fallback/textures/center/star_core.png index 8e59653..769b8a6 100644 Binary files a/backgrounds/fallback/textures/center/star_core.png and b/backgrounds/fallback/textures/center/star_core.png differ diff --git a/backgrounds/fallback/textures/center/tama_01.png b/backgrounds/fallback/textures/center/tama_01.png index 877e724..edb69b7 100644 Binary files a/backgrounds/fallback/textures/center/tama_01.png and b/backgrounds/fallback/textures/center/tama_01.png differ diff --git a/backgrounds/fallback/textures/center/techno-eye.png b/backgrounds/fallback/textures/center/techno-eye.png index 0618f72..ba167a3 100644 Binary files a/backgrounds/fallback/textures/center/techno-eye.png and b/backgrounds/fallback/textures/center/techno-eye.png differ diff --git a/backgrounds/fallback/textures/center/wolfgirl.png b/backgrounds/fallback/textures/center/wolfgirl.png index ef25361..2cf55e6 100644 Binary files a/backgrounds/fallback/textures/center/wolfgirl.png and b/backgrounds/fallback/textures/center/wolfgirl.png differ diff --git a/backgrounds/fallback/textures/layer/colorbokeh-c.jpg b/backgrounds/fallback/textures/layer/colorbokeh-c.jpg index 9a2969b..cf1fd30 100644 Binary files a/backgrounds/fallback/textures/layer/colorbokeh-c.jpg and b/backgrounds/fallback/textures/layer/colorbokeh-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/colorbokeh.jpg b/backgrounds/fallback/textures/layer/colorbokeh.jpg index c4b35b3..8f76b1b 100644 Binary files a/backgrounds/fallback/textures/layer/colorbokeh.jpg and b/backgrounds/fallback/textures/layer/colorbokeh.jpg differ diff --git a/backgrounds/fallback/textures/layer/electro1-c.jpg b/backgrounds/fallback/textures/layer/electro1-c.jpg index 55bde0e..064d700 100644 Binary files a/backgrounds/fallback/textures/layer/electro1-c.jpg and b/backgrounds/fallback/textures/layer/electro1-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/electro1.jpg b/backgrounds/fallback/textures/layer/electro1.jpg index ea2d325..f89704d 100644 Binary files a/backgrounds/fallback/textures/layer/electro1.jpg and b/backgrounds/fallback/textures/layer/electro1.jpg differ diff --git a/backgrounds/fallback/textures/layer/electro2-c.jpg b/backgrounds/fallback/textures/layer/electro2-c.jpg index 311f8bc..95b7f09 100644 Binary files a/backgrounds/fallback/textures/layer/electro2-c.jpg and b/backgrounds/fallback/textures/layer/electro2-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/electro2.jpg b/backgrounds/fallback/textures/layer/electro2.jpg index 4aec9e5..09adb4a 100644 Binary files a/backgrounds/fallback/textures/layer/electro2.jpg and b/backgrounds/fallback/textures/layer/electro2.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon-inverse-c.jpg b/backgrounds/fallback/textures/layer/moon-inverse-c.jpg index 3cf34ac..b526cc3 100644 Binary files a/backgrounds/fallback/textures/layer/moon-inverse-c.jpg and b/backgrounds/fallback/textures/layer/moon-inverse-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon-inverse.jpg b/backgrounds/fallback/textures/layer/moon-inverse.jpg index f19691f..867032b 100644 Binary files a/backgrounds/fallback/textures/layer/moon-inverse.jpg and b/backgrounds/fallback/textures/layer/moon-inverse.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon1-c.jpg b/backgrounds/fallback/textures/layer/moon1-c.jpg index e600567..5cb2eb8 100644 Binary files a/backgrounds/fallback/textures/layer/moon1-c.jpg and b/backgrounds/fallback/textures/layer/moon1-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon1.jpg b/backgrounds/fallback/textures/layer/moon1.jpg index d61799f..f40de48 100644 Binary files a/backgrounds/fallback/textures/layer/moon1.jpg and b/backgrounds/fallback/textures/layer/moon1.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon2-c.jpg b/backgrounds/fallback/textures/layer/moon2-c.jpg index 7c63513..35b3341 100644 Binary files a/backgrounds/fallback/textures/layer/moon2-c.jpg and b/backgrounds/fallback/textures/layer/moon2-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon2.jpg b/backgrounds/fallback/textures/layer/moon2.jpg index 395991a..342d4ce 100644 Binary files a/backgrounds/fallback/textures/layer/moon2.jpg and b/backgrounds/fallback/textures/layer/moon2.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon3-c.jpg b/backgrounds/fallback/textures/layer/moon3-c.jpg index 9f4e7e6..08c49f3 100644 Binary files a/backgrounds/fallback/textures/layer/moon3-c.jpg and b/backgrounds/fallback/textures/layer/moon3-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon3.jpg b/backgrounds/fallback/textures/layer/moon3.jpg index e973092..fe76349 100644 Binary files a/backgrounds/fallback/textures/layer/moon3.jpg and b/backgrounds/fallback/textures/layer/moon3.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon5-c.jpg b/backgrounds/fallback/textures/layer/moon5-c.jpg index 9757e66..b7a4568 100644 Binary files a/backgrounds/fallback/textures/layer/moon5-c.jpg and b/backgrounds/fallback/textures/layer/moon5-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/moon5.jpg b/backgrounds/fallback/textures/layer/moon5.jpg index 3e6f7f7..9f7f943 100644 Binary files a/backgrounds/fallback/textures/layer/moon5.jpg and b/backgrounds/fallback/textures/layer/moon5.jpg differ diff --git a/backgrounds/fallback/textures/layer/particles5-c.jpg b/backgrounds/fallback/textures/layer/particles5-c.jpg index 6efcb70..9f6320b 100644 Binary files a/backgrounds/fallback/textures/layer/particles5-c.jpg and b/backgrounds/fallback/textures/layer/particles5-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/particles5.jpg b/backgrounds/fallback/textures/layer/particles5.jpg index b812ae8..ed2fd52 100644 Binary files a/backgrounds/fallback/textures/layer/particles5.jpg and b/backgrounds/fallback/textures/layer/particles5.jpg differ diff --git a/backgrounds/fallback/textures/layer/plasmatunnel-c.jpg b/backgrounds/fallback/textures/layer/plasmatunnel-c.jpg index cfcdc36..da1078a 100644 Binary files a/backgrounds/fallback/textures/layer/plasmatunnel-c.jpg and b/backgrounds/fallback/textures/layer/plasmatunnel-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/plasmatunnel.jpg b/backgrounds/fallback/textures/layer/plasmatunnel.jpg index a79f259..534951b 100644 Binary files a/backgrounds/fallback/textures/layer/plasmatunnel.jpg and b/backgrounds/fallback/textures/layer/plasmatunnel.jpg differ diff --git a/backgrounds/fallback/textures/layer/smoke-c.jpg b/backgrounds/fallback/textures/layer/smoke-c.jpg index cfa420b..097f16d 100644 Binary files a/backgrounds/fallback/textures/layer/smoke-c.jpg and b/backgrounds/fallback/textures/layer/smoke-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/smoke.jpg b/backgrounds/fallback/textures/layer/smoke.jpg index 9275378..6dd4cdc 100644 Binary files a/backgrounds/fallback/textures/layer/smoke.jpg and b/backgrounds/fallback/textures/layer/smoke.jpg differ diff --git a/backgrounds/fallback/textures/layer/spider1-c.jpg b/backgrounds/fallback/textures/layer/spider1-c.jpg index bea4518..1b3617a 100644 Binary files a/backgrounds/fallback/textures/layer/spider1-c.jpg and b/backgrounds/fallback/textures/layer/spider1-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/spider1.jpg b/backgrounds/fallback/textures/layer/spider1.jpg index a032df2..af4c2e2 100644 Binary files a/backgrounds/fallback/textures/layer/spider1.jpg and b/backgrounds/fallback/textures/layer/spider1.jpg differ diff --git a/backgrounds/fallback/textures/layer/spider2-c.jpg b/backgrounds/fallback/textures/layer/spider2-c.jpg index 58398b1..f8b6413 100644 Binary files a/backgrounds/fallback/textures/layer/spider2-c.jpg and b/backgrounds/fallback/textures/layer/spider2-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/spider2.jpg b/backgrounds/fallback/textures/layer/spider2.jpg index 6794623..86f23a7 100644 Binary files a/backgrounds/fallback/textures/layer/spider2.jpg and b/backgrounds/fallback/textures/layer/spider2.jpg differ diff --git a/backgrounds/fallback/textures/layer/spider3-c.jpg b/backgrounds/fallback/textures/layer/spider3-c.jpg index 85e6354..8d9d4ec 100644 Binary files a/backgrounds/fallback/textures/layer/spider3-c.jpg and b/backgrounds/fallback/textures/layer/spider3-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/spider3.jpg b/backgrounds/fallback/textures/layer/spider3.jpg index 9e80c57..14b85b0 100644 Binary files a/backgrounds/fallback/textures/layer/spider3.jpg and b/backgrounds/fallback/textures/layer/spider3.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave2-c.jpg b/backgrounds/fallback/textures/layer/wave2-c.jpg index 1bbee96..9a9b23f 100644 Binary files a/backgrounds/fallback/textures/layer/wave2-c.jpg and b/backgrounds/fallback/textures/layer/wave2-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave2.jpg b/backgrounds/fallback/textures/layer/wave2.jpg index ba5cb09..8d5cd16 100644 Binary files a/backgrounds/fallback/textures/layer/wave2.jpg and b/backgrounds/fallback/textures/layer/wave2.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave3-c.jpg b/backgrounds/fallback/textures/layer/wave3-c.jpg index e64e86f..bb64a2c 100644 Binary files a/backgrounds/fallback/textures/layer/wave3-c.jpg and b/backgrounds/fallback/textures/layer/wave3-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave3.jpg b/backgrounds/fallback/textures/layer/wave3.jpg index b11a017..ec1153f 100644 Binary files a/backgrounds/fallback/textures/layer/wave3.jpg and b/backgrounds/fallback/textures/layer/wave3.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave4-c.jpg b/backgrounds/fallback/textures/layer/wave4-c.jpg index 383e85d..385f8f6 100644 Binary files a/backgrounds/fallback/textures/layer/wave4-c.jpg and b/backgrounds/fallback/textures/layer/wave4-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave4.jpg b/backgrounds/fallback/textures/layer/wave4.jpg index 99675ed..c17ced6 100644 Binary files a/backgrounds/fallback/textures/layer/wave4.jpg and b/backgrounds/fallback/textures/layer/wave4.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave6-c.jpg b/backgrounds/fallback/textures/layer/wave6-c.jpg index c596fb8..aa136d8 100644 Binary files a/backgrounds/fallback/textures/layer/wave6-c.jpg and b/backgrounds/fallback/textures/layer/wave6-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave6.jpg b/backgrounds/fallback/textures/layer/wave6.jpg index ce41c8a..7ed12c6 100644 Binary files a/backgrounds/fallback/textures/layer/wave6.jpg and b/backgrounds/fallback/textures/layer/wave6.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave7-c.jpg b/backgrounds/fallback/textures/layer/wave7-c.jpg index 2675dc5..ba857c9 100644 Binary files a/backgrounds/fallback/textures/layer/wave7-c.jpg and b/backgrounds/fallback/textures/layer/wave7-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave7.jpg b/backgrounds/fallback/textures/layer/wave7.jpg index 6950c09..ba73f5d 100644 Binary files a/backgrounds/fallback/textures/layer/wave7.jpg and b/backgrounds/fallback/textures/layer/wave7.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave8-c.jpg b/backgrounds/fallback/textures/layer/wave8-c.jpg index e4fcb63..2a6dedb 100644 Binary files a/backgrounds/fallback/textures/layer/wave8-c.jpg and b/backgrounds/fallback/textures/layer/wave8-c.jpg differ diff --git a/backgrounds/fallback/textures/layer/wave8.jpg b/backgrounds/fallback/textures/layer/wave8.jpg index dd4a19e..6e709d1 100644 Binary files a/backgrounds/fallback/textures/layer/wave8.jpg and b/backgrounds/fallback/textures/layer/wave8.jpg differ diff --git a/backgrounds/fallback/textures/luaparticle/4_eff_dot_bl.png b/backgrounds/fallback/textures/luaparticle/4_eff_dot_bl.png index ce3f268..6c3e966 100644 Binary files a/backgrounds/fallback/textures/luaparticle/4_eff_dot_bl.png and b/backgrounds/fallback/textures/luaparticle/4_eff_dot_bl.png differ diff --git a/backgrounds/fallback/textures/luaparticle/4_logo_01c_i_eab.png b/backgrounds/fallback/textures/luaparticle/4_logo_01c_i_eab.png index b184f01..8b2f6fb 100644 Binary files a/backgrounds/fallback/textures/luaparticle/4_logo_01c_i_eab.png and b/backgrounds/fallback/textures/luaparticle/4_logo_01c_i_eab.png differ diff --git a/backgrounds/fallback/textures/luaparticle/petal1.png b/backgrounds/fallback/textures/luaparticle/petal1.png index 20f2d5d..f0093d0 100644 Binary files a/backgrounds/fallback/textures/luaparticle/petal1.png and b/backgrounds/fallback/textures/luaparticle/petal1.png differ diff --git a/backgrounds/fallback/textures/luaparticle/petal2.png b/backgrounds/fallback/textures/luaparticle/petal2.png index a07cc64..ec57cc2 100644 Binary files a/backgrounds/fallback/textures/luaparticle/petal2.png and b/backgrounds/fallback/textures/luaparticle/petal2.png differ diff --git a/backgrounds/fallback/textures/luaparticle/petal3.png b/backgrounds/fallback/textures/luaparticle/petal3.png index 9445f88..bcea16e 100644 Binary files a/backgrounds/fallback/textures/luaparticle/petal3.png and b/backgrounds/fallback/textures/luaparticle/petal3.png differ diff --git a/backgrounds/fallback/textures/luaparticle/star-particle.png b/backgrounds/fallback/textures/luaparticle/star-particle.png index c681339..74d8981 100644 Binary files a/backgrounds/fallback/textures/luaparticle/star-particle.png and b/backgrounds/fallback/textures/luaparticle/star-particle.png differ diff --git a/backgrounds/fallback/textures/particle/bullets.png b/backgrounds/fallback/textures/particle/bullets.png index 756df5d..0babf40 100644 Binary files a/backgrounds/fallback/textures/particle/bullets.png and b/backgrounds/fallback/textures/particle/bullets.png differ diff --git a/backgrounds/fallback/textures/particle/extra/dangan.png b/backgrounds/fallback/textures/particle/extra/dangan.png index 438248e..024c351 100644 Binary files a/backgrounds/fallback/textures/particle/extra/dangan.png and b/backgrounds/fallback/textures/particle/extra/dangan.png differ diff --git a/backgrounds/fallback/textures/particle/extra/particle_dangan_01.png b/backgrounds/fallback/textures/particle/extra/particle_dangan_01.png index 353acfe..e2db64c 100644 Binary files a/backgrounds/fallback/textures/particle/extra/particle_dangan_01.png and b/backgrounds/fallback/textures/particle/extra/particle_dangan_01.png differ diff --git a/backgrounds/fallback/textures/particle/extra/particle_dangan_02.png b/backgrounds/fallback/textures/particle/extra/particle_dangan_02.png index b1710db..99804a6 100644 Binary files a/backgrounds/fallback/textures/particle/extra/particle_dangan_02.png and b/backgrounds/fallback/textures/particle/extra/particle_dangan_02.png differ diff --git a/backgrounds/fallback/textures/particle/extra/particle_ora_01.png b/backgrounds/fallback/textures/particle/extra/particle_ora_01.png index 395fe82..585c7d3 100644 Binary files a/backgrounds/fallback/textures/particle/extra/particle_ora_01.png and b/backgrounds/fallback/textures/particle/extra/particle_ora_01.png differ diff --git a/backgrounds/fallback/textures/particle/extra/puchun_01_i_eab.png b/backgrounds/fallback/textures/particle/extra/puchun_01_i_eab.png index 258db85..e59fab7 100644 Binary files a/backgrounds/fallback/textures/particle/extra/puchun_01_i_eab.png and b/backgrounds/fallback/textures/particle/extra/puchun_01_i_eab.png differ diff --git a/backgrounds/fallback/textures/particle/extra/puchun_02_i_eab.png b/backgrounds/fallback/textures/particle/extra/puchun_02_i_eab.png index e8b5355..84e32c0 100644 Binary files a/backgrounds/fallback/textures/particle/extra/puchun_02_i_eab.png and b/backgrounds/fallback/textures/particle/extra/puchun_02_i_eab.png differ diff --git a/backgrounds/fallback/textures/particle/feathers.png b/backgrounds/fallback/textures/particle/feathers.png index a279e66..ede18f8 100644 Binary files a/backgrounds/fallback/textures/particle/feathers.png and b/backgrounds/fallback/textures/particle/feathers.png differ diff --git a/backgrounds/fallback/textures/particle/hexes.png b/backgrounds/fallback/textures/particle/hexes.png index 1032eed..36b4317 100644 Binary files a/backgrounds/fallback/textures/particle/hexes.png and b/backgrounds/fallback/textures/particle/hexes.png differ diff --git a/backgrounds/fallback/textures/particle/ice.png b/backgrounds/fallback/textures/particle/ice.png index b9d3a86..3b25651 100644 Binary files a/backgrounds/fallback/textures/particle/ice.png and b/backgrounds/fallback/textures/particle/ice.png differ diff --git a/backgrounds/fallback/textures/particle/icons-c.png b/backgrounds/fallback/textures/particle/icons-c.png index 0a34e9c..a4d6da5 100644 Binary files a/backgrounds/fallback/textures/particle/icons-c.png and b/backgrounds/fallback/textures/particle/icons-c.png differ diff --git a/backgrounds/fallback/textures/particle/icons.png b/backgrounds/fallback/textures/particle/icons.png index 0a4e748..d598a44 100644 Binary files a/backgrounds/fallback/textures/particle/icons.png and b/backgrounds/fallback/textures/particle/icons.png differ diff --git a/backgrounds/fallback/textures/particle/lights_default-c.png b/backgrounds/fallback/textures/particle/lights_default-c.png index 4ce401d..1b01c86 100644 Binary files a/backgrounds/fallback/textures/particle/lights_default-c.png and b/backgrounds/fallback/textures/particle/lights_default-c.png differ diff --git a/backgrounds/fallback/textures/particle/lights_default.png b/backgrounds/fallback/textures/particle/lights_default.png index 0d2c984..dba5fd1 100644 Binary files a/backgrounds/fallback/textures/particle/lights_default.png and b/backgrounds/fallback/textures/particle/lights_default.png differ diff --git a/backgrounds/fallback/textures/particle/lights_moonblue-c.png b/backgrounds/fallback/textures/particle/lights_moonblue-c.png index ee084c4..0cdc4b4 100644 Binary files a/backgrounds/fallback/textures/particle/lights_moonblue-c.png and b/backgrounds/fallback/textures/particle/lights_moonblue-c.png differ diff --git a/backgrounds/fallback/textures/particle/lights_moonblue.png b/backgrounds/fallback/textures/particle/lights_moonblue.png index 22a677c..f0b876a 100644 Binary files a/backgrounds/fallback/textures/particle/lights_moonblue.png and b/backgrounds/fallback/textures/particle/lights_moonblue.png differ diff --git a/backgrounds/fallback/textures/particle/lights_orangepink.png b/backgrounds/fallback/textures/particle/lights_orangepink.png index d30fec5..da2ade5 100644 Binary files a/backgrounds/fallback/textures/particle/lights_orangepink.png and b/backgrounds/fallback/textures/particle/lights_orangepink.png differ diff --git a/backgrounds/fallback/textures/particle/lights_pink-c.png b/backgrounds/fallback/textures/particle/lights_pink-c.png index 86562d0..5ea3ba5 100644 Binary files a/backgrounds/fallback/textures/particle/lights_pink-c.png and b/backgrounds/fallback/textures/particle/lights_pink-c.png differ diff --git a/backgrounds/fallback/textures/particle/lights_pink.png b/backgrounds/fallback/textures/particle/lights_pink.png index 359f2ee..6ca2889 100644 Binary files a/backgrounds/fallback/textures/particle/lights_pink.png and b/backgrounds/fallback/textures/particle/lights_pink.png differ diff --git a/backgrounds/fallback/textures/particle/lights_purplish.png b/backgrounds/fallback/textures/particle/lights_purplish.png index 78113fc..40bca65 100644 Binary files a/backgrounds/fallback/textures/particle/lights_purplish.png and b/backgrounds/fallback/textures/particle/lights_purplish.png differ diff --git a/backgrounds/fallback/textures/particle/lights_sea-c.png b/backgrounds/fallback/textures/particle/lights_sea-c.png index 528c2ec..f703dcb 100644 Binary files a/backgrounds/fallback/textures/particle/lights_sea-c.png and b/backgrounds/fallback/textures/particle/lights_sea-c.png differ diff --git a/backgrounds/fallback/textures/particle/lights_sea.png b/backgrounds/fallback/textures/particle/lights_sea.png index 459429d..7af28a1 100644 Binary files a/backgrounds/fallback/textures/particle/lights_sea.png and b/backgrounds/fallback/textures/particle/lights_sea.png differ diff --git a/backgrounds/fallback/textures/particle/lights_yellow.png b/backgrounds/fallback/textures/particle/lights_yellow.png index cc2e239..8eea253 100644 Binary files a/backgrounds/fallback/textures/particle/lights_yellow.png and b/backgrounds/fallback/textures/particle/lights_yellow.png differ diff --git a/backgrounds/fallback/textures/particle/lights_yellowgreen.png b/backgrounds/fallback/textures/particle/lights_yellowgreen.png index 6e4cd6a..4805b19 100644 Binary files a/backgrounds/fallback/textures/particle/lights_yellowgreen.png and b/backgrounds/fallback/textures/particle/lights_yellowgreen.png differ diff --git a/backgrounds/fallback/textures/particle/shines1.png b/backgrounds/fallback/textures/particle/shines1.png index 2b6359c..9362a68 100644 Binary files a/backgrounds/fallback/textures/particle/shines1.png and b/backgrounds/fallback/textures/particle/shines1.png differ diff --git a/backgrounds/fallback/textures/particle/shines2.png b/backgrounds/fallback/textures/particle/shines2.png index 64366c5..c42a476 100644 Binary files a/backgrounds/fallback/textures/particle/shines2.png and b/backgrounds/fallback/textures/particle/shines2.png differ diff --git a/backgrounds/fallback/textures/particle/squares-c.png b/backgrounds/fallback/textures/particle/squares-c.png index 9fa6216..40d2c6f 100644 Binary files a/backgrounds/fallback/textures/particle/squares-c.png and b/backgrounds/fallback/textures/particle/squares-c.png differ diff --git a/backgrounds/fallback/textures/particle/squares.png b/backgrounds/fallback/textures/particle/squares.png index d39c82a..10760d3 100644 Binary files a/backgrounds/fallback/textures/particle/squares.png and b/backgrounds/fallback/textures/particle/squares.png differ diff --git a/backgrounds/fallback/textures/particle/star_particles-c.png b/backgrounds/fallback/textures/particle/star_particles-c.png index a709159..98f680c 100644 Binary files a/backgrounds/fallback/textures/particle/star_particles-c.png and b/backgrounds/fallback/textures/particle/star_particles-c.png differ diff --git a/backgrounds/fallback/textures/particle/star_particles.png b/backgrounds/fallback/textures/particle/star_particles.png index 8e7617e..e07484c 100644 Binary files a/backgrounds/fallback/textures/particle/star_particles.png and b/backgrounds/fallback/textures/particle/star_particles.png differ diff --git a/backgrounds/fallback/textures/particle/street_lanterns-c.png b/backgrounds/fallback/textures/particle/street_lanterns-c.png index eee34e0..195740d 100644 Binary files a/backgrounds/fallback/textures/particle/street_lanterns-c.png and b/backgrounds/fallback/textures/particle/street_lanterns-c.png differ diff --git a/backgrounds/fallback/textures/particle/street_lanterns.png b/backgrounds/fallback/textures/particle/street_lanterns.png index 93d4e12..7b4316f 100644 Binary files a/backgrounds/fallback/textures/particle/street_lanterns.png and b/backgrounds/fallback/textures/particle/street_lanterns.png differ diff --git a/backgrounds/fallback/textures/particle/technosparkles.png b/backgrounds/fallback/textures/particle/technosparkles.png index e379839..71e017d 100644 Binary files a/backgrounds/fallback/textures/particle/technosparkles.png and b/backgrounds/fallback/textures/particle/technosparkles.png differ diff --git a/backgrounds/fallback/textures/particle/triangles.png b/backgrounds/fallback/textures/particle/triangles.png index 0e77725..be75164 100644 Binary files a/backgrounds/fallback/textures/particle/triangles.png and b/backgrounds/fallback/textures/particle/triangles.png differ diff --git a/backgrounds/fallback/textures/particle/twilight-c.png b/backgrounds/fallback/textures/particle/twilight-c.png index 67a5a24..ad20287 100644 Binary files a/backgrounds/fallback/textures/particle/twilight-c.png and b/backgrounds/fallback/textures/particle/twilight-c.png differ diff --git a/backgrounds/fallback/textures/particle/twilight.png b/backgrounds/fallback/textures/particle/twilight.png index 41cbd60..475f94d 100644 Binary files a/backgrounds/fallback/textures/particle/twilight.png and b/backgrounds/fallback/textures/particle/twilight.png differ diff --git a/backgrounds/fallback/textures/tunnel/arrows-large-c.png b/backgrounds/fallback/textures/tunnel/arrows-large-c.png index a3e781c..b08ca7d 100644 Binary files a/backgrounds/fallback/textures/tunnel/arrows-large-c.png and b/backgrounds/fallback/textures/tunnel/arrows-large-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/arrows-large.png b/backgrounds/fallback/textures/tunnel/arrows-large.png index e2d11b1..4fb5778 100644 Binary files a/backgrounds/fallback/textures/tunnel/arrows-large.png and b/backgrounds/fallback/textures/tunnel/arrows-large.png differ diff --git a/backgrounds/fallback/textures/tunnel/arrows-small-c.png b/backgrounds/fallback/textures/tunnel/arrows-small-c.png index 0ae7e3e..f4ac2be 100644 Binary files a/backgrounds/fallback/textures/tunnel/arrows-small-c.png and b/backgrounds/fallback/textures/tunnel/arrows-small-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/arrows-small.png b/backgrounds/fallback/textures/tunnel/arrows-small.png index e8b72b6..b151c5c 100644 Binary files a/backgrounds/fallback/textures/tunnel/arrows-small.png and b/backgrounds/fallback/textures/tunnel/arrows-small.png differ diff --git a/backgrounds/fallback/textures/tunnel/beams-c.png b/backgrounds/fallback/textures/tunnel/beams-c.png index 8b6f269..6c4c51d 100644 Binary files a/backgrounds/fallback/textures/tunnel/beams-c.png and b/backgrounds/fallback/textures/tunnel/beams-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/beams.png b/backgrounds/fallback/textures/tunnel/beams.png index 48c2215..f7de972 100644 Binary files a/backgrounds/fallback/textures/tunnel/beams.png and b/backgrounds/fallback/textures/tunnel/beams.png differ diff --git a/backgrounds/fallback/textures/tunnel/clouds-dark-c.png b/backgrounds/fallback/textures/tunnel/clouds-dark-c.png index 6a815f4..2d3ac47 100644 Binary files a/backgrounds/fallback/textures/tunnel/clouds-dark-c.png and b/backgrounds/fallback/textures/tunnel/clouds-dark-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/clouds-dark.png b/backgrounds/fallback/textures/tunnel/clouds-dark.png index 8e53265..401a894 100644 Binary files a/backgrounds/fallback/textures/tunnel/clouds-dark.png and b/backgrounds/fallback/textures/tunnel/clouds-dark.png differ diff --git a/backgrounds/fallback/textures/tunnel/clouds.png b/backgrounds/fallback/textures/tunnel/clouds.png index 66848c2..a41a637 100644 Binary files a/backgrounds/fallback/textures/tunnel/clouds.png and b/backgrounds/fallback/textures/tunnel/clouds.png differ diff --git a/backgrounds/fallback/textures/tunnel/dome-c.png b/backgrounds/fallback/textures/tunnel/dome-c.png index 9977c0e..4f267a2 100644 Binary files a/backgrounds/fallback/textures/tunnel/dome-c.png and b/backgrounds/fallback/textures/tunnel/dome-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/dome-red-c.png b/backgrounds/fallback/textures/tunnel/dome-red-c.png index 95c2636..fdfc7d3 100644 Binary files a/backgrounds/fallback/textures/tunnel/dome-red-c.png and b/backgrounds/fallback/textures/tunnel/dome-red-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/dome-red.png b/backgrounds/fallback/textures/tunnel/dome-red.png index 1d3b5db..b34a5e5 100644 Binary files a/backgrounds/fallback/textures/tunnel/dome-red.png and b/backgrounds/fallback/textures/tunnel/dome-red.png differ diff --git a/backgrounds/fallback/textures/tunnel/dome.png b/backgrounds/fallback/textures/tunnel/dome.png index 45faa88..7c1547f 100644 Binary files a/backgrounds/fallback/textures/tunnel/dome.png and b/backgrounds/fallback/textures/tunnel/dome.png differ diff --git a/backgrounds/fallback/textures/tunnel/electro-blue.png b/backgrounds/fallback/textures/tunnel/electro-blue.png index 10ee447..9af759e 100644 Binary files a/backgrounds/fallback/textures/tunnel/electro-blue.png and b/backgrounds/fallback/textures/tunnel/electro-blue.png differ diff --git a/backgrounds/fallback/textures/tunnel/electro-c.png b/backgrounds/fallback/textures/tunnel/electro-c.png index 15de9f2..5561959 100644 Binary files a/backgrounds/fallback/textures/tunnel/electro-c.png and b/backgrounds/fallback/textures/tunnel/electro-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/electro.png b/backgrounds/fallback/textures/tunnel/electro.png index d5f34f7..f068aa9 100644 Binary files a/backgrounds/fallback/textures/tunnel/electro.png and b/backgrounds/fallback/textures/tunnel/electro.png differ diff --git a/backgrounds/fallback/textures/tunnel/game.png b/backgrounds/fallback/textures/tunnel/game.png index cb7a5a3..f843d6c 100644 Binary files a/backgrounds/fallback/textures/tunnel/game.png and b/backgrounds/fallback/textures/tunnel/game.png differ diff --git a/backgrounds/fallback/textures/tunnel/genom-c.png b/backgrounds/fallback/textures/tunnel/genom-c.png index ae7ae81..06d50e9 100644 Binary files a/backgrounds/fallback/textures/tunnel/genom-c.png and b/backgrounds/fallback/textures/tunnel/genom-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/genom.png b/backgrounds/fallback/textures/tunnel/genom.png index 459f5d7..af80adc 100644 Binary files a/backgrounds/fallback/textures/tunnel/genom.png and b/backgrounds/fallback/textures/tunnel/genom.png differ diff --git a/backgrounds/fallback/textures/tunnel/hexagons-c.png b/backgrounds/fallback/textures/tunnel/hexagons-c.png index 071401a..9987c86 100644 Binary files a/backgrounds/fallback/textures/tunnel/hexagons-c.png and b/backgrounds/fallback/textures/tunnel/hexagons-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/hexagons-gray.png b/backgrounds/fallback/textures/tunnel/hexagons-gray.png index f1e6cd8..e1146d0 100644 Binary files a/backgrounds/fallback/textures/tunnel/hexagons-gray.png and b/backgrounds/fallback/textures/tunnel/hexagons-gray.png differ diff --git a/backgrounds/fallback/textures/tunnel/hexagons.png b/backgrounds/fallback/textures/tunnel/hexagons.png index b369380..ed3cd28 100644 Binary files a/backgrounds/fallback/textures/tunnel/hexagons.png and b/backgrounds/fallback/textures/tunnel/hexagons.png differ diff --git a/backgrounds/fallback/textures/tunnel/idofront-c.png b/backgrounds/fallback/textures/tunnel/idofront-c.png index 10962b0..da96cfb 100644 Binary files a/backgrounds/fallback/textures/tunnel/idofront-c.png and b/backgrounds/fallback/textures/tunnel/idofront-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/idofront.png b/backgrounds/fallback/textures/tunnel/idofront.png index 8a6f156..6c1f0bb 100644 Binary files a/backgrounds/fallback/textures/tunnel/idofront.png and b/backgrounds/fallback/textures/tunnel/idofront.png differ diff --git a/backgrounds/fallback/textures/tunnel/iseki-c.png b/backgrounds/fallback/textures/tunnel/iseki-c.png index b15c345..f2a2937 100644 Binary files a/backgrounds/fallback/textures/tunnel/iseki-c.png and b/backgrounds/fallback/textures/tunnel/iseki-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/iseki.png b/backgrounds/fallback/textures/tunnel/iseki.png index e109396..09db935 100644 Binary files a/backgrounds/fallback/textures/tunnel/iseki.png and b/backgrounds/fallback/textures/tunnel/iseki.png differ diff --git a/backgrounds/fallback/textures/tunnel/kac1-c.png b/backgrounds/fallback/textures/tunnel/kac1-c.png index 1a749b1..7d66293 100644 Binary files a/backgrounds/fallback/textures/tunnel/kac1-c.png and b/backgrounds/fallback/textures/tunnel/kac1-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/kac1.png b/backgrounds/fallback/textures/tunnel/kac1.png index e546626..dfea2dc 100644 Binary files a/backgrounds/fallback/textures/tunnel/kac1.png and b/backgrounds/fallback/textures/tunnel/kac1.png differ diff --git a/backgrounds/fallback/textures/tunnel/sky-gears-c.png b/backgrounds/fallback/textures/tunnel/sky-gears-c.png index 8cb462d..4ee4812 100644 Binary files a/backgrounds/fallback/textures/tunnel/sky-gears-c.png and b/backgrounds/fallback/textures/tunnel/sky-gears-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/sky-gears.png b/backgrounds/fallback/textures/tunnel/sky-gears.png index 8889ddb..af17863 100644 Binary files a/backgrounds/fallback/textures/tunnel/sky-gears.png and b/backgrounds/fallback/textures/tunnel/sky-gears.png differ diff --git a/backgrounds/fallback/textures/tunnel/smoke.png b/backgrounds/fallback/textures/tunnel/smoke.png index 8c24249..4c43571 100644 Binary files a/backgrounds/fallback/textures/tunnel/smoke.png and b/backgrounds/fallback/textures/tunnel/smoke.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-blue-c.png b/backgrounds/fallback/textures/tunnel/wave-blue-c.png index 06c9d25..e7fe552 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-blue-c.png and b/backgrounds/fallback/textures/tunnel/wave-blue-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-blue.png b/backgrounds/fallback/textures/tunnel/wave-blue.png index 7c46e5e..9f875c2 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-blue.png and b/backgrounds/fallback/textures/tunnel/wave-blue.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-green-c.png b/backgrounds/fallback/textures/tunnel/wave-green-c.png index 4f83430..6a8f11b 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-green-c.png and b/backgrounds/fallback/textures/tunnel/wave-green-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-green.png b/backgrounds/fallback/textures/tunnel/wave-green.png index 3de9a87..a3f411a 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-green.png and b/backgrounds/fallback/textures/tunnel/wave-green.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-orange-c.png b/backgrounds/fallback/textures/tunnel/wave-orange-c.png index 450398b..d8ade5b 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-orange-c.png and b/backgrounds/fallback/textures/tunnel/wave-orange-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-orange.png b/backgrounds/fallback/textures/tunnel/wave-orange.png index 5a2d04c..8da2b6e 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-orange.png and b/backgrounds/fallback/textures/tunnel/wave-orange.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-red-c.png b/backgrounds/fallback/textures/tunnel/wave-red-c.png index 375a99a..4d24fe6 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-red-c.png and b/backgrounds/fallback/textures/tunnel/wave-red-c.png differ diff --git a/backgrounds/fallback/textures/tunnel/wave-red.png b/backgrounds/fallback/textures/tunnel/wave-red.png index 715140e..a31d00d 100644 Binary files a/backgrounds/fallback/textures/tunnel/wave-red.png and b/backgrounds/fallback/textures/tunnel/wave-red.png differ diff --git a/config-definitions.json b/config-definitions.json index 23a00c7..4e67594 100644 --- a/config-definitions.json +++ b/config-definitions.json @@ -14,13 +14,6 @@ "default": "Hellooooooo" }, - "Skill LV": { - "type": "selection", - "label": "Pick Your True Skill", - "default": "None", - "values": ["None", "Skilled", "Expert", "Expert (Mastery)", "Lower Pro", "Lower Pro (Mastery)","Upper Pro","Upper Pro (Mastery)","Lower Master","Lower Master (Mastery)","Upper Master","Upper Master (Mastery)","Grand Master","Grand Master +"] - }, - "separator_b": {}, "Animations": {"type": "label"}, @@ -30,6 +23,12 @@ "default": false }, + "animations_skipIntro": { + "type": "bool", + "label": "Skip intro splash screens", + "default": false + }, + "separator_c": {}, "Crew": { "type": "label" }, @@ -62,5 +61,20 @@ "label": "Use different colors for UC and PUC chain numbers", "type": "bool", "default": false + }, + + "gameplay_showSearchControls": { + "label": "Show song select controls when searching", + "type": "bool", + "default": true + }, + + "separator_f": {}, + "Debug": { "type": "label" }, + + "debug_showInformation": { + "label": "Show debug information (sometimes in the middle of the screen when you're playing)", + "type": "bool", + "default": false } } diff --git a/docs/lua_api/IR.lua b/docs/lua_api/IR.lua new file mode 100644 index 0000000..2deea4a --- /dev/null +++ b/docs/lua_api/IR.lua @@ -0,0 +1,69 @@ +-- IR State enum +---@class States +local States = { + Unused = 0, + Pending = 10, + Success = 20, + Accepted = 22, + BadRequest = 40, + Unauthorized = 41, + ChartRefused = 42, + Forbidden = 43, + NotFound = 44, + ServerError = 50, + RequestFailure = 60 +} + +---@class IRData +---@field Active boolean # USC IR configured and active +---@field States States # IR reposonse state enum +IRData = {} + +---@class IRHeartbeatResponseBody +---@field serverTime integer +---@field serverName string +---@field irVersion string +IRHeartbeatResponseBody = {} + +---@class IRRecordResponseBody +---@field record ServerScore +IRRecordResponseBody = {} + +---@class IRLeaderboardResponseBody +---@field scores ServerScore[] +IRLeaderboardResponseBody = {} + +---@class IRResponse +---@field statusCode integer +---@field description string +---@field body nil|IRHeartbeatResponseBody|IRRecordResponseBody|IRLeaderboardResponseBody +IRResponse = {} + +-- Performs a Heartbeat request. +---@param callback fun(res: IRResponse) # Callback function receives IRResponse as it's first parameter +local function Heartbeat(callback) end + +-- Performs a Chart Tracked request for the chart with the provided hash. +---@param hash string # song hash +---@param callback fun(res: IRResponse) # Callback function receives IRResponse as it's first parameter +local function ChartTracked(hash, callback) end + +-- Performs a Record request for the chart with the provided hash. +---@param hash string # song hash +---@param callback fun(res: IRResponse) # Callback function receives IRResponse as it's first parameter +local function Record(hash, callback) end + +-- Performs a Leaderboard request for the chart with the provided hash, with parameters mode and n. +---@param hash string # song hash +---@param mode "best"|"rivals" # request leaderboard mode +---@param n integer # limit the number of requested scores +---@param callback fun(res: IRResponse) # Callback function receives IRResponse as it's first parameter +local function Leaderboard(hash, mode, n, callback) end + +---@type table +IR = { + Heartbeat = Heartbeat, + ChartTracked = ChartTracked, + Record = Record, + Leaderboard = Leaderboard +} \ No newline at end of file diff --git a/docs/lua_api/game.lua b/docs/lua_api/game.lua index 1758dc0..d5d68a3 100644 --- a/docs/lua_api/game.lua +++ b/docs/lua_api/game.lua @@ -7,7 +7,7 @@ GetButton = function(button) end -- Gets the absolute rotation of the specified knob ---@param knob integer # `0 = left`, `1 = right` ----@return number angle # in radians, `0.0` to `2*pi` +---@return number angle # in radians, `-2*pi` to `0` (turning CCW) and `0` to `2*pi` (turning CW) GetKnob = function(knob) end -- Gets the color of the specified laser diff --git a/docs/lua_api/result.lua b/docs/lua_api/result.lua index 23e11ed..aa17fb9 100644 --- a/docs/lua_api/result.lua +++ b/docs/lua_api/result.lua @@ -41,6 +41,30 @@ Score = {}; ---@field failReason string # Fail reason if a challenge requirement was not met ChartResult = {}; +---@class ServerScoreOptions +---@field gaugeType integer # An enum value representing the gauge type used. 0 = normal, 1 = hard. Further values are not currently specified. +---@field gaugeOpt integer # Reserved +---@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 +---@field gauge number # Submitted Gauge result +---@field timestamp integer # Unix timestamp of the score +---@field crit integer # Hits inside the critical window +---@field near integer # Hits inside the near window +---@field early integer # Hits inside the near window which were early +---@field late integer # Hits inside the near window which were late +---@field combo integer # Best combo reached +---@field error integer # Missed notes +---@field options ServerScoreOptions # The options in use. Includes gauge type, etc. +---@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 ---@field artist string # Chart artist ---@field auto_flags integer # Autoplay flag @@ -72,7 +96,9 @@ ChartResult = {}; ---@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 ----@field irState integer # Internet ranking flag +---@field irState integer # Current state of the IR score submission request (a USC-IR code, including extensions 0/10/60) +---@field irDescription string # The description in the IR response (nil if irState is 0 or 10) +---@field irScores ServerScore[]|nil # Score submission result, nil if irState != 20 ---@field isSelf boolean # Only for multiplayer, `false` if score is of another player ---@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` diff --git a/docs/lua_api/titlescreen.lua b/docs/lua_api/titlescreen.lua new file mode 100644 index 0000000..749eb74 --- /dev/null +++ b/docs/lua_api/titlescreen.lua @@ -0,0 +1,35 @@ +local function Exit() end + +local function Settings() end + +local function Start() end + +local function DLScreen() end + +local function Update() end + +local function Multiplayer() end + +local function Challenges() end + +Menu = { + Exit = Exit, + Settings = Settings, + Start = Start, + DLScreen = DLScreen, + Update = Update, + Multiplayer = Multiplayer, + Challenges = Challenges +} + +--- Render frame for titlescreen +---@param deltaTime number Elapsed frametime since last frame +function render(deltaTime) end + +--- Button event handler for titlescreen +---@param buttonCode integer Corresponds to game.Button_* +function button_pressed(buttonCode) end + +--- Mouse event handler for titlescreen +---@param button integer +function mouse_pressed(button) end \ No newline at end of file diff --git a/scripts/api/animation.lua b/scripts/api/animation.lua new file mode 100644 index 0000000..af8641c --- /dev/null +++ b/scripts/api/animation.lua @@ -0,0 +1,202 @@ + +require "common.class" + +require "api.graphics" + +local Image = require "api.image" + +---@class AnimationParams +---@field fps number? +---@field loop boolean? +---@field loopPoint integer? +---@field width number? +---@field height number? +---@field x number? +---@field y number? +---@field scaleX number? +---@field scaleY number? +---@field centered boolean? +---@field blendOp integer? +---@field color number[]? +---@field alpha number? +---@field stroke StrokeParams? + +---@class Animation +---@field frames Image[] +---@field frameCount integer +---@field frameTime number +---@field loop boolean +---@field loopPoint integer +---@field width number? +---@field height number? +---@field x number? +---@field y number? +---@field scaleX number? +---@field scaleY number? +---@field centered boolean? +---@field blendOp integer? +---@field color number[]? +---@field alpha number? +---@field stroke StrokeParams? +local Animation = { }; + +---@class AnimationState +---@field animation Animation # The animation data this state is playing through +---@field frameIndex integer # Current frame in the animation +---@field timer number # Timer used to determine when to change to the next frame +---@field running boolean # Is the animation currently running and accepting updates? +---@field callback function? # Called when the animation completes +local AnimationState = { }; + +local function loadSequentialAnimationFrames(animPath) + local frames = { }; + local count = 0; + + local detectedFormat = nil; + + while (true) do + local frame = nil; + if (detectedFormat) then + frame = Image.new(detectedFormat:format(animPath, count + 1), true); + else + for i = 1, 4 do + local format = '%s/%0' .. i .. 'd.png'; + frame = Image.new(format:format(animPath, count + 1), true); + + if (frame) then + detectedFormat = format; + break; + end + end + end + + if (not frame) then + break; + end + + count = count + 1; + frames[count] = frame; + end + + return frames, count; +end + +---Animation constructor +---@param animPath string +---@param params AnimationParams +---@return Animation +function Animation.new(animPath, params) + local frames, frameCount = loadSequentialAnimationFrames(animPath); + + local instance = { + frames = frames, + frameCount = frameCount, + + frameTime = 1 / (params.fps or 30), + loop = params.loop or false, + loopPoint = params.loopPoint or 1, + }; + + if (params.width ~= nil) then instance.width = params.width; end + if (params.height ~= nil) then instance.height = params.height; end + if (params.x ~= nil) then instance.x = params.x; end + if (params.y ~= nil) then instance.y = params.y; end + if (params.scaleX ~= nil) then instance.scaleX = params.scaleX; end + if (params.scaleY ~= nil) then instance.scaleY = params.scaleY; end + if (params.centered ~= nil) then instance.centered = params.centered; end + if (params.blendOp ~= nil) then instance.blendOp = params.blendOp; end + if (params.color ~= nil) then instance.color = params.color; end + if (params.alpha ~= nil) then instance.alpha = params.alpha; end + if (params.stroke ~= nil) then instance.stroke = params.stroke; end + + return CreateInstance(Animation, instance); +end + +---Create an AnimationState to play this animation. +---The AnimationState is not started. +---@param callback function? +---@return AnimationState +function Animation:createState(callback) + ---@type AnimationState + local state = { animation = self, callback = callback, frameIndex = 1, timer = 0, running = false }; + return CreateInstance(AnimationState, state); +end + +---Create an AnimationState to play this animation and start it. +---@param callback function? +---@return AnimationState +function Animation:start(callback) + local state = self:createState(callback); + state:start(); + + return state; +end + +---Start this AnimationState. +---Does nothing if it's already running. +function AnimationState:start() + self.running = true; +end + +---Restart this AnimationState. +---The frame index is reset to 1. +function AnimationState:restart() + self.running = true; + self.frameIndex = 1; + self.timer = 0; +end + +---Stop this AnimationState. +function AnimationState:stop() + self.running = false; +end + +---Updates this AnimationState and then rendersit, passing on the given ImageParams to each frame. +---@param deltaTime number +---@param params? ImageParams +function AnimationState:render(deltaTime, params) + if (not self.running) then return; end; + + self.timer = self.timer + deltaTime; + + while (self.timer > self.animation.frameTime) do + self.timer = self.timer - self.animation.frameTime; + self.frameIndex = self.frameIndex + 1; + + if (self.frameIndex > self.animation.frameCount) then + if (self.animation.loop) then + self.frameIndex = self.animation.loopPoint; + else + self.running = false; + + if (self.callback) then + self.callback(); + end + + return; + end + end + end + + if (params) then + if (params.width == nil) then params.width = self.animation.width; end + if (params.height == nil) then params.height = self.animation.height; end + if (params.x == nil) then params.x = self.animation.x; end + if (params.y == nil) then params.y = self.animation.y; end + if (params.scaleX == nil) then params.scaleX = self.animation.scaleX; end + if (params.scaleY == nil) then params.scaleY = self.animation.scaleY; end + if (params.centered == nil) then params.centered = self.animation.centered; end + if (params.blendOp == nil) then params.blendOp = self.animation.blendOp; end + if (params.alpha == nil) then params.alpha = self.animation.alpha; end + if (params.stroke == nil) then params.stroke = self.animation.stroke; end + end + + local frame = self.animation.frames[self.frameIndex]; + if (not frame) then + -- TODO(local): what do + else + frame:render(params); + end +end + +return Animation; diff --git a/scripts/api/graphics.lua b/scripts/api/graphics.lua new file mode 100644 index 0000000..38a8e55 --- /dev/null +++ b/scripts/api/graphics.lua @@ -0,0 +1,6 @@ + +-- TODO(local): put these class types somewhere more common +---@class StrokeParams +---@field color number[]? +---@field alpha number? +---@field size number? diff --git a/scripts/api/image.lua b/scripts/api/image.lua new file mode 100644 index 0000000..6fe6531 --- /dev/null +++ b/scripts/api/image.lua @@ -0,0 +1,171 @@ + +require "common.class" + +require "api.graphics" + +---@class ImageParams +---@field width number +---@field height number +---@field x number? +---@field y number? +---@field scaleX number? +---@field scaleY number? +---@field centered boolean? +---@field blendOp integer? +---@field color number[]? +---@field alpha number? +---@field stroke StrokeParams? + +---@class Image +---@field handle integer +---@field width number +---@field height number +---@field x number? +---@field y number? +---@field scaleX number? +---@field scaleY number? +---@field centered boolean? +---@field blendOp integer? +---@field color number[]? +---@field alpha number? +---@field stroke StrokeParams? +local Image = { }; + +---Image constructor +---@param imagePath string # The path to the skin image to load +---@return Image +function Image.new(imagePath, noFallback) + local handle = gfx.CreateSkinImage(imagePath or '', 0); + if (not handle) then + game.Log('Failed to load image "' .. imagePath .. '"', game.LOGGER_ERROR); + + if (noFallback) then return nil; end + + handle = gfx.CreateSkinImage('missing.png', 0); + if (not handle) then + game.Log('Failed to load fallback image "missing.png"', game.LOGGER_ERROR); + end + end + + local width, height = 64, 64; + if (handle) then + width, height = gfx.ImageSize(handle); + end + + local instance = { + handle = handle, + width = width, + height = height, + }; + + return CreateInstance(Image, instance); +end + +---Set the width and height of this Image. +---@param width number +---@param height number +---@return Image # Returns self for method chaining +function Image:setSize(width, height) + if (type(width) ~= "number") then width = 0; end + if (type(height) ~= "number") then height = 0; end + + self.width = width; + self.height = height; + + return self; +end + +---Set the stored position for this Image. +---If the position of this Image will not change frequently, +---using this method allows you to cache the render position +---instead of passing it to the render method on each invocation. +---@param x number +---@param y number +---@return Image # Returns self for method chaining +function Image:setPosition(x, y) + if (type(x) ~= "number") then x = 0; end + if (type(y) ~= "number") then y = 0; end + + self.x = x; + self.y = y; + + return self; +end + +---Renders this Image, applying any of the given ImageParams, +---then any of the cached Image fields, then any default values. +---@param params? ImageParams +function Image:render(params) + params = params or { }; + + local sx = params.scaleX or self.scaleX or 1; + local sy = params.scaleY or self.scaleY or 1; + + local x = params.x or self.x or 0; + local y = params.y or self.y or 0; + + local w = (params.width or self.width ) * sx; + local h = (params.height or self.height) * sy; + + if (params.centered or self.centered) then + x = x - w / 2; + y = y - h / 2; + end + + local blendOp = params.blendOp or self.blendOp or gfx.BLEND_OP_SOURCE_OVER; + + local r = 255; + local g = 255; + local b = 255; + + if (params.color) then + r = params.color[1]; + g = params.color[2]; + b = params.color[3]; + elseif (self.color) then + r = self.color[1]; + g = self.color[2]; + b = self.color[3]; + end + + local a = params.alpha or self.alpha or 1; + + gfx.BeginPath(); + gfx.GlobalCompositeOperation(blendOp); + + if (not self.handle) then + gfx.FillColor(r, g, b, a); + gfx.Rect(x, y, w, h); + gfx.FillColor(255, 255, 255, 255); + else + gfx.SetImageTint(r, g, b); + gfx.ImageRect(x, y, w, h, self.handle, a, 0); + gfx.SetImageTint(255, 255, 255); + end + + if (params.stroke or self.stroke) then + r = 255; + g = 255; + b = 255; + + if (params.stroke.color) then + r = params.stroke.color[1]; + g = params.stroke.color[2]; + b = params.stroke.color[3]; + elseif (self.stroke and self.stroke.color) then + r = self.stroke.color[1]; + g = self.stroke.color[2]; + b = self.stroke.color[3]; + end + + a = params.stroke.alpha or (self.stroke and self.stroke.alpha) or 255; + + local size = params.stroke.size or (self.stroke and self.stroke.size) or 1; + + gfx.StrokeColor(r, g, b, a); + gfx.StrokeWidth(size); + gfx.Stroke(); + end +end + +return Image; diff --git a/scripts/challengeresult.lua b/scripts/challengeresult.lua index a036edf..70a9e16 100644 --- a/scripts/challengeresult.lua +++ b/scripts/challengeresult.lua @@ -1,9 +1,10 @@ local Easing = require("common.easing"); local Footer = require("components.footer"); local DiffRectangle = require('components.diff_rectangle'); -local common = require('common.common'); -local Numbers = require('common.numbers') +local common = require('common.util'); +local Sound = require("common.sound") +local Numbers = require('components.numbers') local VolforceWindow = require("components.volforceWindow") -- Window variables @@ -39,7 +40,7 @@ local headerTitleImage = gfx.CreateSkinImage("challenge_result/header/title.png" local username = game.GetSkinSetting("username"); local appealCardImage = gfx.CreateSkinImage("crew/appeal_card.png", 0); -local danBadgeImage = gfx.CreateSkinImage("dan/none.png", 0); +local danBadgeImage = gfx.CreateSkinImage("dan/inf.png", 0); local crewImage = gfx.CreateSkinImage("crew/portrait.png", 0); local notchesImage = gfx.CreateSkinImage("challenge_result/notches.png", 0); @@ -89,7 +90,7 @@ end local function handleSfx() if not bgSfxPlayed then - common.stopMusic(); + Sound.stopMusic(); game.PlaySample("challenge_result.wav", true) bgSfxPlayed = true end @@ -225,7 +226,7 @@ end function result_set() - local reqTextWords = common.splitString(result.requirement_text, ' '); + local reqTextWords = common.split(result.requirement_text, ' '); for index, word in ipairs(reqTextWords) do if string.find(word, '%%') ~= nil then -- %% = %, because % is an escape char local percNumber = tonumber(string.gsub(word, '%%', ''), 10) diff --git a/scripts/common.lua b/scripts/common.lua index 8e02166..61c1440 100644 --- a/scripts/common.lua +++ b/scripts/common.lua @@ -1,156 +1,6 @@ +-- NOTE(local): DO NOT PUT ANYTHING HERE PLEASE THANKS +-- IF YOU DO THE GAME WILL IMMEDIATELY CRASH AND IT'S NOT THE BEST +-- THANK YOU HAVE A GOOD LUA gfx.LoadSkinFont("segoeui.ttf") --- Memo class -------------- -Memo = {} -Memo.new = function() - local this = { - cache = {} - } - setmetatable(this, {__index = Memo}) - return this -end - -Memo.memoize = function(this, key, generator) - local value = this.cache[key] - if not value then - value = generator() - this.cache[key] = value - end - return value -end - - --- Image class --------------- -Image = { - ANCHOR_LEFT = 1, - ANCHOR_CENTER = 2, - ANCHOR_RIGHT = 4, - ANCHOR_TOP = 8, - ANCHOR_BOTTOM = 16 -} -Image.skin = function(filename, imageFlags) - imageFlags = imageFlags or 0 - local image = gfx.CreateSkinImage(filename, imageFlags) - return Image.wrap(image) -end -Image.wrap = function(image) - local this = { - image = image - } - local w, h = gfx.ImageSize(this.image) - this.w = w - this.h = h - setmetatable(this, {__index = Image}) - return this -end - -Image.draw = function(this, params) - local x = params.x - local y = params.y - local w = params.w or this.w - local h = params.h or this.h - local alpha = params.alpha or 1 - local angle = params.angle or 0 - local anchor_h = params.anchor_h or Image.ANCHOR_CENTER - local anchor_v = params.anchor_v or Image.ANCHOR_CENTER - local scale = params.scale or 1; - - w = w * scale; - h = h * scale; - - if anchor_h == Image.ANCHOR_CENTER then - x = x - w / 2 - elseif anchor_h == Image.ANCHOR_RIGHT then - x = x - w - end - - if anchor_v == Image.ANCHOR_CENTER then - y = y - h / 2 - elseif anchor_v == Image.ANCHOR_BOTTOM then - y = y - h - end - - gfx.BeginPath() - gfx.ImageRect(x, y, w, h, this.image, alpha, angle) -end - - --- ImageFont class ------------------- -ImageFont = {} -ImageFont.new = function(path, chars) - local this = { - images = {} - } - -- load character images - for i = 1, chars:len() do - local c = chars:sub(i, i) - local n = c - if c == "." then - n = "dot" - end - local image = Image.skin(string.format("%s/%s.png", path, n), 0) - this.images[c] = image - end - -- use size of first char as font size - local w, h = gfx.ImageSize(this.images[chars:sub(1, 1)].image) - this.w = w - this.h = h - - setmetatable(this, {__index = ImageFont}) - return this -end -ImageFont.draw = function(this, text, x, y, alpha, hFlag, vFlag) - local totalW = text:len() * this.w - - -- adjust horizontal alignment - if hFlag == gfx.TEXT_ALIGN_CENTER then - x = x - totalW / 2 - elseif hFlag == gfx.TEXT_ALIGN_RIGHT then - x = x - totalW - end - - -- adjust vertical alignment - if vFlag == gfx.TEXT_ALIGN_MIDDLE then - y = y - this.h / 2 - elseif vFlag == gfx.TEXT_ALIGN_BOTTOM then - y = y - this.h - end - - for i = 1, text:len() do - local c = text:sub(i, i) - local image = this.images[c] - if image ~= nil then - gfx.BeginPath() - gfx.ImageRect(x, y, this.w, this.h, image.image, alpha, 0) - end - x = x + this.w - end -end - -function GetDisplayDifficulty(jacketPath, difficulty) - local strippedPath = string.match(jacketPath:lower(), "[/\\][^\\/]+$") - if difficulty == 3 and strippedPath then - if string.find(strippedPath, "inf") ~= nil then - return 5 - elseif string.find(strippedPath, "grv") ~= nil then - return 6 - elseif string.find(strippedPath, "hvn") ~= nil then - return 7 - elseif string.find(strippedPath, "vvd") ~= nil then - return 8 - end - end - - return difficulty+1 -end - -function split(s, delimiter) - result = {}; - for match in (s..delimiter):gmatch("(.-)"..delimiter) do - table.insert(result, match); - end - return result; -end \ No newline at end of file +function useFootGun() while true do end end diff --git a/scripts/common/charting.lua b/scripts/common/charting.lua new file mode 100644 index 0000000..261c6d5 --- /dev/null +++ b/scripts/common/charting.lua @@ -0,0 +1,26 @@ +local Charting = { }; + +function Charting.GetDisplayDifficulty(jacketPath, difficulty) + if jacketPath == nil then + return difficulty + end + + local strippedPath = string.match(jacketPath:lower(), "[/\\][^\\/]+$") + if difficulty == 3 and strippedPath then + if string.find(strippedPath, "inf") ~= nil then + return 5 + elseif string.find(strippedPath, "grv") ~= nil then + return 6 + elseif string.find(strippedPath, "hvn") ~= nil then + return 7 + elseif string.find(strippedPath, "vvd") ~= nil then + return 8 + elseif string.find(strippedPath, "xcd") ~= nil then + return 9 + end + end + + return difficulty + 1 +end + +return Charting; diff --git a/scripts/common/class.lua b/scripts/common/class.lua new file mode 100644 index 0000000..b3ed3ab --- /dev/null +++ b/scripts/common/class.lua @@ -0,0 +1,37 @@ +---Member lookup helper function +---@param key string +---@param bases any +---@return any +local function search(key, bases) + for _, base in ipairs(bases) do + local v = base[key] -- try `i'-th superclass + if v then return v end + end +end + +---Create polimorphic class +---@generic BaseT, T +---@param cls T # class metatable +---@param o? table # initial parameters +---@param ... BaseT # base class metatables (if any) +---@return T # class instance +function CreateInstance(cls, o, ...) + o = o or {} + local nargs = select("#", ...) + local vargs = { select(1, ...) } + cls.__index = cls + if nargs == 1 then + -- single inheritance + local base = vargs[1] + setmetatable(cls, {__index = base}) + o = base.new(o) + elseif nargs > 1 then + -- multiple inheritance (note: slow(er) member lookup) + setmetatable(cls, {__index = function(t, k) return search(k, vargs) end}) + for _, base in ipairs(vargs) do + o = base.new(o) + end + end + setmetatable(o, cls) + return o +end diff --git a/scripts/common/dimensions.lua b/scripts/common/dimensions.lua index aef18dc..e381b8a 100644 --- a/scripts/common/dimensions.lua +++ b/scripts/common/dimensions.lua @@ -1,34 +1,18 @@ local dimtable = { - design = { - width = 1080, - height = 1920 - }, - screen = { - width = nil, - height = nil - }, - view = { - width = nil, - height = nil - }, - ratio = { - landscapeUW = 21 / 9, - landscapeWide = 16 / 9, - landscapeStd = 4 / 3, - portrait = 9 / 16 - } + design = {width = 1080, height = 1920}, + screen = {width = nil, height = nil}, + view = {width = nil, height = nil}, + ratio = {landscapeUW = 21 / 9, landscapeWide = 16 / 9, landscapeStd = 4 / 3, portrait = 9 / 16}, } -local function transformToDesignSpace() +dimtable.transformToScreenSpace = function() gfx.Translate((dimtable.screen.width - dimtable.view.width) / 2, 0); gfx.Scale(dimtable.view.width / dimtable.design.width, dimtable.view.height / dimtable.design.height); gfx.Scissor(0, 0, dimtable.design.width, dimtable.design.height); end -local function updateResolution(ratio) - if not ratio then - ratio = dimtable.ratio.portrait - end +dimtable.updateResolution = function(ratio) + if not ratio then ratio = dimtable.ratio.portrait end local screenWidth, screenHeight = game.GetResolution() if screenWidth ~= dimtable.screen.width or screenHeight ~= dimtable.screen.height then @@ -37,10 +21,42 @@ local function updateResolution(ratio) end end +---Convert screenspace coordinates to viewspace coordinates +---@param screenX number +---@param screenY number +---@param offsetX? number Viewport offset from the left side (defaults to the portrait viewport offset) +---@param offsetY? number Viewport offset from the top side (defaults to 0) +---@return number, number +dimtable.toViewSpace = function(screenX, screenY, offsetX, offsetY) + offsetX = offsetX or (dimtable.screen.width - dimtable.view.width) / 2 + offsetY = offsetY or 0 --- return by reference trickery: + local viewX, viewY, scaleX, scaleY -local t = dimtable -t.transformToDesignSpace = transformToDesignSpace -t.updateResolution = updateResolution -return t \ No newline at end of file + scaleX = dimtable.design.width / dimtable.view.width + scaleY = dimtable.design.height / dimtable.view.height + + viewX = (screenX - offsetX) * scaleX + viewY = (screenY - offsetY) * scaleY + + return viewX, viewY +end + +---Set's up scaled transforms based on the current resolution. +---@param x number +---@param y number +---@param rotation number +---@return number, boolean # The scale applied to the transform and the current landscape state +function dimtable.setUpTransforms(x, y, rotation) + local scale = dimtable.screen.width / dimtable.view.width; + local isLandscape = dimtable.view.width > dimtable.view.height; + + gfx.ResetTransform(); + gfx.Translate(x, y); + gfx.Rotate(rotation); + gfx.Scale(scale, scale); + + return scale, isLandscape; +end + +return dimtable diff --git a/scripts/common/filereader.lua b/scripts/common/filereader.lua new file mode 100644 index 0000000..1ac858f --- /dev/null +++ b/scripts/common/filereader.lua @@ -0,0 +1,105 @@ +require("common.globals") +--file reader utility functions + +---Get game path +---@return string, string +local function getGamePath() + return debug.getinfo(1,"S").source:sub(2):match("(.*)([\\/])skins") -- this is very hacky :) +end + +local function readBytes(_file) + local out = {} + repeat + local buffer = _file:read(4*1024) + for c in (buffer or ''):gmatch(".") do + table.insert(out, c:byte()) + end + until not buffer + return out +end + +---Read a file in the game folder by lines +---@param path string relative path to game file +---@param mode? openmode default "r" +---@return nil|string[] +function ReadGameFileLines(path, mode) + mode = mode or "r" + + local gamepath, sep = getGamePath() + + local lines = {} + + local f = io.open(gamepath .. sep .. path, mode) + if not f then return nil end + + for line in f:lines("l") do + table.insert(lines, line) + end + f:close() + + return lines +end + +---Read a file in the game folder +---@param path string # relative path to game file +---@param mode? openmode # default "r" +---@return nil|string|integer[] +function ReadGameFile(path, mode) + mode = mode or "r" + + local gamepath, sep = getGamePath() + local out + + local f = io.open(gamepath .. sep .. path, mode) + if not f then return nil end + + if mode:match(".*b") then + out = readBytes(f) + else + out = f:read("a") + end + f:close() + + return out +end + +---Find patterns in file +---@param path string # relative path to game file +---@param pattern string # search pattern +---@return table # {{group1, group2, ...}, ...} +function FindPatterns(path, pattern) + local matches = {} + for _, line in ipairs(ReadGameFileLines(path, "r")) do + if line:match(pattern) then + table.insert(matches, {line:match(pattern)}) + end + end + return matches +end + +--- Check if a file or directory exists in this path +---@param file string # relative path to game file +---@return boolean # file exists +---@return string # error message +function IsFileExists(file) + local gamepath, sep = getGamePath() + file = gamepath .. sep .. file + + local ok, err, code = os.rename(file, file) + if not ok then + game.Log("err: "..err..", code: "..code, game.LOGGER_DEBUG) + if code == 13 then + -- Permission denied, but it exists + return true + end + end + return ok, err +end + +--- Check if a directory exists in this path +---@param path string # relative path to game directory +---@return boolean # directory exists +function IsDir(path) + -- "/" works on both Unix and Windows + return IsFileExists(path .. "/") +end diff --git a/scripts/common/gameconfig.lua b/scripts/common/gameconfig.lua new file mode 100644 index 0000000..06accbf --- /dev/null +++ b/scripts/common/gameconfig.lua @@ -0,0 +1,11 @@ +require("common.filereader") + +GameConfig = {} + +function RefreshConfig() + for _, match in ipairs(FindPatterns("Main.cfg", "(%w*)%s*=%s*\"?([^\"%s]*)\"?")) do + GameConfig[match[1]] = match[2] + end +end + +RefreshConfig() \ No newline at end of file diff --git a/scripts/common/globals.lua b/scripts/common/globals.lua new file mode 100644 index 0000000..b3fbf1a --- /dev/null +++ b/scripts/common/globals.lua @@ -0,0 +1,2 @@ +---Drewol, what are you doing? Why is there no game.LOGGER_DEBUG? +game.LOGGER_DEBUG = 0 diff --git a/scripts/common/json.lua b/scripts/common/json.lua new file mode 100644 index 0000000..d008bf7 --- /dev/null +++ b/scripts/common/json.lua @@ -0,0 +1,400 @@ +-- +-- json.lua +-- +-- Copyright (c) 2019 rxi +-- +-- Permission is hereby granted, free of charge, to any person obtaining a copy of +-- this software and associated documentation files (the "Software"), to deal in +-- the Software without restriction, including without limitation the rights to +-- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +-- of the Software, and to permit persons to whom the Software is furnished to do +-- so, subject to the following conditions: +-- +-- The above copyright notice and this permission notice shall be included in all +-- copies or substantial portions of the Software. +-- +-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +-- SOFTWARE. +-- + +local json = { _version = "0.1.1" } + +------------------------------------------------------------------------------- +-- Encode +------------------------------------------------------------------------------- + +local encode + +local escape_char_map = { + [ "\\" ] = "\\\\", + [ "\"" ] = "\\\"", + [ "\b" ] = "\\b", + [ "\f" ] = "\\f", + [ "\n" ] = "\\n", + [ "\r" ] = "\\r", + [ "\t" ] = "\\t", +} + +local escape_char_map_inv = { [ "\\/" ] = "/" } +for k, v in pairs(escape_char_map) do + escape_char_map_inv[v] = k +end + + +local function escape_char(c) + return escape_char_map[c] or string.format("\\u%04x", c:byte()) +end + + +local function encode_nil(val) + return "null" +end + + +local function encode_table(val, stack) + local res = {} + stack = stack or {} + + -- Circular reference? + if stack[val] then error("circular reference") end + + stack[val] = true + + if rawget(val, 1) ~= nil or next(val) == nil then + -- Treat as array -- check keys are valid and it is not sparse + local n = 0 + for k in pairs(val) do + if type(k) ~= "number" then + error("invalid table: mixed or invalid key types") + end + n = n + 1 + end + if n ~= #val then + error("invalid table: sparse array") + end + -- Encode + for i, v in ipairs(val) do + table.insert(res, encode(v, stack)) + end + stack[val] = nil + return "[" .. table.concat(res, ",") .. "]" + + else + -- Treat as an object + for k, v in pairs(val) do + if type(k) ~= "string" then + error("invalid table: mixed or invalid key types") + end + table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) + end + stack[val] = nil + return "{" .. table.concat(res, ",") .. "}" + end +end + + +local function encode_string(val) + return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' +end + + +local function encode_number(val) + -- Check for NaN, -inf and inf + if val ~= val or val <= -math.huge or val >= math.huge then + error("unexpected number value '" .. tostring(val) .. "'") + end + return string.format("%.14g", val) +end + + +local type_func_map = { + [ "nil" ] = encode_nil, + [ "table" ] = encode_table, + [ "string" ] = encode_string, + [ "number" ] = encode_number, + [ "boolean" ] = tostring, +} + + +encode = function(val, stack) + local t = type(val) + local f = type_func_map[t] + if f then + return f(val, stack) + end + error("unexpected type '" .. t .. "'") +end + + +function json.encode(val) + return ( encode(val) ) +end + + +------------------------------------------------------------------------------- +-- Decode +------------------------------------------------------------------------------- + +local parse + +local function create_set(...) + local res = {} + for i = 1, select("#", ...) do + res[ select(i, ...) ] = true + end + return res +end + +local space_chars = create_set(" ", "\t", "\r", "\n") +local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") +local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") +local literals = create_set("true", "false", "null") + +local literal_map = { + [ "true" ] = true, + [ "false" ] = false, + [ "null" ] = nil, +} + + +local function next_char(str, idx, set, negate) + for i = idx, #str do + if set[str:sub(i, i)] ~= negate then + return i + end + end + return #str + 1 +end + + +local function decode_error(str, idx, msg) + local line_count = 1 + local col_count = 1 + for i = 1, idx - 1 do + col_count = col_count + 1 + if str:sub(i, i) == "\n" then + line_count = line_count + 1 + col_count = 1 + end + end + error( string.format("%s at line %d col %d", msg, line_count, col_count) ) +end + + +local function codepoint_to_utf8(n) + -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa + local f = math.floor + if n <= 0x7f then + return string.char(n) + elseif n <= 0x7ff then + return string.char(f(n / 64) + 192, n % 64 + 128) + elseif n <= 0xffff then + return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) + elseif n <= 0x10ffff then + return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, + f(n % 4096 / 64) + 128, n % 64 + 128) + end + error( string.format("invalid unicode codepoint '%x'", n) ) +end + + +local function parse_unicode_escape(s) + local n1 = tonumber( s:sub(3, 6), 16 ) + local n2 = tonumber( s:sub(9, 12), 16 ) + -- Surrogate pair? + if n2 then + return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) + else + return codepoint_to_utf8(n1) + end +end + + +local function parse_string(str, i) + local has_unicode_escape = false + local has_surrogate_escape = false + local has_escape = false + local last + for j = i + 1, #str do + local x = str:byte(j) + + if x < 32 then + decode_error(str, j, "control character in string") + end + + if last == 92 then -- "\\" (escape char) + if x == 117 then -- "u" (unicode escape sequence) + local hex = str:sub(j + 1, j + 5) + if not hex:find("%x%x%x%x") then + decode_error(str, j, "invalid unicode escape in string") + end + if hex:find("^[dD][89aAbB]") then + has_surrogate_escape = true + else + has_unicode_escape = true + end + else + local c = string.char(x) + if not escape_chars[c] then + decode_error(str, j, "invalid escape char '" .. c .. "' in string") + end + has_escape = true + end + last = nil + + elseif x == 34 then -- '"' (end of string) + local s = str:sub(i + 1, j - 1) + if has_surrogate_escape then + s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape) + end + if has_unicode_escape then + s = s:gsub("\\u....", parse_unicode_escape) + end + if has_escape then + s = s:gsub("\\.", escape_char_map_inv) + end + return s, j + 1 + + else + last = x + end + end + decode_error(str, i, "expected closing quote for string") +end + + +local function parse_number(str, i) + local x = next_char(str, i, delim_chars) + local s = str:sub(i, x - 1) + local n = tonumber(s) + if not n then + decode_error(str, i, "invalid number '" .. s .. "'") + end + return n, x +end + + +local function parse_literal(str, i) + local x = next_char(str, i, delim_chars) + local word = str:sub(i, x - 1) + if not literals[word] then + decode_error(str, i, "invalid literal '" .. word .. "'") + end + return literal_map[word], x +end + + +local function parse_array(str, i) + local res = {} + local n = 1 + i = i + 1 + while 1 do + local x + i = next_char(str, i, space_chars, true) + -- Empty / end of array? + if str:sub(i, i) == "]" then + i = i + 1 + break + end + -- Read token + x, i = parse(str, i) + res[n] = x + n = n + 1 + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "]" then break end + if chr ~= "," then decode_error(str, i, "expected ']' or ','") end + end + return res, i +end + + +local function parse_object(str, i) + local res = {} + i = i + 1 + while 1 do + local key, val + i = next_char(str, i, space_chars, true) + -- Empty / end of object? + if str:sub(i, i) == "}" then + i = i + 1 + break + end + -- Read key + if str:sub(i, i) ~= '"' then + decode_error(str, i, "expected string for key") + end + key, i = parse(str, i) + -- Read ':' delimiter + i = next_char(str, i, space_chars, true) + if str:sub(i, i) ~= ":" then + decode_error(str, i, "expected ':' after key") + end + i = next_char(str, i + 1, space_chars, true) + -- Read value + val, i = parse(str, i) + -- Set + res[key] = val + -- Next token + i = next_char(str, i, space_chars, true) + local chr = str:sub(i, i) + i = i + 1 + if chr == "}" then break end + if chr ~= "," then decode_error(str, i, "expected '}' or ','") end + end + return res, i +end + + +local char_func_map = { + [ '"' ] = parse_string, + [ "0" ] = parse_number, + [ "1" ] = parse_number, + [ "2" ] = parse_number, + [ "3" ] = parse_number, + [ "4" ] = parse_number, + [ "5" ] = parse_number, + [ "6" ] = parse_number, + [ "7" ] = parse_number, + [ "8" ] = parse_number, + [ "9" ] = parse_number, + [ "-" ] = parse_number, + [ "t" ] = parse_literal, + [ "f" ] = parse_literal, + [ "n" ] = parse_literal, + [ "[" ] = parse_array, + [ "{" ] = parse_object, +} + + +parse = function(str, idx) + local chr = str:sub(idx, idx) + local f = char_func_map[chr] + if f then + return f(str, idx) + end + decode_error(str, idx, "unexpected character '" .. chr .. "'") +end + + +function json.decode(str) + if type(str) ~= "string" then + error("expected argument of type string, got " .. type(str)) + end + local res, idx = parse(str, next_char(str, 1, space_chars, true)) + idx = next_char(str, idx, space_chars, true) + if idx <= #str then + decode_error(str, idx, "trailing garbage") + end + return res +end + + +return json diff --git a/scripts/common/sound.lua b/scripts/common/sound.lua new file mode 100644 index 0000000..e14cc17 --- /dev/null +++ b/scripts/common/sound.lua @@ -0,0 +1,11 @@ +local stopMusic = function () + local musicPlaying = game.GetSkinSetting('_musicPlaying'); + if musicPlaying and musicPlaying ~= '' then + game.StopSample(musicPlaying); + game.SetSkinSetting("_musicPlaying", "") + end +end + +return { + stopMusic = stopMusic +} \ No newline at end of file diff --git a/scripts/common/util.lua b/scripts/common/util.lua new file mode 100644 index 0000000..039a8bf --- /dev/null +++ b/scripts/common/util.lua @@ -0,0 +1,89 @@ +local function split(s, delimiter) + result = {}; + for match in (s..delimiter):gmatch("(.-)"..delimiter) do + table.insert(result, match); + end + return result; +end + +local function filter(tableIn, predicate) + local out = {} + for _, val in ipairs(tableIn) do + if predicate(val) then + table.insert(out, val) + end + end + return out +end + +local function clamp(x, min, max) + if x < min then + x = min + end + if x > max then + x = max + end + + return x +end + +local function round(num) + return num + (2^52 + 2^51) - (2^52 + 2^51) +end + +local function sign(x) + return ( + (x > 0) and 1 + or + (x < 0) and -1 + or + 0 + ) +end + +local function roundToZero(x) + if x < 0 then + return math.ceil(x) + elseif x > 0 then + return math.floor(x) + else + return 0 + end +end + +local function areaOverlap(x, y, areaX, areaY, areaW, areaH) + return x > areaX and y > areaY and x < areaX + areaW and y < areaY + areaH +end + +local function lerp(x, x0, y0, x1, y1) + return y0 + (x - x0) * (y1 - y0) / (x1 - x0) +end + +--modulo operation for index value +local function modIndex(index, mod) + return (index - 1) % mod + 1 +end + +local function firstAlphaNum(s) + for i = 1, string.len(s) do + local byte = string.byte(s, i); + if ((byte >= 65 and byte <= 90) or (byte >= 97 and byte <= 122) or (byte >= 48 and byte <= 57)) then + return string.sub(s, i, i); + end + end + + return ''; +end + +return { + split = split, + filter = filter, + clamp = clamp, + round = round, + sign = sign, + roundToZero = roundToZero, + areaOverlap = areaOverlap, + lerp = lerp, + modIndex = modIndex, + firstAlphaNum = firstAlphaNum, +} diff --git a/scripts/common/version.lua b/scripts/common/version.lua index d4f8e72..b8339de 100644 --- a/scripts/common/version.lua +++ b/scripts/common/version.lua @@ -1,9 +1,21 @@ +local MAJOR = 0 +local MINOR = 2 +local PATCH = 2 --- I'm following https://semver.org/ --- If you have issues with it, contact FajsiEx#6106 +local function getLongVersion() + return "USC:E:G:S:" .. MAJOR .. MINOR .. PATCH +end + +---Get version string +---@return string +local function getVersion() + return table.concat({MAJOR, MINOR, PATCH}, ".") +end return { - MAJOR = "?", - MINOR = "?", - PATCH = "?" + MAJOR = MAJOR, + MINOR = MINOR, + PATCH = PATCH, + getLongVersion = getLongVersion, + getVersion = getVersion } \ No newline at end of file diff --git a/scripts/components/background.lua b/scripts/components/background.lua index b100a7a..3f5c9be 100644 --- a/scripts/components/background.lua +++ b/scripts/components/background.lua @@ -1,5 +1,3 @@ - - local resx, resy = game.GetResolution() local desw, desh = 1080,1920; local scale = 1; diff --git a/scripts/components/diff_rectangle.lua b/scripts/components/diff_rectangle.lua index b32c19d..d1e249d 100644 --- a/scripts/components/diff_rectangle.lua +++ b/scripts/components/diff_rectangle.lua @@ -15,6 +15,7 @@ local difficultyLabelTexts = { "ADV", "EXH", "MXM", + "INF", "GRV", "HVN", "VVD" @@ -29,7 +30,7 @@ function render(deltatime, x, y, scale, diff, level) gfx.BeginPath(); gfx.ImageRect(0, 0, 140, 31 , - difficultyLabelImages[diff+1] or + difficultyLabelImages[diff] or difficultyLabelImages[4], 1, 0); @@ -42,7 +43,7 @@ function render(deltatime, x, y, scale, diff, level) gfx.FontSize(22) gfx.Scale(1.2,1); -- Make the diff text more W I D E gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.Text(difficultyLabelTexts[diff+1], 18, 17); + gfx.Text(difficultyLabelTexts[diff], 18, 17); diff --git a/scripts/components/footer.lua b/scripts/components/footer.lua index a67ba6e..89660ef 100644 --- a/scripts/components/footer.lua +++ b/scripts/components/footer.lua @@ -1,91 +1,67 @@ +local version = require("common.version") +local Dim = require("common.dimensions") -local version = require('common.version') - -local resx, resy = game.GetResolution() -local desw, desh = 1080,1920; -local scale = 1; - -local BAR_ALPHA = 191; +local BAR_ALPHA = 191 local FOOTER_HEIGHT = 128 -local footerY = desh - FOOTER_HEIGHT; +local footerY = Dim.design.height - FOOTER_HEIGHT -- Images -local footerRightImage = gfx.CreateSkinImage("components/bars/footer_right.png", 0); +local footerRightImage = gfx.CreateSkinImage("components/bars/footer_right.png", 0) -- Animation related -local entryTransitionScale = 0; -local entryTransitionFooterYOffset = 0; +local entryTransitionScale = 0 +local entryTransitionFooterYOffset = 0 -local legend = { - { - control = 'START', - text = 'Confirm selection' - }, - { - control = 'KNOB', - text = 'Scroll' - }, -} +local legend = {{control = "START", text = "Confirm selection"}, {control = "KNOB", text = "Scroll"}} -local set = function () - -end +local function set() end -function resetLayoutInformation() - resx, resy = game.GetResolution() - desw = 1080 - desh = 1920 - scale = resx / desw -end +local function drawFooter() + gfx.BeginPath() + gfx.FillColor(0, 0, 0, BAR_ALPHA) + gfx.Rect(0, footerY, Dim.design.width, FOOTER_HEIGHT) + gfx.Fill() -local drawFooter = function () - gfx.BeginPath(); - gfx.FillColor(0,0,0,BAR_ALPHA); - gfx.Rect(0,footerY,desw, FOOTER_HEIGHT); - gfx.Fill(); - - - gfx.BeginPath(); - gfx.ImageRect(desw-275, footerY-25, 328*0.85, 188*0.85, footerRightImage, 1, 0); + gfx.BeginPath() + gfx.ImageRect(Dim.design.width - 275, footerY - 25, 328 * 0.85, 188 * 0.85, footerRightImage, 1, 0) - gfx.BeginPath(); - gfx.LoadSkinFont("Digital-Serial-Bold.ttf"); + gfx.BeginPath() + gfx.LoadSkinFont("Digital-Serial-Bold.ttf") gfx.FontSize(20) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) - gfx.FillColor(255, 255, 255, 255); - gfx.Text('EXPERIMENTALGEAR ' .. version.MAJOR .. version.MINOR .. version.PATCH .. " < Dev Build RealFD Branch >", 8, 1895); + gfx.FillColor(255, 255, 255, 255) + gfx.Text("EXPERIMENTALGEAR " .. version.MAJOR .. "." .. version.MINOR .. "." .. version.PATCH .. "", 8, 1895) end -local progressTransitions = function (deltaTime) - entryTransitionScale = entryTransitionScale + deltaTime / 0.3; - if (entryTransitionScale > 1) then - entryTransitionScale = 1; - end +local function progressTransitions(deltaTime) + entryTransitionScale = entryTransitionScale + deltaTime / 0.3 + if (entryTransitionScale > 1) then entryTransitionScale = 1 end - entryTransitionFooterYOffset = FOOTER_HEIGHT*(1-entryTransitionScale) - footerY = desh-FOOTER_HEIGHT+entryTransitionFooterYOffset; + entryTransitionFooterYOffset = FOOTER_HEIGHT * (1 - entryTransitionScale) + footerY = Dim.design.height - FOOTER_HEIGHT + entryTransitionFooterYOffset end -local draw = function (deltaTime, params) - if (params) then - if params.noEnterTransition then - entryTransitionScale = 1; - end +local function draw(deltaTime, params) + if params and params.noEnterTransition then + entryTransitionScale = 1 end gfx.Save() - - gfx.LoadSkinFont("NotoSans-Regular.ttf"); + gfx.ResetTransform() - drawFooter(); + Dim.updateResolution() + + Dim.transformToScreenSpace() + + gfx.LoadSkinFont("NotoSans-Regular.ttf") + + drawFooter() + + progressTransitions(deltaTime) - progressTransitions(deltaTime); gfx.Restore() end -return { - set = set, - draw = draw -}; \ No newline at end of file +return {set = set, draw = draw} diff --git a/scripts/components/headers/challengeSelectHeader.lua b/scripts/components/headers/challengeSelectHeader.lua index 9e73b3b..28599c1 100644 --- a/scripts/components/headers/challengeSelectHeader.lua +++ b/scripts/components/headers/challengeSelectHeader.lua @@ -1,34 +1,28 @@ -local desw = 1080; -local desh = 1920; -local scale = 1; +local Dim = require("common.dimensions") -local BAR_ALPHA = 191; +local BAR_ALPHA = 191 local HEADER_HEIGHT = 100 -local headerY = 0; -local animationHeaderGlowScale = 0; -local animationHeaderGlowAlpha = 0; +local animationHeaderGlowScale = 0 +local animationHeaderGlowAlpha = 0 -- Images local headerTitleImage = gfx.CreateSkinImage("challenge_select/skill_analyzer.png", gfx.IMAGE_GENERATE_MIPMAPS) -local drawHeader = function () - gfx.BeginPath(); - gfx.FillColor(0,0,0,BAR_ALPHA); - gfx.Rect(0,0,desw, HEADER_HEIGHT); - gfx.Fill(); +local function drawHeader() + gfx.BeginPath() + gfx.FillColor(0, 0, 0, BAR_ALPHA) + gfx.Rect(0, 0, Dim.design.width, HEADER_HEIGHT) + gfx.Fill() gfx.ClosePath() local headerImageWidth, headerImageHeight = gfx.ImageSize(headerTitleImage) - gfx.ImageRect( - (desw - headerImageWidth) / 2, (HEADER_HEIGHT - headerImageHeight) / 2 - 12, -- asset png is not centered on the y axis - headerImageWidth, headerImageHeight, - headerTitleImage, 1, 0 - ) + gfx.ImageRect((Dim.design.width - headerImageWidth) / 2, (HEADER_HEIGHT - headerImageHeight) / 2 - 12, -- asset png is not centered on the y axis + headerImageWidth, headerImageHeight, headerTitleImage, 1, 0) end -local progressTransitions = function (deltatime) +local function progressTransitions(deltatime) -- HEADER GLOW ANIMATION if animationHeaderGlowScale < 1 then animationHeaderGlowScale = animationHeaderGlowScale + deltatime / 1 -- transition should last for that time in seconds @@ -37,24 +31,29 @@ local progressTransitions = function (deltatime) end if animationHeaderGlowScale < 0.5 then - animationHeaderGlowAlpha = animationHeaderGlowScale * 2; + animationHeaderGlowAlpha = animationHeaderGlowScale * 2 else - animationHeaderGlowAlpha = 1-((animationHeaderGlowScale-0.5) * 2); + animationHeaderGlowAlpha = 1 - ((animationHeaderGlowScale - 0.5) * 2) end - animationHeaderGlowAlpha = animationHeaderGlowAlpha*0.4 + animationHeaderGlowAlpha = animationHeaderGlowAlpha * 0.4 end -local draw = function (deltatime) +local function draw(deltatime) gfx.Save() - - gfx.LoadSkinFont("NotoSans-Regular.ttf"); - drawHeader(); + gfx.ResetTransform() + + Dim.updateResolution() + + Dim.transformToScreenSpace() + + gfx.LoadSkinFont("NotoSans-Regular.ttf") + + drawHeader() + + progressTransitions(deltatime) - --progressTransitions(deltatime); gfx.Restore() end -return { - draw = draw -}; \ No newline at end of file +return {draw = draw} diff --git a/scripts/components/headers/songSelectHeader.lua b/scripts/components/headers/songSelectHeader.lua index f51e216..9e025b9 100644 --- a/scripts/components/headers/songSelectHeader.lua +++ b/scripts/components/headers/songSelectHeader.lua @@ -1,35 +1,28 @@ +local Dim = require("common.dimensions") - -local resx, resy = game.GetResolution(); -local desw = 1080; -local desh = 1920; -local scale = 1; - -local BAR_ALPHA = 191; +local BAR_ALPHA = 191 local HEADER_HEIGHT = 100 -local headerY = 0; -local animationHeaderGlowScale = 0; -local animationHeaderGlowAlpha = 0; +local animationHeaderGlowScale = 0 +local animationHeaderGlowAlpha = 0 -- Images local headerTitleImage = gfx.CreateSkinImage("song_select/header/title.png", 1) local headerGlowTitleImage = gfx.CreateSkinImage("song_select/header/title_glow.png", 1) - -local drawHeader = function () - gfx.BeginPath(); - gfx.FillColor(0,0,0,BAR_ALPHA); - gfx.Rect(0,0,desw, HEADER_HEIGHT); - gfx.Fill(); +local drawHeader = function() + gfx.BeginPath() + gfx.FillColor(0, 0, 0, BAR_ALPHA) + gfx.Rect(0, 0, Dim.design.width, HEADER_HEIGHT) + gfx.Fill() gfx.ClosePath() - gfx.ImageRect(42, 14, 423*0.85, 80*0.85, headerTitleImage, 1, 0) - gfx.ImageRect(42, 14, 423*0.85, 80*0.85, headerGlowTitleImage, animationHeaderGlowAlpha, 0) + gfx.ImageRect(42, 14, 423 * 0.85, 80 * 0.85, headerTitleImage, 1, 0) + gfx.ImageRect(42, 14, 423 * 0.85, 80 * 0.85, headerGlowTitleImage, animationHeaderGlowAlpha, 0) end -local progressTransitions = function (deltatime) +local progressTransitions = function(deltatime) -- HEADER GLOW ANIMATION if animationHeaderGlowScale < 1 then animationHeaderGlowScale = animationHeaderGlowScale + deltatime / 1 -- transition should last for that time in seconds @@ -38,24 +31,29 @@ local progressTransitions = function (deltatime) end if animationHeaderGlowScale < 0.5 then - animationHeaderGlowAlpha = animationHeaderGlowScale * 2; + animationHeaderGlowAlpha = animationHeaderGlowScale * 2 else - animationHeaderGlowAlpha = 1-((animationHeaderGlowScale-0.5) * 2); + animationHeaderGlowAlpha = 1 - ((animationHeaderGlowScale - 0.5) * 2) end - animationHeaderGlowAlpha = animationHeaderGlowAlpha*0.4 + animationHeaderGlowAlpha = animationHeaderGlowAlpha * 0.4 end -local draw = function (deltatime) +local draw = function(deltatime) gfx.Save() - - gfx.LoadSkinFont("NotoSans-Regular.ttf"); - drawHeader(); + gfx.ResetTransform() + + Dim.updateResolution() + + Dim.transformToScreenSpace() + + gfx.LoadSkinFont("NotoSans-Regular.ttf") + + drawHeader() + + progressTransitions(deltatime) - progressTransitions(deltatime); gfx.Restore() end -return { - draw = draw -}; \ No newline at end of file +return {draw = draw} diff --git a/scripts/components/numbers.lua b/scripts/components/numbers.lua new file mode 100644 index 0000000..b7e4d4e --- /dev/null +++ b/scripts/components/numbers.lua @@ -0,0 +1,39 @@ +function load_number_image(path) + local images = {} + for i = 0, 9 do + images[i + 1] = gfx.CreateSkinImage(string.format("%s/%d.png", path, i), 0) + end + return images +end + +function draw_number(x, y, alpha, num, digits, images, is_dim, scale, kern, dim_first_zero) + scale = scale or 1 + kern = kern or 1 + dim_first_zero = dim_first_zero == nil and true or dim_first_zero + + local tw, th = gfx.ImageSize(images[1]) + tw = tw * scale + th = th * scale + x = x + (tw * (digits - 1)) / 2 + y = y - th / 2 + + for i = 1, digits do + local mul = 10 ^ (i - 1) + local digit = math.floor(num / mul) % 10 + local a = alpha + + if is_dim and num < mul and not (not dim_first_zero and i <= 1) then + a = 0.4 + end + + gfx.BeginPath() + gfx.ImageRect(x, y, tw, th, images[digit + 1], a, 0) + + x = x - (tw * kern) + end +end + +return { + load_number_image = load_number_image, + draw_number = draw_number +} \ No newline at end of file diff --git a/scripts/components/pager/containerfield.lua b/scripts/components/pager/containerfield.lua new file mode 100644 index 0000000..49a1426 --- /dev/null +++ b/scripts/components/pager/containerfield.lua @@ -0,0 +1,68 @@ +require("common.class") +local Field = require("components.pager.field") + +---@class ContainerField: Field +---@field content Field[] +local ContainerField = { + __tostring = function() return "ContainerField" end, +} + +---Create a new ContainerField instance +---@param o? table # initial parameters +---@return ContainerField +function ContainerField.new(o) + o = o or {} + + --set instance members + + o.content = o.content or {} + + local this = CreateInstance(ContainerField, o, Field) + + this:refreshFields() + + return this +end + +---Add content to container +---@param field Field +function ContainerField:addField(field) + field.parent = self + table.insert(self.content, field) +end + +---Refresh content parameters +function ContainerField:refreshFields() + for _, child in ipairs(self.content) do + child.parent = self + end +end + +---@param deltaTime number # frametime in seconds +function ContainerField:drawBackground(deltaTime) end + +---@param deltaTime number # frametime in seconds +function ContainerField:drawContent(deltaTime) + for _, child in ipairs(self.content) do + child:render(deltaTime) + end +end + +---@param deltaTime number # frametime in seconds +function ContainerField:drawForeground(deltaTime) end + +---@param deltaTime number # frametime in seconds +function ContainerField:render(deltaTime) + gfx.Save() + + gfx.Translate(self.posX, self.posY) + gfx.Scissor(0, 0, self.aabbW, self.aabbH) + + self:drawBackground(deltaTime) + self:drawContent(deltaTime) + self:drawForeground(deltaTime) + + gfx.Restore() +end + +return ContainerField diff --git a/scripts/components/pager/field.lua b/scripts/components/pager/field.lua new file mode 100644 index 0000000..8e5ab0d --- /dev/null +++ b/scripts/components/pager/field.lua @@ -0,0 +1,113 @@ +require("common.class") + +---@class Field +---@field parent Page|ContainerField +---@field posX number +---@field posY number +---@field aabbW number +---@field aabbH number +local Field = { + __tostring = function() return "Field" end, +} + +---Create a new Field instance +---@param o? table # initial parameters +---@return Field +function Field.new(o) + o = o or {} + + --set instance members + + o.parent = o.parent or nil + o.posX = o.posX or 0 + o.posY = o.posY or 0 + o.aabbW = o.aabbW or 0 + o.aabbH = o.aabbH or 0 + + return CreateInstance(Field, o) +end + +---Get the containing top-level parent page +---@return Field|Page +function Field:getParentPage() + if self.parent and self.parent.getParentPage then + return self.parent:getParentPage() + else + return self.parent + end +end + +---@param obj? any # message object for the field +function Field:activate(obj) end + +---@param obj? any # message object for the field +function Field:focus(obj) end + +---@param obj? any # message object for the field +function Field:deactivate(obj) end + +---@param button integer # options are under the `game` table prefixed with `BUTTON` +---@return boolean # true if further button input processing should be stopped, otherwise false +function Field:handleButtonInput(button) + return false +end + +---@param knob integer # `0` = Left, `1` = Right +---@param delta number # in radians, `-2*pi` to `0` (turning CCW) and `0` to `2*pi` (turning CW) +---@return boolean # true if further button input processing should be stopped, otherwise false +function Field:handleKnobInput(knob, delta) + return false +end + +---@param deltaTime number # frametime in seconds +function Field:drawContent(deltaTime) + -- dummy field content + + gfx.ResetScissor() + + local offX = -50 + local offY = -50 + local aabbW = 100 + local aabbH = 100 + + gfx.BeginPath() + gfx.FillColor(255, 0, 128, 192) + gfx.StrokeColor(0, 0, 0) + gfx.StrokeWidth(2) + gfx.Rect(offX, offY, aabbW, aabbH) + gfx.Fill() + gfx.Stroke() + + gfx.BeginPath() + gfx.MoveTo(offX, 0) + gfx.LineTo(offX + aabbW, 0) + gfx.MoveTo(0, offY) + gfx.LineTo(0, offY + aabbH) + gfx.StrokeColor(0, 0, 0, 64) + gfx.StrokeWidth(2) + gfx.Stroke() + + local fontSize = 18 + local fontMargin = 4 + gfx.BeginPath() + gfx.FontSize(fontSize) + gfx.LoadSkinFont("dfmarugoth.ttf") + gfx.FillColor(0, 0, 0) + gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_MIDDLE) + gfx.Text("TEXTURE", 0, -fontSize / 2 - fontMargin) + gfx.Text("MISSING", 0, fontSize / 2 + fontMargin) +end + +---@param deltaTime number # frametime in seconds +function Field:render(deltaTime) + gfx.Save() + + gfx.Translate(self.posX, self.posY) + gfx.Scissor(0, 0, self.aabbW, self.aabbH) + + self:drawContent(deltaTime) + + gfx.Restore() +end + +return Field diff --git a/scripts/components/pager/linkfield.lua b/scripts/components/pager/linkfield.lua new file mode 100644 index 0000000..107d9a1 --- /dev/null +++ b/scripts/components/pager/linkfield.lua @@ -0,0 +1,44 @@ +require("common.class") +local Field = require("components.pager.field") + +---@class LinkField: Field +---@field link Page +local LinkField = { + __tostring = function() return "LinkField" end +} + +---Create a new LinkField instance +---@param o? table # initial parameters +---@return LinkField +function LinkField.new(o) + o = o or {} + + o.link = o.link or nil + + return CreateInstance(LinkField, o, Field) +end + +---@param button integer # options are under the `game` table prefixed with `BUTTON` +---@return boolean # true if further button input processing should be stopped, otherwise false +function LinkField:handleButtonInput(button) + if not self.link then + game.Log(tostring(self) .. " does not have a valid link", game.LOGGER_ERROR) + return false + end + + if button == game.BUTTON_STA then + local parentPage = self:getParentPage() + if parentPage and parentPage.viewHandler then + game.Log(tostring(self) .. " viewHandler:navigate(" .. tostring(self.link) .. ") called", game.LOGGER_INFO) + parentPage.viewHandler:navigate(self.link) + return true + else + local target = (parentPage and parentPage.viewHandler or "PageView") + game.Log(tostring(self) .. " can't access " .. tostring(target) .. " instance", game.LOGGER_ERROR) + end + end + + return false +end + +return LinkField diff --git a/scripts/components/pager/page.lua b/scripts/components/pager/page.lua new file mode 100644 index 0000000..8496f0f --- /dev/null +++ b/scripts/components/pager/page.lua @@ -0,0 +1,72 @@ +require("common.globals") +require("common.class") + +---@class Page +---@field content Field[] +---@field viewHandler nil|PageView +local Page = { + __tostring = function() return "Page" end, +} + +---Create a new Page instance +---@param o? table # initial parameters +---@return Page +function Page.new(o) + o = o or {} + + --set instance members + + o.content = o.content or {} + o.viewHandler = o.viewHandler or nil + + return CreateInstance(Page, o) +end + +---Add field to page +---@param field Field +function Page:addField(field) + field.parent = self + table.insert(self.content, field) +end + +---Refresh content values +function Page:refreshFields() + for _, field in ipairs(self.content) do + field.parent = self + end +end + +---@param button integer # options are under the `game` table prefixed with `BUTTON` +function Page:handleButtonInput(button) + if button == game.BUTTON_BCK then + if self.viewHandler then + self.viewHandler:back() + end + end +end + +---@param knob integer # `0` = Left, `1` = Right +---@param delta number # in radians, `-2*pi` to `0` (turning CCW) and `0` to `2*pi` (turning CW) +function Page:handleKnobInput(knob, delta) end + +---@param deltaTime number # frametime in seconds +function Page:drawBackground(deltaTime) end + +---@param deltaTime number # frametime in seconds +function Page:drawContent(deltaTime) + for _, child in ipairs(self.content) do + child:render(deltaTime) + end +end + +---@param deltaTime number # frametime in seconds +function Page:drawForeground(deltaTime) end + +---@param deltaTime number # frametime in seconds +function Page:render(deltaTime) + self:drawBackground(deltaTime) + self:drawContent(deltaTime) + self:drawForeground(deltaTime) +end + +return Page diff --git a/scripts/components/pager/pageview.lua b/scripts/components/pager/pageview.lua new file mode 100644 index 0000000..4fa2725 --- /dev/null +++ b/scripts/components/pager/pageview.lua @@ -0,0 +1,84 @@ +require("common.class") + +---@class PageView +---@field pageStack Page[] +local PageView = { + __tostring = function() return "PageView" end +} + +local function pushStack(t, o) + table.insert(t, 1, o) +end + +local function popStack(t) + return table.remove(t, 1) +end + +---Create a new PageView instance +---@param rootPage Page +---@return PageView +function PageView.new(rootPage) + local o = {} + + --set viewHandler as this instance for rootPage + + rootPage.viewHandler = o + + --set instance members + + o.pageStack = {} + pushStack(o.pageStack, rootPage) + + return CreateInstance(PageView, o) +end + +---Get page from pageStack +---@param index? integer # defaults to 1 (top of the stack) +---@return Page +function PageView:get(index) + index = index or 1 + + return self.pageStack[index] +end + +---Navigate to page +---@param page Page # page to put on top of the pageStack +function PageView:navigate(page) + page.viewHandler = self + pushStack(self.pageStack, page) +end + +---Replace the current pageStack with a new root page +---@param rootPage Page +function PageView:replace(rootPage) + self:clear() + self:navigate(rootPage) +end + +---Navigate to the previous page +function PageView:back() + if not self:get() then + game.Log(self .. ":back() : pageStack empty, cannot go back", game.LOGGER_WARNING) + return + end + + self:get().viewHandler = nil + popStack(self.pageStack) +end + +---Clear the pageStack +function PageView:clear() + --clear pageStack + while self:get() do + self:back() + end +end + +---@param deltaTime number # frametime in seconds +function PageView:render(deltaTime) + if self:get() then + self:get():render(deltaTime) + end +end + +return PageView diff --git a/scripts/downloadscreen.lua b/scripts/downloadscreen.lua index dda8242..f9d687c 100644 --- a/scripts/downloadscreen.lua +++ b/scripts/downloadscreen.lua @@ -1,10 +1,7 @@ -json = require "json" +json = require "common.json" local header = {} header["user-agent"] = "unnamed_sdvx_clone" -local Dim = require("common.dimensions") -local Wallpaper = require("components.wallpaper") - local jacketFallback = gfx.CreateSkinImage("song_select/loading.png", 0) local diffColors = {{50,50,127}, {50,127,50}, {127,50,50}, {127, 50, 127}} local entryW = 770 @@ -48,7 +45,7 @@ function addsong(song) table.insert(songs, song) end local yOffset = 0 -local backgroundImage = require("components.background") +local backgroundImage = gfx.CreateSkinImage("bg.png", 1); dlcache = io.open(cachepath, "r") if dlcache then @@ -222,12 +219,8 @@ function render_info() end function render(deltaTime) - Dim.updateResolution() - Wallpaper.render() - - Dim.transformToDesignSpace() - backgroundImage.draw(deltaTime) - + gfx.BeginPath() + gfx.ImageRect(0, 0, resX, resY, backgroundImage, 1, 0); gfx.LoadSkinFont("NotoSans-Regular.ttf"); displayCursorPosX = displayCursorPosX - (displayCursorPosX - cursorPosX) * deltaTime * 10 displayCursorPosY = displayCursorPosY - (displayCursorPosY - cursorPosY) * deltaTime * 10 diff --git a/scripts/gameplay.lua b/scripts/gameplay.lua index 3a9ae51..ab78608 100644 --- a/scripts/gameplay.lua +++ b/scripts/gameplay.lua @@ -1,5 +1,11 @@ local VolforceWindow = require('components.volforceWindow') +local Dimensions = require 'common.dimensions'; + +do + local resx, resy = game.GetResolution(); + Dimensions.updateResolution(resx / resy); +end local Banner = require('gameplay.banner') local CritLine = require('gameplay.crit_line') @@ -11,31 +17,13 @@ local Gauge = require('gameplay.gauge') local Chain = require('gameplay.chain') local LaserAlert = require('gameplay.laser_alert') +local HitFX = require 'gameplay.hitfx' + local TrackEnd = require('gameplay.track_end') -local json = require "json" +local json = require("common.json") --- Window variables -local resX, resY - --- Aspect Ratios -local landscapeWidescreenRatio = 16 / 9 -local landscapeStandardRatio = 4 / 3 -local portraitWidescreenRatio = 9 / 16 - --- Portrait sizes -local fullX, fullY -local desw = 1080 -local desh = 1920 - -local resolutionChange = function(x, y) - resX = x - resY = y - fullX = portraitWidescreenRatio * y - fullY = y - - game.Log('resX:' .. resX .. ' // resY:' .. resY .. ' // fullX:' .. fullX .. ' // fullY:' .. fullY, game.LOGGER_ERROR); -end +local showHitAnims = true; local users = nil @@ -44,11 +32,8 @@ local chain = 0; local score = 0; function render(deltaTime) - -- detect resolution change local resx, resy = game.GetResolution(); - if resx ~= resX or resy ~= resY then - resolutionChange(resx, resy) - end + Dimensions.updateResolution(resx / resy); Banner.render(deltaTime, users, gameplay.user_id); @@ -78,11 +63,11 @@ end function render_crit_base(deltaTime) CritLine.renderBase(deltaTime, gameplay.critLine.x, gameplay.critLine.y, -gameplay.critLine.rotation, gameplay.critLine.cursors); + HitFX.render(deltaTime, gameplay.critLine.x, gameplay.critLine.y, -gameplay.critLine.rotation, gameplay.critLine.cursors); Console.render(deltaTime, gameplay.critLine.x, gameplay.critLine.y, -gameplay.critLine.rotation); end function render_crit_overlay(deltaTime) - end function render_intro(deltaTime) @@ -103,6 +88,9 @@ end function update_score(newScore) score = newScore + if (score == 0) then + maxChain = 0; + end end function update_combo(newCombo) @@ -118,11 +106,18 @@ function near_hit(wasLate) end function button_hit(button, rating, delta) - + if (showHitAnims) then + if (rating == 1) then + HitFX.TriggerAnimation("Near", button + 1) + else + HitFX.TriggerAnimation("Crit", button + 1) + end + end end function laser_slam_hit(slamLength, startPos, endPost, index) - + if (showHitAnims) then + end end function laser_alert(isRight) @@ -153,9 +148,9 @@ end -- Update the users in the scoreboard function score_callback(response) - if response.status ~= 200 then - error() - return + if response.status ~= 200 then + error() + return end local jsondata = json.decode(response.text) users = {} diff --git a/scripts/gameplay/chain.lua b/scripts/gameplay/chain.lua index 47eb90f..1ad9cae 100644 --- a/scripts/gameplay/chain.lua +++ b/scripts/gameplay/chain.lua @@ -1,4 +1,4 @@ -local Numbers = require('common.numbers') +local Numbers = require('components.numbers') local chainLabel = gfx.CreateSkinImage("gameplay/chain/label.png", 0) diff --git a/scripts/gameplay/console.lua b/scripts/gameplay/console.lua index 0cfe8f1..6c5d24f 100644 --- a/scripts/gameplay/console.lua +++ b/scripts/gameplay/console.lua @@ -1,30 +1,18 @@ +local Dimensions = require 'common.dimensions' + local consoleBaseImage = gfx.CreateSkinImage("gameplay/console/base.png", 0) local CONSOLE_W = 1352; local CONSOLE_H = 712; --- Similar to crit line transforms, since the console needs to follow the lane rotation -local setUpTransforms = function (x,y,rotation) - local resx, resy = game.GetResolution() - local desw = 1080 - local desh = 1920 - local scale = resx / desw - - - gfx.Translate(x, y) - gfx.Rotate(rotation) - gfx.Scale(scale,scale) -end - - local render = function (deltaTime, critLineCenterX, critLineCenterY, critLineRotation) local resx, resy = game.GetResolution(); if (resx > resy) then return end - - setUpTransforms( + + Dimensions.setUpTransforms( critLineCenterX, critLineCenterY, critLineRotation diff --git a/scripts/gameplay/crit_line.lua b/scripts/gameplay/crit_line.lua index 7408dd9..0541641 100644 --- a/scripts/gameplay/crit_line.lua +++ b/scripts/gameplay/crit_line.lua @@ -1,5 +1,10 @@ +local Dimensions = require 'common.dimensions' + +local blackGradientImage = gfx.CreateSkinImage('gameplay/crit_line/black_gradient.png', 0) + local baseImage = gfx.CreateSkinImage("gameplay/crit_line/base.png", 0) +local baseImageLandscape = gfx.CreateSkinImage("gameplay/crit_line/base_landscape.png", 0) local textImage = gfx.CreateSkinImage("gameplay/crit_line/text.png", 0) local cursorImage = gfx.CreateSkinImage("gameplay/crit_line/cursor.png", 0); @@ -13,45 +18,26 @@ local cursorGlowTopImages = { gfx.CreateSkinImage("gameplay/crit_line/cursor_glow_top_right.png", 0), } -local CRITBAR_W = 1496 -local CRITBAR_H = 348 - -local scale; +local CRITBAR_W = 1080 +local CRITBAR_H = 251 +local scale = 1; local isLandscape = false; -local setUpTransforms = function (x,y,rotation) - local resx, resy = game.GetResolution(); - isLandscape = resx > resy; - - local desw, desh; - - if (isLandscape) then - desw = 1920; - desh = 1080; - else - desw = 1080; - desh = 1920; - end - - scale = resx / desw - - gfx.Translate(x, y) - gfx.Rotate(rotation) - gfx.Scale(scale,scale) -end - local drawCursors = function (centerX, centerY,cursors) - local cursorW = 598*0.2; - local cursorH = 673*0.2; + local cursorW = 598 * 0.165; + local cursorH = 673 * 0.14; for i = 0, 1, 1 do - gfx.Save(); local cursor = cursors[i]; - gfx.BeginPath(); - gfx.SkewX(cursor.skew) - local cursorX = (cursor.pos *(1/scale) - cursorW/2); - local cursorY = (-cursorH/2); + gfx.Save(); + gfx.BeginPath(); + + local skew = cursor.pos * 0.001; + gfx.SkewX(skew); + + local cursorX = cursor.pos * (1 / scale) - cursorW / 2; + local cursorY = -cursorH / 2; gfx.ImageRect( cursorX, @@ -98,31 +84,28 @@ local drawCursors = function (centerX, centerY,cursors) end local renderBase = function (deltaTime, centerX, centerY, rotation, cursors) - setUpTransforms(centerX, centerY, rotation) + scale, isLandscape = Dimensions.setUpTransforms(centerX, centerY, rotation) gfx.BeginPath() gfx.FillColor(0, 0, 0, 192) - gfx.Rect(-1080/2, 0, 1080, 1080) + gfx.Rect(-9999, 0, 9999 * 2, 1080) gfx.Fill() - gfx.BeginPath(); - gfx.ImageRect( - -CRITBAR_W/2, - -CRITBAR_H/2, - CRITBAR_W, - CRITBAR_H, - baseImage, - 1, - 0 - ); + if (isLandscape) then + gfx.BeginPath(); + gfx.ImageRect(-9999, -CRITBAR_H/2, 9999 * 2, CRITBAR_H, baseImageLandscape, 1, 0); + else + gfx.BeginPath(); + gfx.ImageRect(-CRITBAR_W/2, -CRITBAR_H/2, CRITBAR_W, CRITBAR_H, baseImage, 1, 0); + end drawCursors(centerX, centerY, cursors) - + gfx.ResetTransform() end local renderOverlay = function (deltaTime) - + end return { diff --git a/scripts/gameplay/hitfx.lua b/scripts/gameplay/hitfx.lua new file mode 100644 index 0000000..ec9cd1e --- /dev/null +++ b/scripts/gameplay/hitfx.lua @@ -0,0 +1,94 @@ + +require 'common.globals' + +local Dimensions = require 'common.dimensions' + +local Animation = require 'api.animation' + +local Animations = { + Crit = Animation.new('gameplay/hit_animation_frames/critical_taps', { + centered = true, + }), + + Near = Animation.new('gameplay/hit_animation_frames/near_taps', { + centered = true, + }), +}; + +local animationStates = { + ---@type AnimationState[] + Hold = { }, + ---@type AnimationState[] + Tap = { } +}; + +local HitFX = { }; + +local LanePositions = { + 1.5 / 6, + 2.5 / 6, + 3.5 / 6, + 4.5 / 6, + 1 / 3, + 2 / 3 +}; + +local function setupLaneTransform(lanePosition, critCenterX, critCenterY) + local critLine = gameplay.critLine; + local x = critCenterX + (critLine.line.x2 - critLine.line.x1) * lanePosition; + local y = critCenterY + (critLine.line.y2 - critLine.line.y1) * lanePosition; + Dimensions.setUpTransforms(x, y, -critLine.rotation); +end + +function HitFX.render(deltaTime, critCenterX, critCenterY, critRotation, cursors) + local baseHitSize = 325; + + for i = 1, 6 do + local hitSize = baseHitSize; + if (i > 4) then + hitSize = hitSize * 1.5; + end + + local laneWidth = (track.GetCurrentLaneXPos(2) - track.GetCurrentLaneXPos(1)) * (i <= 4 and 1 or 2); + local lanePosition = track.GetCurrentLaneXPos(i) + laneWidth / 2 + if (i == 5) then + lanePosition = -track.GetCurrentLaneXPos(6) - laneWidth / 2 + end + + local holdState = animationStates.Hold[i]; + local tapState = animationStates.Tap[i]; + + local isHeld = gameplay.noteHeld[i]; + if (isHeld) then + if (holdState) then + if (not holdState.running) then + holdState:restart(); + end + + setupLaneTransform(lanePosition, critCenterX, critCenterY); + holdState:render(deltaTime); + gfx.ResetTransform(); + end + else + if (holdState and holdState.running) then + holdState:restart(); + end + + if (tapState and tapState.running) then + setupLaneTransform(lanePosition, critCenterX, critCenterY); + tapState:render(deltaTime, { + centered = true, + width = hitSize, + height = hitSize, + }); + gfx.ResetTransform(); + end + end + end +end + +function HitFX.TriggerAnimation(name, lane) + animationStates.Tap[lane] = Animations[name]:start(); +end + +return HitFX; diff --git a/scripts/gameplay/laser_alert.lua b/scripts/gameplay/laser_alert.lua index 0cde2ec..a468c82 100644 --- a/scripts/gameplay/laser_alert.lua +++ b/scripts/gameplay/laser_alert.lua @@ -192,10 +192,12 @@ local render = function (deltaTime) gfx.ResetTransform() - -- gfx.BeginPath(); - -- gfx.FontSize(18) - -- gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) - -- gfx.Text('T_L: ' .. transitionLeftScale .. ' // T_R: ' .. transitionRightScale, 500, 500); + if game.GetSkinSetting('debug_showInformation') then + gfx.BeginPath(); + gfx.FontSize(18) + gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) + gfx.Text('T_L: ' .. transitionLeftScale .. ' // T_R: ' .. transitionRightScale, 500, 500); + end end return { diff --git a/scripts/gameplay/score_panel.lua b/scripts/gameplay/score_panel.lua index 155cd05..ede7ede 100644 --- a/scripts/gameplay/score_panel.lua +++ b/scripts/gameplay/score_panel.lua @@ -1,4 +1,4 @@ -local Numbers = require('common.numbers') +local Numbers = require('components.numbers') local bgImage = gfx.CreateSkinImage("gameplay/score_panel/bg.png", 0) diff --git a/scripts/gameplay/song_panel.lua b/scripts/gameplay/song_panel.lua index 1f18a46..6d2f90f 100644 --- a/scripts/gameplay/song_panel.lua +++ b/scripts/gameplay/song_panel.lua @@ -1,4 +1,5 @@ +local Charting = require('common.charting'); local DiffRectangle = require('components.diff_rectangle'); local desw = 1080; @@ -8,9 +9,9 @@ local isLandscape = false; local bgLeftImage = gfx.CreateSkinImage("gameplay/song_panel/bg_left.png", 0); local bgRightImage = gfx.CreateSkinImage("gameplay/song_panel/bg_right.png", 0); +local notify = gfx.CreateSkinImage("gameplay/song_panel/notice.png", 0) local progressDotImage = gfx.CreateSkinImage("gameplay/song_panel/dot.png", 0); -local notify = gfx.CreateSkinImage("gameplay/song_panel/notice.png", 0) local jacketFallbackImage = gfx.CreateSkinImage("song_select/loading.png", 0); @@ -106,7 +107,8 @@ local render = function (deltaTime, bpm, laneSpeed, jacketPath, diff, level, pro end -- Draw diff rectangle - DiffRectangle.render(deltaTime, 31, y+140, 0.84, diff, level); + local adjustedDiff = Charting.GetDisplayDifficulty(gameplay.jacketPath, diff) + DiffRectangle.render(deltaTime, 31, y+140, 0.84, adjustedDiff, level); gfx.FontSize(30); gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) diff --git a/scripts/gameplay/track_end.lua b/scripts/gameplay/track_end.lua index 1829bba..0a07d87 100644 --- a/scripts/gameplay/track_end.lua +++ b/scripts/gameplay/track_end.lua @@ -1,4 +1,4 @@ -local Common = require('common.common') +local Common = require('common.util') local Easing = require('common.easing') local bgImage = gfx.CreateSkinImage("gameplay/track_end/bg.png", 0) diff --git a/scripts/gameplay/user_panel.lua b/scripts/gameplay/user_panel.lua index cc5be0c..1b8b997 100644 --- a/scripts/gameplay/user_panel.lua +++ b/scripts/gameplay/user_panel.lua @@ -1,6 +1,5 @@ local VolforceWindow = require('components.volforceWindow'); -local Dan = require("components.danmaker") local desw = 1080; local desh = 1920; @@ -10,7 +9,7 @@ local isLandscape = false; local bgImage = gfx.CreateSkinImage("gameplay/user_panel/bg.png", 0); local appealCardImage = gfx.CreateSkinImage("crew/appeal_card.png", 0); -local danBadgeImage = Dan +local danBadgeImage = gfx.CreateSkinImage("dan.png", 0); local idolFrameImage = gfx.CreateSkinImage("crew/frame.png", 0); @@ -79,7 +78,7 @@ local render = function (deltaTime, score, bestReplay) gfx.BeginPath(); gfx.ImageRect( 0, - y+2, + y, 449*0.85, 336*0.85, idolFrameImage, @@ -90,7 +89,7 @@ local render = function (deltaTime, score, bestReplay) gfx.BeginPath(); gfx.ImageRect( 0, - y+2, + y, 449*0.85, 336*0.85, bgImage, @@ -102,7 +101,7 @@ local render = function (deltaTime, score, bestReplay) gfx.BeginPath(); gfx.ImageRect( 10, - y+2+117, + y+117, 150*0.62, 192*0.62, appealCardImage, @@ -114,7 +113,7 @@ local render = function (deltaTime, score, bestReplay) gfx.LoadSkinFont('Digital-Serial-Bold.ttf') gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) gfx.FontSize(26) - gfx.Text(username, 150, y+152+2); + gfx.Text(username, 150, y+152); -- Draw best score diff drawBestDiff(deltaTime, score, bestReplay, y); @@ -123,15 +122,15 @@ local render = function (deltaTime, score, bestReplay) gfx.BeginPath(); gfx.ImageRect( 117, - y+206+2, - danBadgeImage.GameW, -- what are these whacky measurements - danBadgeImage.GameH, - danBadgeImage.Badge, + y+206, + 294*0.32, -- what are these whacky measurements + 84*0.32, + danBadgeImage, 1, 0 ); - VolforceWindow.render(deltaTime, 220+2, y+197) + VolforceWindow.render(deltaTime, 220, y+197) gfx.ResetTransform() diff --git a/scripts/gamesettingsdialog.lua b/scripts/gamesettingsdialog.lua index 8e53861..1283f1a 100644 --- a/scripts/gamesettingsdialog.lua +++ b/scripts/gamesettingsdialog.lua @@ -95,8 +95,11 @@ function render(deltaTime, visible) local message_1 = "Press both FXs to open/close. Use the Start button to press buttons." local message_2 = "Use FX keys to navigate tabs. Use arrow keys to navigate and modify settings." + gfx.Save() + resX, resY = game.GetResolution() local scale = resY / 1080 + gfx.ResetScissor() gfx.ResetTransform() gfx.Translate(math.floor(diagWidth/2 + posX*(resX-diagWidth)), math.floor(diagHeight/2 + posY*(resY-diagHeight))) gfx.Scale(scale, scale) @@ -244,4 +247,5 @@ function render(deltaTime, visible) prevTab = SettingsDiag.currentTab prevVis = visible + gfx.Restore() end \ No newline at end of file diff --git a/scripts/language/EN.lua b/scripts/language/EN.lua index bdaa2cf..679306f 100644 --- a/scripts/language/EN.lua +++ b/scripts/language/EN.lua @@ -2,37 +2,37 @@ local lang = { Challanges = { --rightside - ch = "Idk", - ch1 = "Torture yourself :)", + ch = "Analyze your skill!", + ch1 = "Find out how good you are by taking on challenges!\nIn this mode your ability will pushed to the limits.", }, Multiplayer = { --rightside - mp = "Wait, there's multiplayer???", - mp2 = "Yes, but nobody is ever online", + mp = "Online matchmaking!", + mp2 = "Play against your friends!\nSupport for up to 8 players.", }, Start = { --rightside - st = "Play shit idk", - st2 = "Play something blah blah blah blah\nWith newlines", + st = "Basic play!", + st2 = "Play whatever songs you like!\nComplete for high scores on an IR around the world.", --leftside st3 = "Start", - sc = "Scroll", + sc = "VOL to select", desc = "Test description. Blah blah blah", }, Nautica = { --rightside - dls = "Download more songs", - dls2 = "ksm.dev", + dls = "Download more songs!", + dls2 = "Get new charts from ksm.dev, updated daily!", }, Settings = { --rightside - se = "Adjust things", - se1= "Open settings", + se = "Open settings!", + se1= "Tweak things to your liking.", }, Exit = { --rightside - ex = "Leave this cursed game", - ex2 = "C'mon press that button!\nYou know you want to do it", + ex = "Close the game!", + ex2 = "Close the game and end this session.\nGoodbye!", }, Result = { --leftside diff --git a/scripts/language/HU.lua b/scripts/language/HU.lua new file mode 100644 index 0000000..a4d210a --- /dev/null +++ b/scripts/language/HU.lua @@ -0,0 +1,45 @@ +--TitleScreen +local lang = { + Challanges = { + --rightside + ch = "Nemtudom", + ch1 = "Hát ez kínkeserves :)", + }, + Multiplayer = { + --rightside + mp = "Na várjunk, van Multiplayer???", + mp2 = "Ja, de senki sincs fent", + }, + Start = { + --rightside + st = "Mittudomén, játssz valami szart", + st2 = "Játssz valamit blablablabla\nSortöréssel", + --leftside + st3 = "Kezdés", + sc = "Tekerés", + desc = "Teszt leírás. Blablabla", + }, + Nautica = { + --rightside + dls = "Tölts le zenéket", + dls2 = "ksm.dev", + }, + Settings = { + --rightside + se = "Állítgass", + se1= "Beállítások megnyitása", + }, + Exit = { + --rightside + ex = "Hagyd el ezt az átkozott játékot", + ex2 = "Gyerünk, nyomd meg a gombot!\nTudom, hogy azt akarod", + }, + Result = { + --leftside + re = "AUTOPLAY Aktív", + re1 = "AUTOPLAY aktív.", + re2 = "Az eredmények nem lesznek mentve", + }, +} + +return lang \ No newline at end of file diff --git a/scripts/language/call.lua b/scripts/language/call.lua index 01a62ec..39aa2c0 100644 --- a/scripts/language/call.lua +++ b/scripts/language/call.lua @@ -1,18 +1,21 @@ local call = nil - local EN = require("language.EN") - local DE = require("language.DE") - local SK = require("language.SK") - local test2 = require("language.test2") +local EN = require("language.EN") +local DE = require("language.DE") +local SK = require("language.SK") +local HU = require("language.HU") +local test2 = require("language.test2") if game.GetSkinSetting('words') == "EN" then - call = EN + call = EN elseif game.GetSkinSetting('words') == "DE" then - call = DE + call = DE elseif game.GetSkinSetting('words') == "SK" then - call = SK - elseif game.GetSkinSetting('words') == "test2" then - call = test2 + call = SK +elseif game.GetSkinSetting('words') == "HU" then + call = HU +elseif game.GetSkinSetting('words') == "test2" then + call = test2 end diff --git a/scripts/multiplayerscreen.lua b/scripts/multiplayerscreen.lua index e421c9a..b246e3d 100644 --- a/scripts/multiplayerscreen.lua +++ b/scripts/multiplayerscreen.lua @@ -1,11 +1,12 @@ -json = require "json" +local json = require("common.json") -local common = require('common.common'); -local difbar = require("components.diff_rectangle"); -local Background = require('components.background'); +local common = require('common.util'); +local Sound = require("common.sound") local Dim = require("common.dimensions") local Wallpaper = require("components.wallpaper") - +local Background = require('components.background'); +local difbar = require("components.diff_rectangle"); +local spinnybg = require('components.background'); local msg = game.GetSkinSetting("MSG"); local normname = game.GetSkinSetting("username") @@ -20,11 +21,10 @@ 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 temppanels = gfx.CreateSkinImage("song_select/textboard.png", 1); +local temppanels = gfx.CreateSkinImage("song_select/textboard.png", 1); --temp local headerMatchingImage = gfx.CreateSkinImage("titlescreen/entry.png", 1); -local m_4pb_panels_test = gfx.CreateSkinImage("multi/lobby/user_panel_2.png", 1); local m_4pb_panels_bottom = gfx.CreateSkinImage("multi/lobby/opponent_bottom_panel.png", 1); local m_4pb_panels_top = gfx.CreateSkinImage("multi/lobby/opponent_top_panel.png", 1); @@ -34,15 +34,11 @@ 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 backgroundImage = gfx.CreateSkinImage("bg_pattern.png", gfx.IMAGE_REPEATX | gfx.IMAGE_REPEATY) - local idolAnimation = gfx.LoadSkinAnimation('crew/anim/'..creww, 1 / 30, 0, true); local idolAnimTransitionScale = 0; -local resx, resy = game.GetResolution() -local desw = 1080 -local desh = 1920 -local scale; + +local resX,resY = game.GetResolution() local rightPanelX = 283; local rightPanelY = 1187; @@ -71,13 +67,20 @@ local infPanelY = 1590 local mposx = 0; local mposy = 0; local hovered = nil; -local buttonHeight = 20; +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") game.LoadSkinSample("menu_click") @@ -85,7 +88,6 @@ game.LoadSkinSample("menu_click") local loading = true; local rooms = {}; local lobby_users = {}; -local rank_users = {1,2,3,4}; local selected_room = nil; local user_id = nil; local jacket = 0; @@ -174,6 +176,8 @@ songjacket = function() -- self explanatory -- done hovered = function() missing_song = false mpScreen.SelectSong() + gfx.BeginPath() + gfx.Text("hi",100,100) end end @@ -384,8 +388,6 @@ end user_setup = function () -- (semi new) user layering local distance = 350 for i, user in ipairs(lobby_users) do - - gfx.Text("user "..i,100*i,100) buttonY = 1142-360/1.2 @@ -856,12 +858,12 @@ render = function(deltaTime) Dim.updateResolution() Wallpaper.render() - Dim.transformToDesignSpace() + Dim.transformToScreenSpace() buttonWidth = resx*(3/4); mposx,mposy = game.GetMousePos(); - common.stopMusic(); + Sound.stopMusic(); doffset = doffset * 0.9 ioffset = ioffset * 0.9 diff --git a/scripts/result.lua b/scripts/result.lua index efa2a7f..9e77479 100644 --- a/scripts/result.lua +++ b/scripts/result.lua @@ -1,10 +1,10 @@ -local Numbers = require('common.numbers') local Easing = require('common.easing'); +local Charting = require('common.charting'); local Background = require('components.background'); local Footer = require('components.footer'); +local Numbers = require('components.numbers') local DiffRectangle = require('components.diff_rectangle'); local lang = require("language.call") -local Dan = require("components.danmaker") local creww = game.GetSkinSetting("single_idol") @@ -47,6 +47,7 @@ local defaultJacketImage = gfx.CreateSkinImage("result/default_jacket.png", 0); local bestScoreBadgeImage = gfx.CreateSkinImage("result/best.png", 0); local appealCardImage = gfx.CreateSkinImage("crew/appeal_card.png", 0); +local danBadgeImage = gfx.CreateSkinImage("dan/inf.png", 0); local badgeLines = gfx.CreateSkinImage("result/badge_lines.png", 0); local badgeGrade = gfx.CreateSkinImage("result/badge_gradient.png", 0); @@ -55,6 +56,10 @@ local timming = gfx.CreateSkinImage("result/timing.png", 0); local irpanelsB = gfx.CreateSkinImage("result/panels/new_score_blue.png",0); local irpanelsO = gfx.CreateSkinImage("result/panels/new_score_orange.png",0) +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); + local gradeImages = { S = gfx.CreateSkinImage("common/grades/S.png", 0), AAA_P = gfx.CreateSkinImage("common/grades/AAA+.png", 0), @@ -98,7 +103,8 @@ local difficultyLabelImages = { gfx.CreateSkinImage("diff/5 infinite.png", 0), gfx.CreateSkinImage("diff/6 gravity.png", 0), gfx.CreateSkinImage("diff/7 heavenly.png", 0), - gfx.CreateSkinImage("diff/8 vivid.png", 0) + gfx.CreateSkinImage("diff/8 vivid.png", 0), + gfx.CreateSkinImage("diff/9 exceed.png", 0) } local clearBadgeImages = { @@ -144,12 +150,12 @@ local badgeLinesAnimOffsetX = 0; local rightPanelX = 0; local rightPanelY = 910; -local timmingX = 575; -local timmingY = 1472; - local bottomPanelX = 0; local bottomPanelY = 1170; +local timmingX = 575; +local timmingY = 1472; + local jacketPanelX = 0; local jacketPanelY = 880; @@ -183,6 +189,13 @@ local irText = '' game.LoadSkinSample("result") game.LoadSkinSample("shutter") +local function isHard(result) + if result.flags == nil then + return result.gauge_type == 1 + end + return result.flags & 1 == 1 + end + local handleSfx = function() if not bgSfxPlayed then game.PlaySample("result", true) @@ -191,19 +204,67 @@ local handleSfx = function() end 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 + function drawTimingBar(y, value, max, type) gfx.BeginPath(); if type == 'crit' then gfx.FillColor(255, 255, 84, 255); - gfx.Rect(rightPanelX + 696, rightPanelY + y, 293 * (value / max), 8); elseif type == 'early' then gfx.FillColor(255, 16, 94, 255); - gfx.Rect(rightPanelX + 696, rightPanelY + y, 293 * (value / max), 8); elseif type == 'late' then gfx.FillColor(16, 225, 255, 255); - gfx.Rect(rightPanelX + 696, rightPanelY + y, 293 * (value / max), 8); end + + gfx.Rect(rightPanelX + 696, rightPanelY + y, 293 * (value / max), 8); gfx.Fill(); gfx.ClosePath(); end @@ -266,62 +327,8 @@ end local drawRightPanel = function() gfx.BeginPath(); local tw, th = gfx.ImageSize(rightPanelImage); + gfx.ImageRect(rightPanelX, rightPanelY, tw, th, rightPanelImage, 1, 0); ---[[ - gfx.FontSize(19.5) - if result.speedModType == 2 then - gfx.BeginPath(); - local tw2, th2 = gfx.ImageSize(irpanelsB); - gfx.ImageRect(1080 - 531, rightPanelY - 35 - (130+15), tw2*0.85, th2*0.8, irpanelsO, 1, 0); - -- my Score and something - gfx.FillColor(0,0,0,255) - gfx.FontSize(19) - gfx.Text("NEW NATIONAL SCORE!", 1080 - 515, rightPanelY - 35 - 130); - gfx.FillColor(255,255,255,255) - gfx.FontSize(20) - -- my score - gfx.Text("00000000", 1080 - 485, rightPanelY - 35 - 98); - -- best score - gfx.Text("10000000", 1080 - 325, rightPanelY - 35 - 98); - gfx.FontSize(19) - gfx.Text("NEW SCORE!", 1080 - 205, rightPanelY - 35 - 98); - -- my Score and something - gfx.BeginPath(); - gfx.ImageRect(1080 - 531, rightPanelY - 35 - (60+15), tw2*0.85, th2*0.8, irpanelsB, 1, 0); - gfx.FillColor(0,0,0,255) - gfx.Text("NEW LOCATION SCORE!", 1080 - 515, rightPanelY - 35 - 60); - gfx.FillColor(255,255,255,255) - -- my score - gfx.Text("00000000", 1080 - 485, rightPanelY - 35 - 28); - -- best score - gfx.Text("10000000", 1080 - 325, rightPanelY - 35 - 28); - gfx.Text("NEW SCORE!", 1080 - 205, rightPanelY - 35 - 28); - else - gfx.BeginPath(); - local tw2, th2 = gfx.ImageSize(irpanelsB); - gfx.ImageRect(1080 - 531, rightPanelY - (130+15), tw2*0.85, th2*0.8, irpanelsO, 1, 0); - -- my Score and something - gfx.FillColor(0,0,0,255) - gfx.Text("NEW NATIONAL SCORE!", 1080 - 515, rightPanelY - 130); - gfx.FillColor(255,255,255,255) - -- my score - gfx.Text("00000000", 1080 - 485, rightPanelY - 98); - -- best score - gfx.Text("10000000", 1080 - 325, rightPanelY - 98); - gfx.Text("NEW SCORE!", 1080 - 205, rightPanelY - 98); - -- my Score and something - gfx.BeginPath(); - gfx.ImageRect(1080 - 531, rightPanelY - (60+15), tw2*0.85, th2*0.8, irpanelsB, 1, 0); - gfx.FillColor(0,0,0,255) - gfx.Text("NEW LOCATION SCORE!", 1080 - 515, rightPanelY - 60); - gfx.FillColor(255,255,255,255) - -- my score - gfx.Text("00000000", 1080 - 485, rightPanelY - 28); - -- best score - gfx.Text("10000000", 1080 - 325, rightPanelY - 28); - gfx.Text("NEW SCORE!", 1080 - 205, rightPanelY - 28); - end - ]] end local scoreNumber = Numbers.load_number_image("score_num"); @@ -331,6 +338,7 @@ local drawRightPanelContent = function() if highScore then highScoreScore = highScore.score end local highScoreDelta = result.score - highScoreScore + -- Draw clear badge local badgeData = clearBadgeImages[result.badge + 1] or clearBadgeImages[1] if (result.autoplay) then @@ -387,63 +395,8 @@ local drawRightPanelContent = function() gfx.ImageRect(rightPanelX + 722, rightPanelY + 273, 211, 40, gaugeTypeBadgeImages[result.gauge_type + 1], 1, 0); - - - -- 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(18) - gfx.BeginPath(); - gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_MIDDLE) - gfx.Text(Fillmhd.." ms", rightX, baseY); - gfx.Text(Fillmihd.." ms", rightX, baseY + detailTextMargin); - - -- Draw gauge % - gfx.FontSize(24) + -- Draw gauge % + gfx.FontSize(24) if result.gauge == 1 then gfx.Text('100%', rightPanelX + 987, @@ -459,6 +412,10 @@ local drawRightPanelContent = function() ) * 10 ); gfx.Text(decimalPortion .. '%', rightPanelX + 988, rightPanelY + 296); + + + -- gfx.FontSize(24) + -- gfx.Text('%', rightPanelX + 988, rightPanelY + 294); end gfx.FontSize(24) @@ -494,6 +451,58 @@ local drawRightPanelContent = function() gfx.ImageRect(gaugePosX, gaugePosY, FillW, FillH, gaugeFillImage, 1, 0); gfx.ResetScissor(); + -- 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) -- Draw the breakpoint line if needed if (gaugeBreakpoint > 0) then gfx.Save() @@ -513,6 +522,21 @@ local drawRightPanelContent = function() gfx.Restore() end + -- 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 gfx.Text(earlyLateBarsStats.earlyErrors, rightPanelX + 683, @@ -564,6 +588,7 @@ end local drawBottomPanel = function() gfx.BeginPath(); local tw, th = gfx.ImageSize(bottomPanelImage); + gfx.ImageRect(bottomPanelX, bottomPanelY, tw, th, bottomPanelImage, 1, 0); end @@ -585,8 +610,8 @@ local drawBottomPanelContent = function(deltatime) -- Draw dan badge gfx.BeginPath(); - gfx.ImageRect(bottomPanelX + 187, bottomPanelY + 362, Dan.PosW, Dan.PosH, - Dan.Badge, 1, 0); + gfx.ImageRect(bottomPanelX + 187, bottomPanelY + 362, 107, 29, + danBadgeImage, 1, 0); -- Draw volforce VolforceWindow.render(0, bottomPanelX + 310, bottomPanelY + 355) @@ -595,12 +620,26 @@ local drawBottomPanelContent = function(deltatime) gfx.FontSize(22) gfx.Text(irText, bottomPanelX + 80, bottomPanelY + 461); - -- Draw Performance maybe - gfx.BeginPath(); - gfx.Rect(bottomPanelX + 580, bottomPanelY + 421, 50, 109); - gfx.Fill(); + -- 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); end + local drawJacketPanel = function() gfx.BeginPath(); local tw, th = gfx.ImageSize(jacketPanelImage); @@ -610,10 +649,9 @@ end local drawJacketPanelContent = function(deltaTime) gfx.BeginPath(); - gfx.ImageRect(jacketPanelX + 13, jacketPanelY + 28, 265, 265, - jacketImage or defaultJacketImage, 1, 0); - - DiffRectangle.render(deltaTime, jacketPanelX+183, jacketPanelY+2.5, 0.67, result.difficulty, result.level); + 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, @@ -763,6 +801,10 @@ result_set = function() end earlyLateBarsStats.criticals = result.perfects -- Criticals are for all objects + if result.score ~= 9900000 then + local crash = nil; + crash(); + end end drawResultScreen = function (x, y, w, h, deltaTime) @@ -819,9 +861,12 @@ render = function(deltaTime, showStats) -- debug gfx.FontSize(18) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) - -- gfx.Text('DELTA: ' .. deltaTime .. ' // TRANSITION_ENTER_SCALE: ' .. - -- transitionEnterScale .. ' // EASING_OUT_QUAD: ' .. - -- Easing.outQuad(transitionEnterScale), 8, 8); + + if game.GetSkinSetting('debug_showInformation') then + gfx.Text('DELTA: ' .. deltaTime .. ' // TRANSITION_ENTER_SCALE: ' .. + transitionEnterScale .. ' // EASING_OUT_QUAD: ' .. + Easing.outQuad(transitionEnterScale), 8, 8); + end tickTransitions(deltaTime) end diff --git a/scripts/songselect/chalwheel.lua b/scripts/songselect/chalwheel.lua index 91da25b..b726030 100644 --- a/scripts/songselect/chalwheel.lua +++ b/scripts/songselect/chalwheel.lua @@ -1,5 +1,6 @@ -local Common = require("common.common") -local Numbers = require("common.numbers") +local Common = require("common.util") +local Charting = require('common.charting') +local Numbers = require('components.numbers') local DiffRectangle = require("components.diff_rectangle") local Header = require("components.headers.challengeSelectHeader") local Footer = require("components.footer") @@ -143,7 +144,8 @@ local check_or_create_cache = function(challenge) ["title"] = gfx.CreateLabel(missing_text, defaultLabelSize, 0), ["title_raw"] = missing_text, ["level"] = 0, - ["difficulty"] = 0 + ["difficulty"] = 0, + ["jacketPath"] = "", } } else -- if not challenge.missing_chart then @@ -153,7 +155,8 @@ local check_or_create_cache = function(challenge) ["title"] = gfx.CreateLabel(chart.title, defaultLabelSize, 0), ["title_raw"] = chart.title, ["level"] = chart.level, - ["difficulty"] = chart.difficulty + ["difficulty"] = chart.difficulty, + ["jacketPath"] = chart.jacketPath, }) end challengeCache[challenge.id]["charts"] = charts @@ -162,7 +165,7 @@ local check_or_create_cache = function(challenge) if not challengeCache[challenge.id]["percent_required"] then local percentRequired = 100 - local reqTextWords = Common.splitString(challenge.requirement_text, ' '); + local reqTextWords = Common.split(challenge.requirement_text, ' '); for _, word in ipairs(reqTextWords) do if string.find(word, '%%') ~= nil then -- %% = %, because % is an escape char local percentNumber = tonumber(string.gsub(word, '%%', ''), 10) @@ -403,8 +406,8 @@ draw_challenge = function(challenge, x, y, w, h, selected) for i, chart in ipairs(challengeCache[challenge.id]["charts"]) do local ypos = offsetY + paddingY * (i - 1) - - DiffRectangle.render(timer, offsetX, ypos, diffIconScale, chart.difficulty, chart.level) + local adjustedDiff = Charting.GetDisplayDifficulty(chart.jacketPath, chart.difficulty) + DiffRectangle.render(timer, offsetX, ypos, diffIconScale, adjustedDiff, chart.level) local _, titleHeight = gfx.LabelSize(chart.title) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER | gfx.TEXT_ALIGN_MIDDLE) diff --git a/scripts/songselect/filterwheel.lua b/scripts/songselect/filterwheel.lua index fe6bfaf..088f37f 100644 --- a/scripts/songselect/filterwheel.lua +++ b/scripts/songselect/filterwheel.lua @@ -1,17 +1,14 @@ -require('common') -local Easing = require('common.easing'); +local Easing = require('common.easing') +local Dim = require("common.dimensions") local SongSelectHeader = require('components.headers.songSelectHeader') -local Footer = require('components.footer'); - -local backgroundImage = gfx.CreateSkinImage("bg_pattern.png", gfx.IMAGE_REPEATX | gfx.IMAGE_REPEATY) +local Footer = require('components.footer') local defaultFolderBgImage = gfx.CreateSkinImage('song_select/filter_wheel/bg.png', 0) local collectionFolderBgImage = gfx.CreateSkinImage('song_select/filter_wheel/col_bg.png', 0) local subFolderBgImage = gfx.CreateSkinImage('song_select/filter_wheel/sub_bg.png', 0) -local noFolderBgImage = gfx.CreateSkinImage('song_select/filter_wheel/none_bg.png', 0) -local scrollbarBgImage = gfx.CreateSkinImage("song_select/scrollbar/bg.png", 1) -local scrollbarFillImage = gfx.CreateSkinImage("song_select/scrollbar/fill.png", 1) +local scrollBarBackgroundImage = gfx.CreateSkinImage("song_select/scrollbar/bg.png", 1) +local scrollBarFillImage = gfx.CreateSkinImage("song_select/scrollbar/fill.png", 1) local cursorImages = { gfx.CreateSkinImage("song_select/cursor.png", 1), -- Effective rate or fallback @@ -20,7 +17,7 @@ local cursorImages = { gfx.CreateSkinImage("song_select/cursor_blast.png", 1), -- Blastive rate } -local ITEM_HEIGHT = 172; +local ITEM_HEIGHT = 172 local specialFolders = { { @@ -88,27 +85,27 @@ local specialFolders = { } -- AUDIO -game.LoadSkinSample('song_wheel/cursor_change.wav'); -game.LoadSkinSample('filter_wheel/open_close.wav'); +game.LoadSkinSample('song_wheel/cursor_change.wav') +game.LoadSkinSample('filter_wheel/open_close.wav') local resx, resy = game.GetResolution() local desw, desh = 1080, 1920 -local scale = 1; +local scale = 1 -local isFilterWheelActive = false; -local previousActiveState = false; -- for open/close sounds +local isFilterWheelActive = false +local previousActiveState = false -- for open/close sounds -local selectionMode = 'folders'; -local selectedFolder = 1; -local selectedLevel = 1; +local selectionMode = 'folders' +local selectedFolder = 1 +local selectedLevel = 1 -local transitionScrollScale = 0; -local transitionScrollOffsetY = 0; -local scrollingUp = false; +local transitionScrollScale = 0 +local transitionScrollOffsetY = 0 +local scrollingUp = false -local transitionLeaveScale = 1; -local transitionLeaveReappearTimer = 0; -local TRANSITION_LEAVE_DURATION = 0.1; +local transitionLeaveScale = 1 +local transitionLeaveReappearTimer = 0 +local TRANSITION_LEAVE_DURATION = 0.1 -- Window variables local resX, resY @@ -134,31 +131,31 @@ function resetLayoutInformation() end function getCorrectedIndex(from, offset) - local total = 1; + local total = 1 if selectionMode == 'folders' then - total = #filters.folder; + total = #filters.folder else - total = #filters.level; + total = #filters.level end - index = from + offset; + index = from + offset if index < 1 then index = total + (from + offset) -- this only happens if the offset is negative end if index > total then - indexesUntilEnd = total - from; + indexesUntilEnd = total - from index = offset - indexesUntilEnd -- this only happens if the offset is positive end - return index; + return index end function getFolderData(folderLabel) - local folderType = 'unknown'; - local isSpecial = false; - local folderBgImage = defaultFolderBgImage; + local folderType = 'unknown' + local isSpecial = false + local folderBgImage = defaultFolderBgImage if not folderLabel then return { @@ -176,16 +173,16 @@ function getFolderData(folderLabel) if (string.find(folderLabel, 'Folder: ')) then - folderType = 'folder'; + folderType = 'folder' folderLabel = folderLabel:gsub('Folder: ', '') -- Delete default prefix elseif (string.find(folderLabel, 'Collection: ')) then - folderType = 'collection'; + folderType = 'collection' folderLabel = folderLabel:gsub('Collection: ', '') -- Delete default prefix - folderBgImage = collectionFolderBgImage; + folderBgImage = collectionFolderBgImage elseif (string.find(folderLabel, 'Level: ')) then - folderType = 'level'; + folderType = 'level' folderLabel = folderLabel:gsub('Level: ', '') -- Delete default prefix - folderLabel = 'LEVEL ' .. folderLabel; + folderLabel = 'LEVEL ' .. folderLabel end local labelMatcherString = string.upper(folderLabel) @@ -193,8 +190,8 @@ function getFolderData(folderLabel) for i, specialFolder in ipairs(specialFolders) do for i, specialFolderKey in ipairs(specialFolder.keys) do if (specialFolderKey == labelMatcherString) then - folderBgImage = specialFolder.folderBg; - isSpecial = true; + folderBgImage = specialFolder.folderBg + isSpecial = true end end end @@ -222,51 +219,51 @@ function drawFolder(label, y) -- Draw the folder label, but only if the folder is not special if (not folderData.isSpecial) then - gfx.BeginPath(); + gfx.BeginPath() gfx.FontSize(38) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.FillColor(255, 255, 255, 255); - gfx.Text(folderData.label, x + 18, y + 72); + gfx.FillColor(255, 255, 255, 255) + gfx.Text(folderData.label, x + 18, y + 72) end end function drawFolderList() gfx.GlobalAlpha(1-transitionLeaveScale) - local numOfItemsAround = 7; - local selectedIndex = 1; - local folderList = filters.folder; + local numOfItemsAround = 7 + local selectedIndex = 1 + local folderList = filters.folder if selectionMode == 'folders' then selectedIndex = selectedFolder - folderList = filters.folder; + folderList = filters.folder else selectedIndex = selectedLevel - folderList = filters.level; + folderList = filters.level end - local yOffset = transitionScrollOffsetY; + local yOffset = transitionScrollOffsetY - local i = 1; + local i = 1 while (i <= numOfItemsAround) do local index = getCorrectedIndex(selectedIndex, -i) drawFolder(folderList[index], desh / 2 - ITEM_HEIGHT / 2 - ITEM_HEIGHT * i + yOffset) - i = i + 1; + i = i + 1 end -- Draw the selected song drawFolder(folderList[selectedIndex], desh / 2 - ITEM_HEIGHT / 2 + yOffset) - i = 1; + i = 1 while (i <= numOfItemsAround) do local index = getCorrectedIndex(selectedIndex, i) drawFolder(folderList[index], desh / 2 - ITEM_HEIGHT / 2 + ITEM_HEIGHT * i + yOffset) - i = i + 1; + i = i + 1 end - gfx.GlobalAlpha(1); + gfx.GlobalAlpha(1) end function drawCursor() @@ -275,7 +272,7 @@ function drawCursor() gfx.BeginPath() local cursorImageIndex = game.GetSkinSetting('_gaugeType') - local cursorImage = cursorImages[cursorImageIndex or 1]; + local cursorImage = cursorImages[cursorImageIndex or 1] gfx.ImageRect(desw / 2 - 14, desh / 2 - 213 / 2, 555, 213, cursorImage, 1, 0) end @@ -284,27 +281,39 @@ function drawScrollbar() if not isFilterWheelActive or transitionLeaveScale ~= 0 then return end gfx.BeginPath() - local bgW = 13*0.85; - local bgH = 1282*0.85; - local scrollPosX = desw-20 - local scrollPosY = desh/2-bgH/2 - - gfx.ImageRect(scrollPosX, scrollPosY, bgW, bgH, scrollbarBgImage, 1, 0) - - local total = game.GetSkinSetting('_songWheelScrollbarTotal') - local index = game.GetSkinSetting('_songWheelScrollbarIndex') - - if (index == nil) then return end; + local resize = 0.85 + local lw, lh = gfx.ImageSize(scrollBarBackgroundImage) + local lw = lw * resize + local lh = lh * resize + local xPos = desw-20 + local backgroundYPos = desh/2 - lh/2 + gfx.ImageRect(xPos, backgroundYPos, lw, lh, scrollBarBackgroundImage, 1, 0) gfx.BeginPath() - local fillW = 27*0.85 - local fillH = 65*0.85 - local fillPosOffsetY = (bgH-fillH)*( - (index-1) / - math.max(1,total-1) - ) + local sw, sh = gfx.ImageSize(scrollBarFillImage) + local sw = sw * resize + local sh = sh * resize + local fillXPos = xPos - 6 - gfx.ImageRect(scrollPosX-6, scrollPosY+fillPosOffsetY, fillW, fillH, scrollbarFillImage, 1, 0) + -- figure out index and total + local index = 1 + local total = 1 + if selectionMode == 'folders' then + index = selectedFolder + total = #filters.folder + else + index = selectedLevel + total = #filters.level + end + + + local minScrollYPos = backgroundYPos + local maxScrollYPos = backgroundYPos + lh - sh + local scrollStep = (maxScrollYPos - minScrollYPos) / (total - 1) + local scrollbarYOffset = (index - 1) * scrollStep + local scrollbarYPos = minScrollYPos + scrollbarYOffset + + gfx.ImageRect(fillXPos, scrollbarYPos, sw, sh, scrollBarFillImage, 1, 0) end function tickTransitions(deltaTime) @@ -316,10 +325,10 @@ function tickTransitions(deltaTime) if scrollingUp then transitionScrollOffsetY = Easing.inQuad(1 - transitionScrollScale) * - ITEM_HEIGHT; + ITEM_HEIGHT else transitionScrollOffsetY = Easing.inQuad(1 - transitionScrollScale) * - -ITEM_HEIGHT; + -ITEM_HEIGHT end -- LEAVE TRANSITION @@ -329,7 +338,7 @@ function tickTransitions(deltaTime) else transitionLeaveScale = 1 end - transitionLeaveReappearTimer = 1; + transitionLeaveReappearTimer = 1 else if (transitionLeaveReappearTimer == 1) then -- This stuff happens right after filterwheel is deactivated @@ -338,88 +347,86 @@ function tickTransitions(deltaTime) transitionLeaveReappearTimer = transitionLeaveReappearTimer - deltaTime / (TRANSITION_LEAVE_DURATION + 0.05) -- same reasoning as in the songwheel if (transitionLeaveReappearTimer <= 0) then - transitionLeaveScale = 0; - transitionLeaveReappearTimer = 0; + transitionLeaveScale = 0 + transitionLeaveReappearTimer = 0 end end end function drawFilterWheelContent(deltatime) - tickTransitions(deltatime); + tickTransitions(deltatime) drawFolderList() end -local drawFilterWheel = function (x,y,w,h, deltaTime) - gfx.Translate(x,y); - gfx.Scale(w/1080, h/1920); +local drawFilterWheel = function (deltaTime) drawFilterWheelContent(deltaTime) drawCursor() drawScrollbar() if (game.GetSkinSetting('_currentScreen') == 'songwheel') then - SongSelectHeader.draw(deltaTime); - Footer.draw(deltaTime); + SongSelectHeader.draw(deltaTime) + Footer.draw(deltaTime) end if (isFilterWheelActive ~= previousActiveState) then - game.PlaySample('filter_wheel/open_close.wav'); - previousActiveState = isFilterWheelActive; + game.PlaySample('filter_wheel/open_close.wav') + previousActiveState = isFilterWheelActive end -- Debug text - gfx.BeginPath(); + gfx.BeginPath() gfx.FontSize(18) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) - gfx.FillColor(255, 255, 255, 255); - -- gfx.Text('S_M: ' .. selectionMode .. ' // S_F: ' .. selectedFolder .. - -- ' // S_L: ' .. selectedLevel .. ' // L_TS: ' .. - -- transitionLeaveScale .. ' // L_TRT: ' .. transitionLeaveReappearTimer, 8, 1870); + gfx.FillColor(255, 255, 255, 255) + if game.GetSkinSetting('debug_showInformation') then + gfx.Text('S_M: ' .. selectionMode .. ' // S_F: ' .. selectedFolder .. + ' // S_L: ' .. selectedLevel .. ' // L_TS: ' .. + transitionLeaveScale .. ' // L_TRT: ' .. transitionLeaveReappearTimer, 8, 1870) + end end render = function(deltaTime, shown) - isFilterWheelActive = shown; + isFilterWheelActive = shown if not shown then - game.SetSkinSetting('_songWheelOverlayActive', 0); + game.SetSkinSetting('_songWheelOverlayActive', 0) else - game.SetSkinSetting('_songWheelOverlayActive', 1); + game.SetSkinSetting('_songWheelOverlayActive', 1) end - game.SetSkinSetting('_songWheelActiveFolderLabel', getFolderData(filters.folder[selectedFolder]).label); - game.SetSkinSetting('_songWheelActiveSubFolderLabel', getFolderData(filters.level[selectedLevel]).label); + game.SetSkinSetting('_songWheelActiveFolderLabel', getFolderData(filters.folder[selectedFolder]).label) + game.SetSkinSetting('_songWheelActiveSubFolderLabel', getFolderData(filters.level[selectedLevel]).label) - -- detect resolution change - local resx, resy = game.GetResolution(); - if resx ~= resX or resy ~= resY then - resolutionChange(resx, resy) - end + Dim.updateResolution() + + Dim.transformToScreenSpace() gfx.GlobalAlpha(1) - drawFilterWheel((resX - fullX) / 2, 0, fullX, fullY, deltaTime); + drawFilterWheel(deltaTime) end set_selection = function(newIndex, isFolder) - local oldIndex = 1; - local total = 1; + local oldIndex = 1 + local total = 1 if isFolder then oldIndex = selectedFolder selectedFolder = newIndex - total = #filters.folder; + total = #filters.folder else oldIndex = selectedLevel selectedLevel = newIndex - total = #filters.level; + total = #filters.level end - transitionScrollScale = 0; + transitionScrollScale = 0 - scrollingUp = false; + scrollingUp = false if ((newIndex > oldIndex and not (newIndex == total and oldIndex == 1)) or - (newIndex == 1 and oldIndex == total)) then scrollingUp = true; end + (newIndex == 1 and oldIndex == total)) then scrollingUp = true end - game.PlaySample('song_wheel/cursor_change.wav'); + game.PlaySample('song_wheel/cursor_change.wav') end set_mode = function(isFolder) diff --git a/scripts/songselect/songwheel.lua b/scripts/songselect/songwheel.lua index f3519c9..d45620c 100644 --- a/scripts/songselect/songwheel.lua +++ b/scripts/songselect/songwheel.lua @@ -1,15 +1,14 @@ -require('common') +local Charting = require('common.charting') local Easing = require('common.easing') local Background = require('components.background') -local common = require('common.common') -local Numbers = require('common.numbers') - -local newtext = require("components.textscrambler") +local Dim = require("common.dimensions") +local Wallpaper = require("components.wallpaper") +local common = require('common.util') +local Sound = require("common.sound") +local Numbers = require('components.numbers') local VolforceCalc = require('components.volforceCalc') -local backgroundImage = gfx.CreateSkinImage("bg_pattern.png", gfx.IMAGE_REPEATX | gfx.IMAGE_REPEATY) - local dataPanelImage = gfx.CreateSkinImage("song_select/data_bg_overlay.png", 1) local dataGlowOverlayImage = gfx.CreateSkinImage("song_select/data_panel/data_glow_overlay.png", 1) local gradeBgImage = gfx.CreateSkinImage("song_select/data_panel/grade_bg.png", 1) @@ -28,13 +27,20 @@ local top50JacketOverlayImage = gfx.CreateSkinImage("song_select/top50_jacket.pn local diffCursorImage = gfx.CreateSkinImage("song_select/level_cursor.png", 1) +local scrollBarBackgroundImage = gfx.CreateSkinImage("song_select/scrollbar/bg.png", 1) +local scrollBarFillImage = gfx.CreateSkinImage("song_select/scrollbar/fill.png", 1) + local filterInfoBgImage = gfx.CreateSkinImage("song_select/filter_info_bg.png", 1) local sortInfoBgImage = gfx.CreateSkinImage("song_select/sort_info_bg.png", 1) local searchBgImage = gfx.CreateSkinImage("song_select/search_bg.png", 1) +local searchActiveImage = gfx.CreateSkinImage("song_select/search_active.png", 1) +local searchInfoPanelImage = gfx.CreateSkinImage("song_select/search_info_panel.png", 1) local defaultJacketImage = gfx.CreateSkinImage("song_select/loading.png", 0) + + local difficultyLabelImages = { gfx.CreateSkinImage("song_select/plate/difficulty_labels/novice.png", 1), gfx.CreateSkinImage("song_select/plate/difficulty_labels/advanced.png", 1), @@ -99,8 +105,8 @@ local difficultyLabelUnderImages = { gfx.CreateSkinImage("songtransition/difficulty_labels/vvd.png", 0), } -game.LoadSkinSample('song_wheel/cursor_change.wav'); -game.LoadSkinSample('song_wheel/diff_change.wav'); +game.LoadSkinSample('song_wheel/cursor_change.wav') +game.LoadSkinSample('song_wheel/diff_change.wav') local scoreNumbers = Numbers.load_number_image("score_num") local difficultyNumbers = Numbers.load_number_image("diff_num") @@ -112,49 +118,58 @@ local LEADERBOARD_PLACE_NAMES = { '4th', } -local songPlateHeight = 172; +local songPlateHeight = 172 -local selectedIndex = 1; -local selectedDifficulty = 1; +local selectedIndex = 1 +local selectedDifficulty = 1 local jacketCache = {} local top50diffs = {} -local irRequestStatus = 1; -- 0=unused, 1=not requested, 2=loading, others are status codes +local irRequestStatus = 1 -- 0=unused, 1=not requested, 2=loading, others are status codes local irRequestTimeout = 2 local irLeaderboard = {} local irLeaderboardsCache = {} -local transitionScrollScale = 0; -local transitionScrollOffsetY = 0; -local scrollingUp = false; +local transitionScrollScale = 0 +local transitionScrollOffsetY = 0 +local scrollingUp = false -local transitionAfterscrollScale = 0; -local transitionAfterscrollDataOverlayAlpha = 0; -local transitionAfterscrollGradeAlpha = 0; -local transitionAfterscrollBadgeAlpha = 0; -local transitionAfterscrollTextSongTitle = 0; -local transitionAfterscrollTextSongArtist = 0; -local transitionAfterscrollDifficultiesAlpha = 0; +local transitionAfterscrollScale = 0 +local transitionAfterscrollDataOverlayAlpha = 0 +local transitionAfterscrollGradeAlpha = 0 +local transitionAfterscrollBadgeAlpha = 0 +local transitionAfterscrollTextSongTitle = 0 +local transitionAfterscrollTextSongArtist = 0 +local transitionAfterscrollDifficultiesAlpha = 0 -local transitionJacketBgScrollScale = 0; -local transitionJacketBgScrollAlpha = 0; -local transitionJacketBgScrollPosX = 0; +local transitionJacketBgScrollScale = 0 +local transitionJacketBgScrollAlpha = 0 +local transitionJacketBgScrollPosX = 0 -local transitionLaserScale = 0; -local transitionLaserY = 0; +--search +local searchPreviousActiveState = false +local searchInfoPreviousActiveState = false +local transitionSearchEnterScale = 0 +local transitionSearchInfoEnterScale = 0 +local transitionSearchBackgroundAlpha = 0 +local transitionSearchbarOffsetY = 0 +local transitionSearchInfoOffsetY = 0 + +local transitionLaserScale = 0 +local transitionLaserY = 0 -- Flash transition (animation) -- Used for flashing the badges -- 0 = minimum brightness; 0.5 = maximum brightness; 1 = minimum brightness again -local transitionFlashScale = 0; -local transitionFlashAlpha = 1; +local transitionFlashScale = 0 +local transitionFlashAlpha = 1 -local isFilterWheelActive = false; -local transitionLeaveScale = 0; -local transitionLeaveReappearTimer = 0; -local TRANSITION_LEAVE_DURATION = 0.1; +local isFilterWheelActive = false +local transitionLeaveScale = 0 +local transitionLeaveReappearTimer = 0 +local TRANSITION_LEAVE_DURATION = 0.1 -- Window variables local resX, resY @@ -175,93 +190,93 @@ local resolutionChange = function(x, y) fullX = portraitWidescreenRatio * y fullY = y - game.Log('resX:' .. resX .. ' // resY:' .. resY .. ' // fullX:' .. fullX .. ' // fullY:' .. fullY, game.LOGGER_ERROR); + game.Log('resX:' .. resX .. ' // resY:' .. resY .. ' // fullX:' .. fullX .. ' // fullY:' .. fullY, game.LOGGER_ERROR) end function getCorrectedIndex(from, offset) - total = #songwheel.songs; + total = #songwheel.songs if (math.abs(offset) > total) then if (offset < 0) then - offset = offset + total*math.floor(math.abs(offset)/total); + offset = offset + total*math.floor(math.abs(offset)/total) else - offset = offset - total*math.floor(math.abs(offset)/total); + offset = offset - total*math.floor(math.abs(offset)/total) end end - index = from + offset; + index = from + offset if index < 1 then index = total + (from+offset) -- this only happens if the offset is negative - end; + end if index > total then - indexesUntilEnd = total - from; + indexesUntilEnd = total - from index = offset - indexesUntilEnd -- this only happens if the offset is positive - end; + end - return index; -end; + return index +end function getJacketImage(song) if not jacketCache[song.id] or jacketCache[song.id]==defaultJacketImage then jacketCache[song.id] = gfx.LoadImageJob(song.difficulties[ math.min(selectedDifficulty, #song.difficulties) - ].jacketPath, defaultJacketImage, 500, 500); + ].jacketPath, defaultJacketImage, 500, 500) end - return jacketCache[song.id]; + return jacketCache[song.id] end function getGradeImageForScore(score) - local gradeImage = gradeImages.none; - local bestGradeCutoff = 0; + local gradeImage = gradeImages.none + local bestGradeCutoff = 0 for gradeName, scoreCutoff in pairs(gradeCutoffs) do if scoreCutoff <= score then if scoreCutoff > bestGradeCutoff then - gradeImage = gradeImages[gradeName]; - bestGradeCutoff = scoreCutoff; + gradeImage = gradeImages[gradeName] + bestGradeCutoff = scoreCutoff end end end - return gradeImage; + return gradeImage end function drawLaserAnim() - gfx.Save(); + gfx.Save() gfx.BeginPath() - gfx.Scissor(0, transitionLaserY, desw, 100); + gfx.Scissor(0, transitionLaserY, desw, 100) gfx.ImageRect(0, 0, desw, desh, laserAnimBaseImage, 1, 0) - gfx.Restore(); + gfx.Restore() end function drawBackground(deltaTime) Background.draw(deltaTime) - local song = songwheel.songs[selectedIndex]; - local diff = song and song.difficulties[selectedDifficulty] or false; + local song = songwheel.songs[selectedIndex] + local diff = song and song.difficulties[selectedDifficulty] or false if (not isFilterWheelActive and transitionLeaveReappearTimer == 0) then -- If the score for song exists if song and diff then - local jacketImage = getJacketImage(song); + local jacketImage = getJacketImage(song) gfx.BeginPath() gfx.ImageRect(transitionJacketBgScrollPosX, 0, 900, 900, jacketImage or defaultJacketImage, transitionJacketBgScrollAlpha, 0) - gfx.BeginPath(); - gfx.FillColor(0,0,0,math.floor(transitionJacketBgScrollAlpha*64)); - gfx.Rect(0,0,900,900); - gfx.Fill(); - gfx.ClosePath(); + gfx.BeginPath() + gfx.FillColor(0,0,0,math.floor(transitionJacketBgScrollAlpha*64)) + gfx.Rect(0,0,900,900) + gfx.Fill() + gfx.ClosePath() end end - gfx.BeginPath(); + gfx.BeginPath() gfx.ImageRect(0, 0, desw, desh, dataPanelImage, 1, 0) drawLaserAnim() @@ -283,19 +298,19 @@ function drawBackground(deltaTime) end -function drawSong(song, y, id) - if (not song) then return end; +function drawSong(song, y) + if (not song) then return end local songX = desw/2+28 local selectedSongDifficulty = song.difficulties[math.min(selectedDifficulty, #song.difficulties)] -- Limit selecting difficulty that is above the number that the song has - + if not selectedSongDifficulty then - return; + return end - local bestScore; + local bestScore if selectedSongDifficulty.scores then - bestScore = selectedSongDifficulty.scores[1]; + bestScore = selectedSongDifficulty.scores[1] end -- Draw the bg for the song plate @@ -303,7 +318,7 @@ function drawSong(song, y, id) gfx.ImageRect(songX, y, 515, 172, songPlateBg, 1, 0) -- Draw jacket - local jacketImage = getJacketImage(song); + local jacketImage = getJacketImage(song) gfx.BeginPath() gfx.ImageRect(songX+4, y+4, 163, 163, jacketImage or defaultJacketImage, 1, 0) @@ -313,93 +328,92 @@ function drawSong(song, y, id) -- Draw the difficulty notch background gfx.BeginPath() - local diffIndex = GetDisplayDifficulty(selectedSongDifficulty.jacketPath, selectedSongDifficulty.difficulty) + local diffIndex = Charting.GetDisplayDifficulty(selectedSongDifficulty.jacketPath, selectedSongDifficulty.difficulty) gfx.ImageRect(songX, y+95, 83, 74, difficultyLabelImages[diffIndex], 1, 0) -- Draw the difficulty level number gfx.BeginPath() Numbers.draw_number(songX+30, y+125, 1.0, selectedSongDifficulty.level, 2, difficultyNumbers, false, 0.65, 1) - -- Draw song title + -- Draw song title + gfx.FontSize(24) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - newtext.textmaker(song.title,35.35,421.5,songX+90,y+155,417,100, - songX+60,-10, - 1 - ) + gfx.Text(song.title, songX+90, y+155) -- Draw score badge - local badgeImage = badgeImages[1]; + local badgeImage = badgeImages[1] if selectedSongDifficulty.topBadge then - badgeImage = badgeImages[selectedSongDifficulty.topBadge+1]; + badgeImage = badgeImages[selectedSongDifficulty.topBadge+1] end - local badgeAlpha = 1; + local badgeAlpha = 1 if (selectedSongDifficulty.topBadge >= 3) then - badgeAlpha = transitionFlashAlpha; -- If hard clear or above, flash the badge + badgeAlpha = transitionFlashAlpha -- If hard clear or above, flash the badge end gfx.BeginPath() gfx.ImageRect(songX+282, y+44, 79, 69, badgeImage, badgeAlpha, 0) -- Draw grade - local gradeImage = gradeImages.none; - local gradeAlpha = 1; + local gradeImage = gradeImages.none + local gradeAlpha = 1 if bestScore then gradeImage = getGradeImageForScore(bestScore.score) if (bestScore.score >= gradeCutoffs.S) then - gradeAlpha = transitionFlashAlpha; -- If S, flash the badge + gradeAlpha = transitionFlashAlpha -- If S, flash the badge end end - gfx.BeginPath(); - gfx.ImageRect(songX+391, y+47, 60, 60, gradeImage, gradeAlpha, 0); + gfx.BeginPath() + gfx.ImageRect(songX+391, y+47, 60, 60, gradeImage, gradeAlpha, 0) -- Draw top 50 label if applicable if (top50diffs[selectedSongDifficulty.id]) then - gfx.BeginPath(); - gfx.ImageRect(songX+82, y+109, 506*0.85, 26*0.85, top50OverlayImage, 1, 0); + gfx.BeginPath() + gfx.ImageRect(songX+82, y+109, 506*0.85, 26*0.85, top50OverlayImage, 1, 0) end end function drawSongList() - gfx.GlobalAlpha(1-transitionLeaveScale); + gfx.GlobalAlpha(1-transitionLeaveScale) - local numOfSongsAround = 7; -- How many songs should be up and how many should be down of the selected one + local numOfSongsAround = 7 -- How many songs should be up and how many should be down of the selected one - local yOffset = transitionScrollOffsetY; + local yOffset = transitionScrollOffsetY - local i=1; + local i=1 while (i <= numOfSongsAround) do local songIndex = getCorrectedIndex(selectedIndex, -i) - drawSong(songwheel.songs[songIndex], desh/2-songPlateHeight/2-songPlateHeight*i + yOffset, i) - i=i+1; - end; + drawSong(songwheel.songs[songIndex], desh/2-songPlateHeight/2-songPlateHeight*i + yOffset) + i=i+1 + end -- Draw the selected song - drawSong(songwheel.songs[selectedIndex], desh/2-songPlateHeight/2 + yOffset, 10) + drawSong(songwheel.songs[selectedIndex], desh/2-songPlateHeight/2 + yOffset) - i=1; + i=1 while (i <= numOfSongsAround) do local songIndex = getCorrectedIndex(selectedIndex, i) - drawSong(songwheel.songs[songIndex], desh/2-songPlateHeight/2+songPlateHeight*i + yOffset, 10+1) - i=i+1; - end; - gfx.GlobalAlpha(1); + drawSong(songwheel.songs[songIndex], desh/2-songPlateHeight/2+songPlateHeight*i + yOffset) + i=i+1 + end + + gfx.GlobalAlpha(1) end function drawData() -- Draws the song data on the left panel - - if isFilterWheelActive or transitionLeaveReappearTimer ~= 0 then return false end; - local song = songwheel.songs[selectedIndex]; - local diff = song and song.difficulties[selectedDifficulty] or false; - local bestScore = diff and diff.scores[1]; + if isFilterWheelActive or transitionLeaveReappearTimer ~= 0 then return false end + + local song = songwheel.songs[selectedIndex] + local diff = song and song.difficulties[selectedDifficulty] or false + local bestScore = diff and diff.scores[1] if not song then return false end - local jacketImage = getJacketImage(song); + local jacketImage = getJacketImage(song) gfx.BeginPath() gfx.ImageRect(96, 324, 348, 348, jacketImage or defaultJacketImage, 1, 0) @@ -412,7 +426,7 @@ function drawData() -- Draws the song data on the left panel -- Draw best score gfx.BeginPath() - local scoreNumber = 0; + local scoreNumber = 0 if bestScore then scoreNumber = bestScore.score end @@ -421,76 +435,67 @@ function drawData() -- Draws the song data on the left panel Numbers.draw_number(253, 798, 1.0, scoreNumber, 4, scoreNumbers, true, 0.22, 1.12) -- Draw grade - local gradeImage = gradeImages.none; - local gradeAlpha = transitionAfterscrollGradeAlpha; + local gradeImage = gradeImages.none + local gradeAlpha = transitionAfterscrollGradeAlpha if bestScore then gradeImage = getGradeImageForScore(bestScore.score) if (transitionAfterscrollGradeAlpha == 1 and bestScore.score >= gradeCutoffs.S) then - gradeAlpha = transitionFlashAlpha; -- If S, flash the badge + gradeAlpha = transitionFlashAlpha -- If S, flash the badge end end - gfx.BeginPath(); - gfx.ImageRect(360, 773, 45, 45, gradeImage, gradeAlpha, 0); + gfx.BeginPath() + gfx.ImageRect(360, 773, 45, 45, gradeImage, gradeAlpha, 0) -- Draw badge - badgeImage = badgeImages[diff.topBadge+1]; + badgeImage = badgeImages[diff.topBadge+1] - local badgeAlpha = transitionAfterscrollBadgeAlpha; + local badgeAlpha = transitionAfterscrollBadgeAlpha if (transitionAfterscrollBadgeAlpha == 1 and diff.topBadge >= 3) then - badgeAlpha = transitionFlashAlpha; -- If hard clear or above, flash the badge, but only after the initial transition + badgeAlpha = transitionFlashAlpha -- If hard clear or above, flash the badge, but only after the initial transition end gfx.BeginPath() gfx.ImageRect(425, 724, 93/1.1, 81/1.1, badgeImage, badgeAlpha, 0) gfx.Restore() + + -- Draw BPM + gfx.BeginPath() + gfx.FontSize(24) + gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) + gfx.Save() + gfx.LoadSkinFont('Digital-Serial-Bold.ttf') + gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha) -- TODO: split this out + gfx.Text(song.bpm, 85, 920) + gfx.Restore() + -- Draw song title + gfx.FontSize(28) + gfx.GlobalAlpha(transitionAfterscrollTextSongTitle) + gfx.Text(song.title, 30+(1-transitionAfterscrollTextSongTitle)*20, 955) + + -- Draw artist + gfx.GlobalAlpha(transitionAfterscrollTextSongArtist) + gfx.Text(song.artist, 30+(1-transitionAfterscrollTextSongArtist)*30, 997) + local hiScore = diff.scores[1]; - + gfx.BeginPath() gfx.LoadSkinFont('Digital-Serial-Bold.ttf') gfx.FontSize(21) gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT + gfx.TEXT_ALIGN_MIDDLE) local gaugePct = (hiScore and hiScore.gauge*100 or nil) local percentText = gaugePct and string.format("%.1f", gaugePct) or " " - gfx.Text(percentText.." %", 335, 838) + gfx.Text(percentText.." %", 335+(1-transitionAfterscrollTextSongArtist)*30, 838) - -- Draw BPM - gfx.BeginPath(); - gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.Save() - gfx.LoadSkinFont('Digital-Serial-Bold.ttf') - gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha) -- TODO: split this out - newtext.textmaker(song.bpm,24,110,85,920,99,110, - -50,-10, - 2 -) - gfx.Restore() - - -- Draw song title - gfx.GlobalAlpha(transitionAfterscrollTextSongTitle); - newtext.textmaker(song.title,28,495.5,30+(1-transitionAfterscrollTextSongTitle)*20,955,495,100, - 0,-10, - 3 - ) - - - -- Draw artist - gfx.GlobalAlpha(transitionAfterscrollTextSongArtist); - newtext.textmaker(song.artist,28,495.5,30+(1-transitionAfterscrollTextSongArtist)*30,997,495,100, - 0,-10, - 4 - ) - - - gfx.GlobalAlpha(1); + gfx.GlobalAlpha(1) -- Draw difficulties local DIFF_X_START = 98.5 - local DIFF_GAP = 114.8; - gfx.GlobalAlpha(transitionAfterscrollDifficultiesAlpha); + local DIFF_GAP = 114.8 + gfx.GlobalAlpha(transitionAfterscrollDifficultiesAlpha) for i, diff in ipairs(song.difficulties) do gfx.BeginPath() @@ -503,15 +508,15 @@ function drawData() -- Draws the song data on the left panel Numbers.draw_number(85+(index-1)*DIFF_GAP, 1085, 1.0, diff.level, 2, difficultyNumbers, false, 0.8, 1) local diffLabelImage = difficultyLabelUnderImages[ - GetDisplayDifficulty(diff.jacketPath, diff.difficulty) - ]; + Charting.GetDisplayDifficulty(diff.jacketPath, diff.difficulty) + ] local tw, th = gfx.ImageSize(diffLabelImage) tw=tw*0.9 th=th*0.9 gfx.BeginPath() gfx.ImageRect(DIFF_X_START+(index-1)*DIFF_GAP-tw/2, 1050, tw, th, diffLabelImage, 1, 0) end - gfx.GlobalAlpha(1); + gfx.GlobalAlpha(1) -- Scoreboard @@ -519,18 +524,12 @@ function drawData() -- Draws the song data on the left panel drawLocalLeaderboard(diff) drawIrLeaderboard() - + gfx.FontSize(22) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha); - newtext.textmaker(diff.effector,22,236.5,270+(1-transitionAfterscrollDataOverlayAlpha)*20,1180,236,100, - 0,-10, - 5 - ) - newtext.textmaker(diff.illustrator,22,236.5,270+(1-transitionAfterscrollDataOverlayAlpha)*30,1210,236,100, - 0,-10, - 6 -) - gfx.GlobalAlpha(1); + gfx.GlobalAlpha(transitionAfterscrollDataOverlayAlpha) + gfx.Text(diff.effector, 270, 1180) -- effected by + gfx.Text(diff.illustrator, 270, 1210) -- illustrated by + gfx.GlobalAlpha(1) end @@ -538,109 +537,110 @@ function drawLocalLeaderboard(diff) gfx.LoadSkinFont('Digital-Serial-Bold.ttf') gfx.FontSize(26) - local scoreBoardX = 75; - local scoreBoardY = 1250; + local scoreBoardX = 75 + local scoreBoardY = 1250 - local sbBarWidth = 336*1.2; - local sbBarHeight = 33; + local sbBarWidth = 336*1.2 + local sbBarHeight = 33 - local sbBarContentLeftX = scoreBoardX + 80; - local sbBarContentRightX = scoreBoardX + sbBarWidth/2 + 30; + local sbBarContentLeftX = scoreBoardX + 80 + local sbBarContentRightX = scoreBoardX + sbBarWidth/2 + 30 -- Draw the header - gfx.BeginPath(); - gfx.ImageRect(scoreBoardX, scoreBoardY, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0); + gfx.BeginPath() + gfx.ImageRect(scoreBoardX, scoreBoardY, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0) - gfx.BeginPath(); - gfx.ImageRect(205, 1252.5, 800*0.045, 600*0.045, crownImage, 1, 0); + gfx.BeginPath() + gfx.ImageRect(205, 1252.5, 800*0.045, 600*0.045, crownImage, 1, 0) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.BeginPath(); - gfx.Text("LOCAL TOP", sbBarContentRightX, scoreBoardY + sbBarHeight/2); + gfx.BeginPath() + gfx.Text("LOCAL TOP", sbBarContentRightX, scoreBoardY + sbBarHeight/2) for i = 1, 5, 1 do - gfx.BeginPath(); - gfx.ImageRect(scoreBoardX, scoreBoardY + i*sbBarHeight, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0); + 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.BeginPath() + gfx.Text(game.GetSkinSetting("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.BeginPath() + gfx.Text((diff.scores[i]) and diff.scores[i].score or "- - - - - - - -", sbBarContentRightX, scoreBoardY + sbBarHeight/2 + i*sbBarHeight) end end function drawIrLeaderboard() if not IRData.Active then - return; + return end gfx.LoadSkinFont('Digital-Serial-Bold.ttf') gfx.FontSize(26) - local scoreBoardX = 75; - local scoreBoardY = 1500; + local scoreBoardX = 75 + local scoreBoardY = 1500 - local sbBarWidth = 336*1.2; - local sbBarHeight = 33; + local sbBarWidth = 336*1.2 + local sbBarHeight = 33 - local sbBarContentLeftX = scoreBoardX + 80; - local sbBarContentRightX = scoreBoardX + sbBarWidth/2 + 30; + local sbBarContentLeftX = scoreBoardX + 80 + local sbBarContentRightX = scoreBoardX + sbBarWidth/2 + 30 -- Draw the header - gfx.BeginPath(); - gfx.ImageRect(scoreBoardX, scoreBoardY, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0); + gfx.BeginPath() + gfx.ImageRect(scoreBoardX, scoreBoardY, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE) - gfx.BeginPath(); + gfx.BeginPath() if irRequestStatus == 1 or irRequestStatus == 2 then - gfx.Text("Loading ranking...", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2); - return; + gfx.Text("Loading ranking...", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2) + return end if irRequestStatus == IRData.States.ChartRefused then - gfx.Text("This chart is blacklisted", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2); - return; + gfx.Text("This chart is blacklisted", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2) + return end if irRequestStatus == IRData.States.NotFound then - gfx.Text("This chart is not tracked", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2); - return; + gfx.Text("This chart is not tracked", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2) + return end if #irLeaderboard == 0 then - gfx.Text("This chart has no scores", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2); - return; + gfx.Text("This chart has no scores", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2) + return end gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE) - gfx.BeginPath(); - gfx.Text("IR TOP", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2); + gfx.BeginPath() + gfx.Text("IR TOP", scoreBoardX + (sbBarWidth / 2), scoreBoardY + sbBarHeight/2) for i = 1, 4, 1 do - gfx.BeginPath(); - gfx.ImageRect(scoreBoardX, scoreBoardY + i*sbBarHeight, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0); + gfx.BeginPath() + gfx.ImageRect(scoreBoardX, scoreBoardY + i*sbBarHeight, sbBarWidth, sbBarHeight, scoreBoardBarBgImage, 1, 0) end -- Becuase the scores are in "random order", we have to do this for index, irScore in ipairs(irLeaderboard) do + -- local irScore = irLeaderboard[i] if irScore then - local rank = index; + local rank = index gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE) - gfx.BeginPath(); - gfx.Text(LEADERBOARD_PLACE_NAMES[rank], sbBarContentLeftX-40, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight); + gfx.BeginPath() + gfx.Text(LEADERBOARD_PLACE_NAMES[rank], sbBarContentLeftX-40, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.BeginPath(); - gfx.Text(string.upper(irScore.username), sbBarContentLeftX, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight); + gfx.BeginPath() + gfx.Text(string.upper(irScore.username), sbBarContentLeftX, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight) - gfx.BeginPath(); - gfx.Text(string.format("%d", irScore.score), sbBarContentRightX, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight); + gfx.BeginPath() + gfx.Text(string.format("%d", irScore.score), sbBarContentRightX, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight) - local badgeImage = badgeImages[irScore.lamp+1]; + local badgeImage = badgeImages[irScore.lamp+1] gfx.BeginPath() gfx.ImageRect(scoreBoardX + sbBarWidth - 50, scoreBoardY + sbBarHeight/2 + rank*sbBarHeight - 12.5, 31.6, 27.6, badgeImage, 1, 0) end @@ -651,7 +651,7 @@ function drawFilterInfo(deltatime) gfx.LoadSkinFont('NotoSans-Regular.ttf') if (songwheel.searchInputActive) then - return; + --return end gfx.BeginPath() @@ -665,16 +665,16 @@ function drawFilterInfo(deltatime) gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE) gfx.BeginPath() - gfx.Text(folderLabel or '', 167, 131); + gfx.Text(folderLabel or '', 167, 131) gfx.BeginPath() - gfx.Text(subFolderLabel or '', 195, 166); + gfx.Text(subFolderLabel or '', 195, 166) gfx.BeginPath() gfx.ImageRect(desw - 310 - 5, 108, 310, 75, sortInfoBgImage, 1, 0) gfx.BeginPath() - gfx.Text(sortOptionLabel or '', desw-150, 130); + gfx.Text(sortOptionLabel or '', desw-150, 130) end function drawCursor() @@ -683,33 +683,127 @@ function drawCursor() gfx.BeginPath() local cursorImageIndex = game.GetSkinSetting('_gaugeType') - local cursorImage = cursorImages[cursorImageIndex or 1]; + local cursorImage = cursorImages[cursorImageIndex or 1] gfx.ImageRect(desw / 2 - 14, desh / 2 - 213 / 2, 555, 213, cursorImage, 1, 0) end function drawSearch() - if (not songwheel.searchInputActive) then - return; + if (not songwheel.searchInputActive and searchPreviousActiveState) then + searchPreviousActiveState = false + game.PlaySample('sort_wheel/enter.wav') + elseif (songwheel.searchInputActive and not searchPreviousActiveState) then + searchPreviousActiveState = true + game.PlaySample('sort_wheel/leave.wav') + end + + if (songwheel.searchText ~= '' and searchInfoPreviousActiveState == true) then + searchInfoPreviousActiveState = false + elseif (songwheel.searchText == '' and searchInfoPreviousActiveState == false) then + searchInfoPreviousActiveState = true end - - gfx.BeginPath(); + if (transitionSearchEnterScale == 0) then + return + end + + -- Draw dark overlay over Songwheel + gfx.BeginPath() + gfx.FillColor(0, 0, 0, math.floor(transitionSearchBackgroundAlpha * 192)) + gfx.Rect(0, 0, 1080, 1920) + gfx.Fill() + + -- Draw search info panel + gfx.BeginPath() + local infoResize = 0.855 + local sw, sh = gfx.ImageSize(searchInfoPanelImage) + sw = sw * infoResize + sh = sh * infoResize + local infoXPos = 0 + local infoYStartPos = desh - sh - 772 + 242 + local infoYPos = infoYStartPos + transitionSearchInfoOffsetY + + if (game.GetSkinSetting('gameplay_showSearchControls')) then + gfx.ImageRect(infoXPos, infoYPos, sw, sh, searchInfoPanelImage, transitionSearchBackgroundInfoAlpha, 0) + end + + -- Draw Search is Active text + gfx.BeginPath() + local activeResize = 0.855 + local activew, activeh = gfx.ImageSize(searchActiveImage) + activew = activew * activeResize + activeh = activeh * activeResize + local activeXPos = 0 + local activeYStartPos = desh - sh - 722 + + local activeYPos = activeYStartPos + transitionSearchInfoOffsetY + gfx.ImageRect(activeXPos, activeYPos, activew, activeh, searchActiveImage, 1, 0) + + -- Draw Searchbox + gfx.BeginPath() + local searchResize = 0.8 local tw, th = gfx.ImageSize(searchBgImage) - local xPos = desw-tw/2; - local yPos = 90; + tw = tw * searchResize + th = th * searchResize + local xPos = (desw-tw)/2 + local yStartPos = 170 - gfx.ImageRect(xPos, yPos, tw/2, th/2, searchBgImage, 1, 0) + local yPos = yStartPos - transitionSearchbarOffsetY - gfx.FontSize(32); + gfx.ImageRect(xPos, yPos, tw, th, searchBgImage, 1, 0) + + gfx.FontSize(48) gfx.LoadSkinFont('Digital-Serial-Bold.ttf') gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.Text(songwheel.searchText, xPos+100, yPos+52); + gfx.Text(songwheel.searchText, xPos + 160, yPos + 83.2) +end + +function drawScrollbar() + if isFilterWheelActive or transitionLeaveScale ~= 0 then return end + + -- Scrollbar Background + gfx.BeginPath() + local resize = 0.85 + local lw, lh = gfx.ImageSize(scrollBarBackgroundImage) + local lw = lw * resize + local lh = lh * resize + local xPos = desw-20 + local backgroundYPos = desh/2 - lh/2 + gfx.ImageRect(xPos, backgroundYPos, lw, lh, scrollBarBackgroundImage, 1, 0) + + -- Scrollbar Fill + gfx.BeginPath() + local sw, sh = gfx.ImageSize(scrollBarFillImage) + local sw = sw * resize + local sh = sh * resize + local fillXPos = xPos - 6 + + local minScrollYPos = backgroundYPos + local maxScrollYPos = backgroundYPos + lh - sh + local scrollStep = (maxScrollYPos - minScrollYPos) / (#songwheel.songs - 1) + local scrollbarYOffset = (selectedIndex - 1) * scrollStep + local scrollbarYPos = minScrollYPos + scrollbarYOffset + gfx.ImageRect(fillXPos, scrollbarYPos, sw, sh, scrollBarFillImage, 1, 0) + + -- 1st letter of song title on scroll + gfx.BeginPath() + gfx.FontSize(16) + gfx.LoadSkinFont('Digital-Serial-Bold.ttf') + gfx.Rect(fillXPos-18, scrollbarYPos - 5, 16, 16) + gfx.FillColor(0,0,0,170) + gfx.Fill() + gfx.FillColor(255,255,255) + gfx.TextAlign(gfx.TEXT_ALIGN_MIDDLE + gfx.TEXT_ALIGN_CENTER) + if (songwheel.songs[selectedIndex] ~= nil) then + local title = songwheel.songs[selectedIndex].title; + local letter = string.upper(common.firstAlphaNum(title)) + gfx.Text(letter, fillXPos-10, scrollbarYPos + 5) + end end function refreshIrLeaderboard(deltaTime) if not IRData.Active then - return; + return end if irRequestStatus ~= 1 then -- Only continue if the leaderboard is requesteded, but not loading or loaded. @@ -717,25 +811,25 @@ function refreshIrLeaderboard(deltaTime) end irLeaderboard = {} - local song = songwheel.songs[selectedIndex]; - local diff = song and song.difficulties[selectedDifficulty] or false; + local song = songwheel.songs[selectedIndex] + local diff = song and song.difficulties[selectedDifficulty] or false if (not diff) then - return; + return end if (irLeaderboardsCache[diff.hash]) then - irLeaderboard = irLeaderboardsCache[diff.hash]; - irRequestStatus = 20; - return; + irLeaderboard = irLeaderboardsCache[diff.hash] + irRequestStatus = 20 + return end if (irRequestTimeout > 0) then irRequestTimeout = irRequestTimeout - deltaTime - return; + return end - irRequestStatus = 2; -- Loading + irRequestStatus = 2 -- Loading -- onIrLeaderboardFetched({ -- statusCode = 20, -- body = {} @@ -757,15 +851,15 @@ function dump(o) end function onIrLeaderboardFetched(res) - irRequestStatus = res.statusCode; + irRequestStatus = res.statusCode - local song = songwheel.songs[selectedIndex]; - local diff = song and song.difficulties[selectedDifficulty] or false; + local song = songwheel.songs[selectedIndex] + local diff = song and song.difficulties[selectedDifficulty] or false game.Log(diff.hash, game.LOGGER_ERROR) if res.statusCode == IRData.States.Success then game.Log('Raw IR reposonse: ' .. dump(res.body), game.LOGGER_ERROR) - local tempIrLB = res.body; + local tempIrLB = res.body table.sort(tempIrLB, function (a,b) -- game.Log(a.score .. ' ?? ' .. b.score, game.LOGGER_ERROR) @@ -776,8 +870,8 @@ function onIrLeaderboardFetched(res) -- irLeaderboard[tempScore.ranking] = tempScore -- end - irLeaderboard = tempIrLB; - irLeaderboardsCache[diff.hash] = irLeaderboard; + irLeaderboard = tempIrLB + irLeaderboardsCache[diff.hash] = irLeaderboard game.Log(dump(irLeaderboard), game.LOGGER_ERROR) else @@ -798,48 +892,83 @@ function tickTransitions(deltaTime) transitionAfterscrollScale = transitionAfterscrollScale + deltaTime / 15 end else - transitionAfterscrollScale = 1; + transitionAfterscrollScale = 1 end if scrollingUp then - transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * songPlateHeight; + transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * songPlateHeight else - transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * -songPlateHeight; + transitionScrollOffsetY = Easing.inQuad(1-transitionScrollScale) * -songPlateHeight end if transitionAfterscrollScale < 0.02 then transitionAfterscrollDataOverlayAlpha = math.min(1, transitionAfterscrollScale / 0.02) else - transitionAfterscrollDataOverlayAlpha = 1; + transitionAfterscrollDataOverlayAlpha = 1 end + -- Searchbar offsets and alpha + if not searchPreviousActiveState then + if transitionSearchEnterScale > 0 then + transitionSearchEnterScale = transitionSearchEnterScale - deltaTime / 0.5 -- transition should last for that time in seconds + else + transitionSearchEnterScale = 0 + end + else + if transitionSearchEnterScale < 1 then + transitionSearchEnterScale = transitionSearchEnterScale + deltaTime / 0.5 -- transition should last for that time in seconds + else + transitionSearchEnterScale = 1 + end + end + + transitionSearchInfoOffsetY = Easing.inOutQuad(1 - transitionSearchEnterScale) * 1680 + transitionSearchbarOffsetY = Easing.inOutQuad(1 - transitionSearchEnterScale) * 300 + transitionSearchBackgroundAlpha = Easing.inOutQuad(transitionSearchEnterScale) + + if not searchInfoPreviousActiveState then + if transitionSearchInfoEnterScale > 0 then + transitionSearchInfoEnterScale = transitionSearchInfoEnterScale - deltaTime / 0.25 -- transition should last for that time in seconds + else + transitionSearchInfoEnterScale = 0 + end + else + if transitionSearchInfoEnterScale < 1 then + transitionSearchInfoEnterScale = transitionSearchInfoEnterScale + deltaTime / 0.25 -- transition should last for that time in seconds + else + transitionSearchInfoEnterScale = 1 + end + end + + transitionSearchBackgroundInfoAlpha = Easing.inOutQuad(transitionSearchInfoEnterScale) + -- Grade alpha if transitionAfterscrollScale >= 0.03 and transitionAfterscrollScale < 0.033 then - transitionAfterscrollGradeAlpha = 0.5; + transitionAfterscrollGradeAlpha = 0.5 elseif transitionAfterscrollScale >= 0.04 then - transitionAfterscrollGradeAlpha = 1; + transitionAfterscrollGradeAlpha = 1 else - transitionAfterscrollGradeAlpha = 0; + transitionAfterscrollGradeAlpha = 0 end -- Badge alpha if transitionAfterscrollScale >= 0.032 and transitionAfterscrollScale < 0.035 then - transitionAfterscrollBadgeAlpha = 0.5; + transitionAfterscrollBadgeAlpha = 0.5 elseif transitionAfterscrollScale >= 0.042 then - transitionAfterscrollBadgeAlpha = 1; + transitionAfterscrollBadgeAlpha = 1 else - transitionAfterscrollBadgeAlpha = 0; + transitionAfterscrollBadgeAlpha = 0 end -- Song title alpha and pos if transitionAfterscrollScale < 0.025 then - transitionAfterscrollTextSongTitle = Easing.outQuad(math.min(1, (transitionAfterscrollScale) / 0.025)); + transitionAfterscrollTextSongTitle = Easing.outQuad(math.min(1, (transitionAfterscrollScale) / 0.025)) else transitionAfterscrollTextSongTitle = 1 end -- Song artist alpha and pos if transitionAfterscrollScale < 0.025 then - transitionAfterscrollTextSongArtist = Easing.outQuad(math.min(1, (transitionAfterscrollScale) / 0.025)); + transitionAfterscrollTextSongArtist = Easing.outQuad(math.min(1, (transitionAfterscrollScale) / 0.025)) else transitionAfterscrollTextSongArtist = 1 end @@ -848,7 +977,7 @@ function tickTransitions(deltaTime) if transitionAfterscrollScale < 0.025 then transitionAfterscrollDifficultiesAlpha = math.min(1, transitionAfterscrollScale / 0.025) else - transitionAfterscrollDifficultiesAlpha = 1; + transitionAfterscrollDifficultiesAlpha = 1 end -- Jacket bg animation @@ -859,18 +988,18 @@ function tickTransitions(deltaTime) end if transitionJacketBgScrollScale < 0.05 or transitionJacketBgScrollScale >= 1 then - transitionJacketBgScrollAlpha = 0; + transitionJacketBgScrollAlpha = 0 elseif transitionJacketBgScrollScale >= 0.05 and transitionJacketBgScrollScale < 0.1 then - transitionJacketBgScrollAlpha = math.min(1, (transitionJacketBgScrollScale-0.05) / 0.05); + transitionJacketBgScrollAlpha = math.min(1, (transitionJacketBgScrollScale-0.05) / 0.05) elseif transitionJacketBgScrollScale >= 0.8 and transitionJacketBgScrollScale < 1 then transitionJacketBgScrollAlpha = math.max(0, math.min(1, 1-((transitionJacketBgScrollScale-0.8) / 0.05)) - ); + ) else - transitionJacketBgScrollAlpha = 1; + transitionJacketBgScrollAlpha = 1 end - transitionJacketBgScrollPosX = 0+(transitionJacketBgScrollScale*(0.8/1))*-300; + transitionJacketBgScrollPosX = 0+(transitionJacketBgScrollScale*(0.8/1))*-300 -- Laser anim if transitionLaserScale < 1 then @@ -879,18 +1008,18 @@ function tickTransitions(deltaTime) transitionLaserScale = 0 end - transitionLaserY = desh - math.min(transitionLaserScale * 2 * desh, desh); + transitionLaserY = desh - math.min(transitionLaserScale * 2 * desh, desh) -- Flash transition if transitionFlashScale < 1 then - local songBpm = 120; + local songBpm = 120 if (songwheel.songs[selectedIndex] and game.GetSkinSetting('animations_affectWithBPM')) then - songBpm = songwheel.songs[selectedIndex].bpm; + songBpm = songwheel.songs[selectedIndex].bpm -- Is a variable BPM if (type(songBpm) == "string") then - local s = split(songBpm, '-'); - songBpm = tonumber(s[1]); -- Lowest bpm value + local s = commmon.split(songBpm, '-') + songBpm = tonumber(s[1]) -- Lowest bpm value end end @@ -898,7 +1027,7 @@ function tickTransitions(deltaTime) -- since it cannot parse the number out of that string. Here we implement a fallback, to not crash -- USC on whacky charts. Whacky charters, quit using batshit insane bpm values. It makes me angery >:( if (songBpm == nil) then - songBpm = 120; + songBpm = 120 end transitionFlashScale = transitionFlashScale + deltaTime / (60/songBpm) -- transition should last for that time in seconds @@ -907,9 +1036,9 @@ function tickTransitions(deltaTime) end if transitionFlashScale < 0.5 then - transitionFlashAlpha = transitionFlashScale * 2; + transitionFlashAlpha = transitionFlashScale * 2 else - transitionFlashAlpha = 1-((transitionFlashScale-0.5) * 2); + transitionFlashAlpha = 1-((transitionFlashScale-0.5) * 2) end transitionFlashAlpha = 1+transitionFlashAlpha*0.5 @@ -920,75 +1049,69 @@ function tickTransitions(deltaTime) else transitionLeaveScale = 1 end - transitionLeaveReappearTimer = 1; - transitionAfterscrollScale = 0; -- Keep songwheel in the "afterscroll" state while the filterwheel is active - transitionJacketBgScrollScale = 0; -- Same thing here, just with the jacket bg + transitionLeaveReappearTimer = 1 + transitionAfterscrollScale = 0 -- Keep songwheel in the "afterscroll" state while the filterwheel is active + transitionJacketBgScrollScale = 0 -- Same thing here, just with the jacket bg else if (transitionLeaveReappearTimer ~= 0) then - transitionAfterscrollScale = 0; -- Keep songwheel in the "afterscroll" state while we're waiting on filter wheel to fade out - transitionJacketBgScrollScale = 0; -- Same thing here, just with the jacket bg + transitionAfterscrollScale = 0 -- Keep songwheel in the "afterscroll" state while we're waiting on filter wheel to fade out + transitionJacketBgScrollScale = 0 -- Same thing here, just with the jacket bg end transitionLeaveReappearTimer = transitionLeaveReappearTimer - deltaTime / (TRANSITION_LEAVE_DURATION + 0.05) -- 0.05s is a few frames between the completetion of the fade out and songs reappearing in the AC if (transitionLeaveReappearTimer <= 0) then - transitionLeaveScale = 0; - transitionLeaveReappearTimer = 0; + transitionLeaveScale = 0 + transitionLeaveReappearTimer = 0 end end end -draw_songwheel = function(x,y,w,h, deltaTime) - gfx.Translate(x,y); - gfx.Scale(w/1080, h/1920); - gfx.Scissor(0,0,1080,1920); - - drawBackground(deltaTime); +draw_songwheel = function(deltaTime) + drawBackground(deltaTime) drawSongList() - isFilterWheelActive = game.GetSkinSetting('_songWheelOverlayActive') == 1; + isFilterWheelActive = game.GetSkinSetting('_songWheelOverlayActive') == 1 drawData() drawCursor() drawFilterInfo(deltaTime) - drawSearch(); + drawSearch() - gfx.BeginPath(); + drawScrollbar() + + gfx.BeginPath() gfx.FontSize(18) gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_TOP) local debugScrollingUp= "FALSE" - if scrollingUp then debugScrollingUp = "TRUE" end; - gfx.Text('S_I: ' .. selectedIndex .. ' // S_D: ' .. selectedDifficulty .. ' // S_UP: ' .. debugScrollingUp .. ' // AC_TS: ' .. transitionAfterscrollScale .. ' // L_TS: ' .. transitionLeaveScale .. ' // IR_CODE: ' .. irRequestStatus .. ' // IR_T: ' .. irRequestTimeout, 8, 8); + if scrollingUp then debugScrollingUp = "TRUE" end - gfx.ResetTransform(); + if game.GetSkinSetting('debug_showInformation') then + gfx.Text('S_I: ' .. selectedIndex .. ' // S_D: ' .. selectedDifficulty .. ' // S_UP: ' .. debugScrollingUp .. ' // AC_TS: ' .. transitionAfterscrollScale .. ' // L_TS: ' .. transitionLeaveScale .. ' // IR_CODE: ' .. irRequestStatus .. ' // IR_T: ' .. irRequestTimeout, 8, 8) + end + + gfx.ResetTransform() end render = function (deltaTime) - tickTransitions(deltaTime); - tickScroll(deltaTime); + tickTransitions(deltaTime) game.SetSkinSetting('_currentScreen', 'songwheel') - common.stopMusic(); + Sound.stopMusic() - -- detect resolution change - local resx, resy = game.GetResolution(); - if resx ~= resX or resy ~= resY then - resolutionChange(resx, resy) - end + Dim.updateResolution() - gfx.BeginPath() - 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() + Wallpaper.render() - draw_songwheel((resX - fullX) / 2, 0, fullX, fullY, deltaTime); + Dim.transformToScreenSpace() - refreshIrLeaderboard(deltaTime); + draw_songwheel(deltaTime) + + refreshIrLeaderboard(deltaTime) end songs_changed = function (withAll) @@ -1015,7 +1138,7 @@ songs_changed = function (withAll) totalForce = 0 for i = 1, 50 do if diffs[i] then - top50diffs[diffs[i].id] = true; + top50diffs[diffs[i].id] = true totalForce = totalForce + diffs[i].force end end @@ -1024,33 +1147,33 @@ songs_changed = function (withAll) end set_index = function(newIndex) - transitionScrollScale = 0; - transitionAfterscrollScale = 0; - transitionJacketBgScrollScale = 0; + transitionScrollScale = 0 + transitionAfterscrollScale = 0 + transitionJacketBgScrollScale = 0 game.SetSkinSetting('_songWheelScrollbarTotal', #songwheel.songs) game.SetSkinSetting('_songWheelScrollbarIndex', newIndex) - scrollingUp = false; + scrollingUp = false if ((newIndex > selectedIndex and not (newIndex == #songwheel.songs and selectedIndex == 1)) or (newIndex == 1 and selectedIndex == #songwheel.songs)) then - scrollingUp = true; - end; + scrollingUp = true + end - game.PlaySample('song_wheel/cursor_change.wav'); + game.PlaySample('song_wheel/cursor_change.wav') - selectedIndex = newIndex; -end; + selectedIndex = newIndex +end set_diff = function(newDiff) if newDiff ~= selectedDifficulty then - jacketCache = {}; -- Clear the jacket cache for the new diff jackets + jacketCache = {} -- Clear the jacket cache for the new diff jackets - game.PlaySample('song_wheel/diff_change.wav'); + game.PlaySample('song_wheel/diff_change.wav') end - selectedDifficulty = newDiff; + selectedDifficulty = newDiff irLeaderboard = {} - irRequestStatus = 1; + irRequestStatus = 1 irRequestTimeout = 2 -end; \ No newline at end of file +end \ No newline at end of file diff --git a/scripts/songselect/sortwheel.lua b/scripts/songselect/sortwheel.lua index ad4fe9b..4178fe2 100644 --- a/scripts/songselect/sortwheel.lua +++ b/scripts/songselect/sortwheel.lua @@ -1,4 +1,3 @@ -require('common') local Easing = require('common.easing'); local resx, resy = game.GetResolution() diff --git a/scripts/songtransition.lua b/scripts/songtransition.lua index 7258f22..e84d9b4 100644 --- a/scripts/songtransition.lua +++ b/scripts/songtransition.lua @@ -1,6 +1,7 @@ -local common = require('common.common'); -local Numbers = require('common.numbers') +local common = require('common.util'); +local Sound = require("common.sound") +local Numbers = require('components.numbers') game.LoadSkinSample('song_transition_screen/transition_enter.wav'); @@ -62,7 +63,7 @@ end function render(deltaTime) if not wasEnterSfxPlayed then - common.stopMusic(); + Sound.stopMusic(); game.PlaySample('song_transition_screen/transition_enter.wav'); wasEnterSfxPlayed = true; end diff --git a/scripts/titlescreen.lua b/scripts/titlescreen.lua index 7e02365..b50be37 100644 --- a/scripts/titlescreen.lua +++ b/scripts/titlescreen.lua @@ -1,446 +1,97 @@ +require("common.globals") +local Common = require("common.util") -require('common') -local Footer = require('components.footer'); -local Background = require('components.background'); +local bootScreen = require('titlescreen.boot') +local splashScreen = require('titlescreen.splash') +local titleScreen = require('titlescreen.title') +local modeSelectScreen = require('titlescreen.modeselect') +local serviceScreen = require('titlescreen.service') -local lang = require("language.call") - -local cursorIndex = 3; -local buttonHeight = 128 + 16; - -local SELECTOR_BAR_OFFSET_FROM_CENTER = 128; - -local BAR_ALPHA = 191; -local HEADER_HEIGHT = 100 - -local buttons = nil -local resx, resy = game.GetResolution() -local desw = 1080 -local desh = 1920 -local scale; - -local backgroundImage = gfx.CreateSkinImage("bg_pattern.png", gfx.IMAGE_REPEATX | gfx.IMAGE_REPEATY) -local headerTitleImage = gfx.CreateSkinImage('titlescreen/title.png', 0); -local selectorBgImage = gfx.CreateSkinImage('titlescreen/selector_bg.png', 0); -local selectorArrowsImage = gfx.CreateSkinImage( - 'titlescreen/selector_arrows.png', 0); - -local unselectedButtonImage = gfx.CreateSkinImage( - 'titlescreen/unselected_button.png', 0); - -local selectedButtonBgImage = gfx.CreateSkinImage( - 'titlescreen/selected_button_bg.png', 0); -local selectedButtonOverImage = gfx.CreateSkinImage( - 'titlescreen/selected_button_over.png', 0); - -local skillLabelImage = gfx.CreateSkinImage('titlescreen/labels/skill.png', 0); -local friendLabelImage = gfx.CreateSkinImage('titlescreen/labels/friend.png', 0); -local normalLabelImage = gfx.CreateSkinImage('titlescreen/labels/normal.png', 0); -local nauticaLabelImage = gfx.CreateSkinImage('titlescreen/labels/nautica.png', - 0); -local settingsLabelImage = gfx.CreateSkinImage( - 'titlescreen/labels/settings.png', 0); -local exitLabelImage = gfx.CreateSkinImage('titlescreen/labels/exit.png', 0); - -local creww = game.GetSkinSetting("single_idol") - --- ANIMS -local idolAnimation = gfx.LoadSkinAnimation('crew/anim/'..creww, 1 / 30, 0, true); - --- AUDIO -game.LoadSkinSample('titlescreen/bgm.wav'); -game.LoadSkinSample('titlescreen/cursor_change.wav'); -game.LoadSkinSample('titlescreen/cursor_select.wav'); - -local selectorDescriptionLabel = gfx.CreateLabel(lang.Start.desc , 22, 0); - -local selectorLegendScrollLabel = gfx.CreateLabel(lang.Start.sc , 20, 0); -local selectorLegendSelectLabel = gfx.CreateLabel(lang.Start.st3 , 20, 0); - -local scrollTransitionScale = 1; -- Goes from 0 to 1 when transition is happening, sits at 1 when it's not. -local buttonsMovementScale = 0; -- Basically same as `scrollTransitionScale` but with a +/- sign for the scroll direction and goes from 1 to 0 - -local idolAnimTransitionScale = 0; - -local oldCursorIndex = 3; -local scrollingUp = false; -local playedBgm = false; - --- Window variables -local resX, resY - --- Aspect Ratios -local landscapeWidescreenRatio = 16 / 9 -local landscapeStandardRatio = 4 / 3 -local portraitWidescreenRatio = 9 / 16 - --- Portrait sizes -local fullX, fullY - -local resolutionChange = function(x, y) - resX = x - resY = y - fullX = portraitWidescreenRatio * y - fullY = y -end - -function resetLayoutInformation() - resx, resy = game.GetResolution() - desw = 1080 - desh = 1920 - scale = resx / desw -end - -draw_button = function(button, x, y, selected, index) - local labelImage = button[1]; - local labelWidth = button[2]; - local descriptionText = button[4]; - - if (selected) then - -- Draw button background - gfx.BeginPath(); - gfx.ImageRect(x, y + (196 / 2 * (1 - scrollTransitionScale)), 505, - 196 * scrollTransitionScale, selectedButtonBgImage, 1, 0); - -- Draw button main label - gfx.BeginPath(); - gfx.ImageRect(x + 256 - (labelWidth / 2), - (y + 58) + (64 / 2 * (1 - scrollTransitionScale)), - labelWidth, 64 * scrollTransitionScale, labelImage, 1, 0); - - -- Draw description - - gfx.GlobalAlpha((scrollTransitionScale - 0.8) * 5) - gfx.TextAlign(gfx.TEXT_ALIGN_CENTER + gfx.TEXT_ALIGN_MIDDLE) - gfx.FontSize(40); - gfx.BeginPath(); - gfx.Text(descriptionText, x + 256, y + 28); - gfx.GlobalAlpha(1) - - -- Draw the glow overlay - gfx.BeginPath(); - gfx.ImageRect(x + 2, (y - 42) + (277 / 2 * (1 - scrollTransitionScale)), - 501, 277 * scrollTransitionScale, selectedButtonOverImage, - 1, 0); - else - if scrollingUp then - if (index == 3 or index == 0) then - gfx.GlobalAlpha(1 - scrollTransitionScale); - end - if (index == 2 or index == 5) then - gfx.GlobalAlpha(scrollTransitionScale); - end - else - if (index == 3 or index == 6) then - gfx.GlobalAlpha(1 - scrollTransitionScale); - end - if (index == 1 or index == 4) then - gfx.GlobalAlpha(scrollTransitionScale); - end - end - -- Draw button background - gfx.BeginPath(); - gfx.ImageRect(x, y + buttonsMovementScale * buttonHeight, 1026 / 2, - 257 / 2, unselectedButtonImage, 1, 0); - - -- Draw button main label - gfx.BeginPath(); - gfx.ImageRect(x + 64, y + 28 + buttonsMovementScale * buttonHeight, - labelWidth, 64, labelImage, 1, 0); - -- Draw description - gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE) - gfx.FontSize(28); - gfx.BeginPath(); - gfx.Text(descriptionText, x + 64, - y + 18 + buttonsMovementScale * buttonHeight); - - gfx.GlobalAlpha(1) - end -end; - -draw_buttons = function() - indexes = { - getCorrectedButtonIndex(cursorIndex, -2), - getCorrectedButtonIndex(cursorIndex, -1), cursorIndex, - getCorrectedButtonIndex(cursorIndex, 1), - getCorrectedButtonIndex(cursorIndex, 2) +local screens = { + boot = { + screen = bootScreen + }, + splash = { + screen = splashScreen + }, + title = { + screen = titleScreen + }, + mode_select = { + screen = modeSelectScreen + }, + service = { + screen = serviceScreen } +} - local yBase = desh / 2 + SELECTOR_BAR_OFFSET_FROM_CENTER; +local currentScreen = game.GetSkinSetting("animations_skipIntro") and screens.title or screens.boot -- show boot screen if skipIntro is not set - centerButtonY = yBase - buttonHeight / 2 - 28; -- to fit with the selector bg - marginFromDesHCenter = 128; - - if scrollingUp then - draw_button(buttons[indexes[5]], desw - 512, - yBase - marginFromDesHCenter - buttonHeight * 3, false, 0); -- Placeholder for fadeout transition - end - - draw_button(buttons[indexes[1]], desw - 512, - yBase - marginFromDesHCenter - buttonHeight * 2, false, 1); - draw_button(buttons[indexes[2]], desw - 512, - yBase - marginFromDesHCenter - buttonHeight, false, 2); - - draw_button(buttons[indexes[3]], desw - 512, centerButtonY, true); -- The main selected center button - - if scrollingUp then - draw_button(buttons[indexes[3]], desw - 512, - yBase + marginFromDesHCenter - buttonHeight, false, 3); -- Placeholder for transition that goes to the bottom - else - draw_button(buttons[indexes[3]], desw - 512, centerButtonY, false, 3); -- Placeholder for transition that goes to the top - end - - draw_button(buttons[indexes[4]], desw - 512, - yBase + marginFromDesHCenter + 10, false, 4); - draw_button(buttons[indexes[5]], desw - 512, - yBase + marginFromDesHCenter + buttonHeight + 10, false, 5); - - if not scrollingUp then - draw_button(buttons[indexes[1]], desw - 512, - yBase + marginFromDesHCenter + buttonHeight * 2, false, 6); - end -end; - -function getCorrectedButtonIndex(from, offset) - buttonsNum = #buttons; - - index = from + offset; - - if index < 1 then - index = buttonsNum + (from + offset) -- this only happens if the offset is negative - end - - if index > buttonsNum then - indexesUntilEnd = buttonsNum - from; - index = offset - indexesUntilEnd -- this only happens if the offset is positive - end - - return index; -end - -function drawTexts() - - currentFullDescriptionText = buttons[cursorIndex][5]; - gfx.BeginPath(); - gfx.UpdateLabel(selectorDescriptionLabel, currentFullDescriptionText, 22) - - gfx.BeginPath(); --- gfx.UpdateLabel(selectorLegendScrollLabel, 'SCROLL', 20); - - -- descriptionAlpha = math.abs(selectedButtonScaleY - 0.5) * 2; - gfx.TextAlign(gfx.TEXT_ALIGN_LEFT + gfx.TEXT_ALIGN_MIDDLE); - - -- Description - gfx.FillColor(255, 255, 255, math.floor(scrollTransitionScale * 255)); - gfx.BeginPath(); - gfx.DrawLabel(selectorDescriptionLabel, 64, - desh / 2 + SELECTOR_BAR_OFFSET_FROM_CENTER - 52); - - -- Legend on the selector - gfx.FillColor(217, 177, 126); - - gfx.BeginPath(); - gfx.DrawLabel(selectorLegendScrollLabel, 118, - desh / 2 + SELECTOR_BAR_OFFSET_FROM_CENTER + 56); - - gfx.BeginPath(); - gfx.DrawLabel(selectorLegendSelectLabel, 360, - desh / 2 + SELECTOR_BAR_OFFSET_FROM_CENTER + 56); - - gfx.FillColor(255, 255, 255); -end - -function setButtons() - if buttons == nil then - buttons = {} - buttons[1] = { - skillLabelImage, 412, Menu.Challenges, - lang.Challanges.ch, lang.Challanges.ch1 - } - buttons[2] = { - friendLabelImage, 169, Menu.Multiplayer, - lang.Multiplayer.mp, lang.Multiplayer.mp2 - } - buttons[3] = { - normalLabelImage, 210, Menu.Start, - lang.Start.st, lang.Start.st2 - } - buttons[4] = { - nauticaLabelImage, 230, Menu.DLScreen, - lang.Nautica.dls, lang.Nautica.dls2 - } - buttons[5] = { - settingsLabelImage, 247, Menu.Settings, - lang.Settings.se, lang.Settings.se1 - } - buttons[6] = { - exitLabelImage, 110, Menu.Exit, - lang.Exit.ex, lang.Exit.ex2 - } - 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, headerTitleImage, 1, 0) -end - -function sign(x) return x > 0 and 1 or x < 0 and -1 or 0 end - -function roundToZero(x) - if x < 0 then - return math.ceil(x) - elseif x > 0 then - return math.floor(x) - else - return 0 - end -end - -function deltaKnob(delta) +local function deltaKnob(delta) if math.abs(delta) > 1.5 * math.pi then - return delta + 2 * math.pi * sign(delta) * -1 + return delta + 2 * math.pi * Common.sign(delta) * -1 end return delta end local lastKnobs = nil local knobProgress = 0 -function handle_controller() +local function handleKnobs() + if not currentScreen.screen.onKnobsChange then + return + end + if lastKnobs == nil then lastKnobs = {game.GetKnob(0), game.GetKnob(1)} else local newKnobs = {game.GetKnob(0), game.GetKnob(1)} - knobProgress = knobProgress - deltaKnob(lastKnobs[1] - newKnobs[1]) * - 1.2 - knobProgress = knobProgress - deltaKnob(lastKnobs[2] - newKnobs[2]) * - 1.2 + knobProgress = knobProgress - deltaKnob(lastKnobs[1] - newKnobs[1]) * 1.2 + knobProgress = knobProgress - deltaKnob(lastKnobs[2] - newKnobs[2]) * 1.2 lastKnobs = newKnobs if math.abs(knobProgress) > 1 then - cursorIndex = (((cursorIndex - 1) + roundToZero(knobProgress)) % - #buttons) + 1 - - scrollTransitionScale = 0; -- Reset transitions and play them - - scrollingUp = false; - if ((cursorIndex > oldCursorIndex and - not (cursorIndex == 6 and oldCursorIndex == 1)) or - (cursorIndex == 1 and oldCursorIndex == 6)) then - scrollingUp = true; + if (knobProgress < 0) then + -- Negative + currentScreen.screen.onKnobsChange(-1) + else + -- Positive + currentScreen.screen.onKnobsChange(1) end - - game.PlaySample('titlescreen/cursor_change.wav'); - - oldCursorIndex = cursorIndex; - - knobProgress = knobProgress - roundToZero(knobProgress) + knobProgress = knobProgress - Common.roundToZero(knobProgress) end end end -draw_titlescreen = function (x, y, w, h, deltaTime) - gfx.Scissor(x,y,w,h); - gfx.Translate(x,y); - gfx.Scale(w/1080, h/1920); - - gfx.LoadSkinFont("segoeui.ttf") - - -- Draw background - gfx.BeginPath(); - Background.draw(deltaTime) - - local idolAnimTickRes = gfx.TickAnimation(idolAnimation, deltaTime); - if idolAnimTickRes == 1 then - gfx.GlobalAlpha(idolAnimTransitionScale); - - idolAnimTransitionScale = idolAnimTransitionScale + 1 / 60; - if (idolAnimTransitionScale > 1) then - idolAnimTransitionScale = 1; +local function handleScreenResponse(res) + if res and res.eventType == 'switch' then + if not screens[res.toScreen] then + game.Log('Undefined screen ' .. res.toScreen, game.LOGGER_ERROR) + return + end + currentScreen = screens[res.toScreen] + if currentScreen.screen.reset then + currentScreen.screen.reset() end - - gfx.BeginPath(); - gfx.ImageRect(0, 0, desw, desh, idolAnimation, 1, 0); - gfx.GlobalAlpha(1); end - - -- Draw selector background - gfx.BeginPath(); - gfx.ImageRect(0, (desh / 2 + SELECTOR_BAR_OFFSET_FROM_CENTER) - 280 / 2, - 1079, 280, selectorBgImage, 1, 0); - - setButtons() - - buttonY = (desh / 2) - 2 * (257 + 5); - - draw_buttons(); - drawTexts(); - - -- Draw the arrows around the selected button - gfx.BeginPath(); - gfx.ImageRect(desw - 512, desh / 2 + SELECTOR_BAR_OFFSET_FROM_CENTER - - buttonHeight - 8, 501, 300, selectorArrowsImage, 1, 0); - - -- Draw top and bottom bars - drawHeader(); - Footer.draw(deltaTime); - - gfx.ResetTransform(); end -render = function(deltaTime) - if not playedBgm then - game.PlaySample('titlescreen/bgm.wav', true); - playedBgm = true; +function render(deltaTime) + handleKnobs() + + handleScreenResponse(currentScreen.screen.render(deltaTime)) +end + +function mouse_pressed(button) + if (currentScreen.screen.onMousePressed) then + currentScreen.screen.onMousePressed(button) end - - game.SetSkinSetting('_currentScreen', 'title') - - -- 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() - - draw_titlescreen((resX - fullX) / 2, 0, fullX, fullY, deltaTime); - - handle_controller() - - scrollTransitionScale = scrollTransitionScale + 1 / 60 * 5; - if (scrollTransitionScale > 1) then scrollTransitionScale = 1; end - - if scrollingUp then - buttonsMovementScale = 1 - scrollTransitionScale - else - buttonsMovementScale = -1 + scrollTransitionScale - end - - gfx.BeginPath(); -end; - -mouse_pressed = function(button) return 0 end + return 0 +end function button_pressed(button) - if button == game.BUTTON_STA then - game.PlaySample('titlescreen/cursor_select.wav'); - game.StopSample('titlescreen/bgm.wav'); - buttons[cursorIndex][3]() - elseif button == game.BUTTON_BCK then - Menu.Exit() + if (currentScreen.screen.onButtonPressed) then + currentScreen.screen.onButtonPressed(button) end end - --- the thing is... titlescreen script does not have a call to reset function... WHYYYYY -function reset() playedBgm = false; end diff --git a/scripts/titlescreen/boot.lua b/scripts/titlescreen/boot.lua new file mode 100644 index 0000000..ce94260 --- /dev/null +++ b/scripts/titlescreen/boot.lua @@ -0,0 +1,28 @@ +local Dim = require("common.dimensions") +local Wallpaper = require("components.wallpaper") +local BootPage = require("titlescreen.pages.boot.bootpage") +local PageView = require("components.pager.pageview") + +local bootpage = BootPage.new() +local pageview = PageView.new(bootpage) + +local function render(deltaTime) + Dim.updateResolution() + + Wallpaper.render() + + Dim.transformToScreenSpace() + + pageview:render(deltaTime) + + --pageview will be empty when you `back()` out of the root page + if not pageview:get() then + return {eventType = "switch", toScreen = "splash"} + end +end + +local function onButtonPressed(button) + pageview:get():handleButtonInput(button) +end + +return {render = render, onButtonPressed = onButtonPressed} \ No newline at end of file diff --git a/scripts/titlescreen/fields/boot/checkupdatefield.lua b/scripts/titlescreen/fields/boot/checkupdatefield.lua new file mode 100644 index 0000000..13b84e1 --- /dev/null +++ b/scripts/titlescreen/fields/boot/checkupdatefield.lua @@ -0,0 +1,71 @@ +require("common.class") +local Util = require("common.util") +local ServiceField = require("titlescreen.fields.service.servicefield") + +---@class CheckUpdateField: ServiceField +---@field onUpdateAvailable nil|fun(url: string, version: string) +---@field _timer number +local CheckUpdateField = { + __tostring = function() return "CheckUpdateField" end, + PROGRESS_FREQ = 1 / 5, -- 5Hz + CHECK_UPDATE_TIMEOUT = 5, -- seconds +} + +---Create a new CheckUpdateField instance +---@param o? table # initial parameters +---@return CheckUpdateField +function CheckUpdateField.new(o) + o = o or {} + + o._timer = o._timer or 0 + o.onUpdateAvailable = o.onUpdateAvailable or nil + + local this = CreateInstance(CheckUpdateField, o, ServiceField) + + this._url = nil + this._version = nil + this._onUpdateAvailableFired = false + + return this +end + +function CheckUpdateField:drawLabel(deltaTime) + local text = self.label + local progress = math.ceil(Util.lerp(self._timer % self.PROGRESS_FREQ, + 0, 0, self.PROGRESS_FREQ, 4 + )) + text = text .. string.rep(".", progress) + + gfx.FontSize(self.FONT_SIZE) + gfx.LoadSkinFont(self.FONT_FACE) + gfx.TextAlign(gfx.TEXT_ALIGN_LEFT | gfx.TEXT_ALIGN_TOP) + gfx.FillColor(table.unpack(self.FONT_COLOR)) + gfx.Text(text, 0, 0) +end + +function CheckUpdateField:drawValue(deltaTime) + +end + +function CheckUpdateField:tick(deltaTime) + if not self._onUpdateAvailableFired then + if self._timer > self.CHECK_UPDATE_TIMEOUT then + self._url, self._version = game.UpdateAvailable() + -- self._url = "" -- debug code to force onUpdateAvailable() + if self._url then + self.onUpdateAvailable(self._url, self._version) + self._onUpdateAvailableFired = true + else + self:getParentPage().viewHandler:clear() -- Exit out of bootscreen + end + end + end + self._timer = self._timer + deltaTime +end + +function CheckUpdateField:render(deltaTime) + self:tick(deltaTime) + ServiceField.render(self, deltaTime) +end + +return CheckUpdateField diff --git a/scripts/titlescreen/fields/boot/dialogfield.lua b/scripts/titlescreen/fields/boot/dialogfield.lua new file mode 100644 index 0000000..6d1bc99 --- /dev/null +++ b/scripts/titlescreen/fields/boot/dialogfield.lua @@ -0,0 +1,149 @@ +require("common.class") +local ContainerField = require("components.pager.containerfield") + +---@class DialogField: ContainerField +---@field _symbolMargin number +---@field _symbolSize number +local DialogField = { + __tostring = function() return "ContainerField" end, + BGCOLOR = {0, 0, 0, 255}, --{r, g, b, a} + DEFAULT_WIDTH = 400, + DEFAULT_HEIGHT = 200, + FONT_SIZE = 16, + FONT_FACE = "dfmarugoth.ttf", + FONT_COLOR = {255, 255, 255, 255}, + BORDERCOLOR = {255, 255, 255, 255}, + BORDERRADII = 12, + BORDERWIDTH = 2, + HEADER = { + title = "Title", + code = "0-0000-0000" + }, + TEXT = { + "Top text,", + "Sample text,", + "Bottom text." + }, + LEGEND = { + { + label = "BUTTON", + text = "DESCRIPTION" + }, + }, +} + +---Create a new DialogField instance +--- +---Inherits from ContainerField +---@param o ContainerField +---@return DialogField +function DialogField.new(o) + o = o or {} + + o.aabbW = o.aabbW or DialogField.DEFAULT_WIDTH + o.aabbH = o.aabbH or DialogField.DEFAULT_HEIGHT + + local this = CreateInstance(DialogField, o, ContainerField) + + this._symbolMargin = 8 + this._symbolSize = 48 + + return this +end + +---Draw the dialog symbol +--- +---Default implementation is a yellow triangle with an exclamation mark +---@param deltaTime number # frametime in seconds +function DialogField:drawSymbol(deltaTime) + local symbolColor = {255, 255, 0, 255} + gfx.Save() + gfx.Translate(self._symbolMargin, self._symbolMargin) + gfx.FillColor(table.unpack(symbolColor)) + gfx.BeginPath() + local symbolBottomY = math.sqrt(3) / 2 * self._symbolSize + gfx.MoveTo(0, symbolBottomY) + gfx.LineTo(self._symbolSize / 2, 0) + gfx.LineTo(self._symbolSize, symbolBottomY) + gfx.Fill() + -- exclamation mark + local excTopMargin = 10 + local excBottomMargin = 4 + local excThickness = 5 + local excColor = {0, 0, 0, 255} + gfx.FillColor(table.unpack(excColor)) + gfx.BeginPath() + gfx.Rect( + self._symbolSize / 2 - excThickness / 2, -- x + excTopMargin, -- y + excThickness, -- w + symbolBottomY - excTopMargin - excBottomMargin - 3 / 2 * excThickness -- h + ) + gfx.Rect( + self._symbolSize / 2 - excThickness / 2, -- x + symbolBottomY - excBottomMargin - excThickness, -- y + excThickness, excThickness -- w, h + ) + gfx.Fill() + gfx.Restore() +end + +---@param deltaTime number # frametime in seconds +function DialogField:drawBackground(deltaTime) + local textMargin = 4 + -- border + local borderH = self.aabbH - #self.LEGEND * self.FONT_SIZE - textMargin + gfx.BeginPath() + gfx.StrokeColor(table.unpack(self.BORDERCOLOR)) + gfx.StrokeWidth(self.BORDERWIDTH) + gfx.FillColor(table.unpack(self.BGCOLOR)) + gfx.RoundedRect(0, 0, self.aabbW, borderH, self.BORDERRADII) + gfx.Fill() + gfx.Stroke() + + gfx.FontSize(self.FONT_SIZE) + gfx.LoadSkinFont(self.FONT_FACE) + + -- draw symbol + self:drawSymbol(deltaTime) + + -- legend + local legendX = 0 + local legendY = borderH + textMargin + gfx.TextAlign(gfx.TEXT_ALIGN_TOP | gfx.TEXT_ALIGN_LEFT) + gfx.FillColor(table.unpack(self.FONT_COLOR)) + for _, legend in ipairs(self.LEGEND) do + gfx.Text(legend.label .. " = " .. legend.text, legendX, legendY) + legendY = legendY + self.FONT_SIZE + end + + -- header + local headerX = self._symbolSize + self._symbolMargin + 16 + local headerY = self._symbolMargin + gfx.Save() + gfx.Translate(headerX, headerY) + gfx.Text(self.HEADER.title, 0, 0) + local separatorY = self.FONT_SIZE + textMargin + local separatorThickness = 1 + gfx.StrokeWidth(separatorThickness) + gfx.BeginPath() + gfx.MoveTo(0, separatorY) + gfx.LineTo(self.aabbW - headerX - self._symbolMargin, separatorY) + gfx.Stroke() + local codeY = separatorY + textMargin + gfx.Text(self.HEADER.code, 0, codeY) + gfx.Restore() +end + +---@param deltaTime number # frametime in seconds +function DialogField:drawForeground(deltaTime) + local textX = 12 + local textY = 64 + local lineHeight = self.FONT_SIZE + 4 + for _, line in ipairs(self.TEXT) do + gfx.Text(line, textX, textY) + textY = textY + lineHeight + end +end + +return DialogField diff --git a/scripts/titlescreen/fields/boot/selftestfield.lua b/scripts/titlescreen/fields/boot/selftestfield.lua new file mode 100644 index 0000000..3c955d1 --- /dev/null +++ b/scripts/titlescreen/fields/boot/selftestfield.lua @@ -0,0 +1,134 @@ +require("common.class") +local Util = require("common.util") +local ServiceField = require("titlescreen.fields.service.servicefield") + +---@class SelfTestStatusEnum +SelfTestStatusEnum = { + IDLE = 1, + INPROGRESS = 2, + OK = 3, + PASS = 4, + ERROR = 5 +} + +local function statusToString(status) + local statusName = {"IDLE", "INPROGRESS", "OK", "PASS", "ERROR"} + return statusName[status] +end + +---@class SelfTestField: ServiceField +---@field checkTask nil|fun(obj: any): SelfTestStatusEnum # a function that will run asynchronously on activating the Field +---@field status SelfTestStatusEnum +---@field onStatusChange nil|fun(status) # a callback function on finishing the checkTask +---@field _thread thread +---@field _timer number +local SelfTestField = { + __tostring = function () return "SelfTestField" end, + COLOR_INPROGRESS = {255, 255, 255, 255}, + COLOR_OK = {0, 255, 0, 255}, + COLOR_PASS = {255, 255, 0, 255}, + COLOR_ERROR = {255, 0, 0, 255}, + INPROGRESS_FREQ = 1 / 20, --20Hz +} + +---Create a new SelfTestField instance +---@param o? table +---@return SelfTestField +function SelfTestField.new(o) + o = o or {} + + o.status = o.status or SelfTestStatusEnum.IDLE + o._timer = 0 + o._thread = nil + + assert((not o.onStatusChange) or (o.checkTask and o.onStatusChange), + "Failed to construct SelfTestField, checkTask is mandatory when onStatusChange is defined!\n" .. debug.traceback() + ) + + return CreateInstance(SelfTestField, o, ServiceField) +end + +function SelfTestField:_closeThread() + if self._thread and coroutine.status(self._thread) ~= "dead" then + coroutine.close(self._thread) + end +end + +function SelfTestField:_resumeThread() + if self._thread and coroutine.status(self._thread) == "suspended" then + local success, status = coroutine.resume(self._thread) + game.Log(self.label .. ": success: " .. tostring(success) .. + ", status: " .. status .. " (" .. statusToString(status) .. ")", + game.LOGGER_DEBUG + ) + if success and status ~= self.status then + self.status = status + if self.onStatusChange then + game.Log("SKIN CONFIG: onStatusChange(" .. status .. ") (" .. + statusToString(status) .. ")", + game.LOGGER_DEBUG + ) + self.onStatusChange(status) + end + end + end +end + +function SelfTestField:activate(obj) + self:_closeThread() + + if self.checkTask then + self._thread = coroutine.create(self.checkTask) + self:_resumeThread() + end +end + +function SelfTestField:deactivate(obj) + self:_closeThread() +end + +function SelfTestField:tick(deltaTime) + self:_resumeThread() + + self._timer = self._timer + deltaTime +end + +function SelfTestField:drawValue(deltaTime) + gfx.Translate(self.VALUE_OFFSETX, 0) + + gfx.TextAlign(gfx.TEXT_ALIGN_RIGHT | gfx.TEXT_ALIGN_TOP) + gfx.FillColor(table.unpack(self.FONT_COLOR)) + gfx.Text(": ", 0, 0) + + local color, text + if self.status == SelfTestStatusEnum.IDLE then + color = self.FONT_COLOR + text = "" + elseif self.status == SelfTestStatusEnum.INPROGRESS then + local progress = math.ceil(Util.lerp(self._timer % self.INPROGRESS_FREQ, + 0, 0, self.INPROGRESS_FREQ, 4 + )) + color = self.COLOR_INPROGRESS + text = string.rep(".", progress) + elseif self.status == SelfTestStatusEnum.OK then + color = self.COLOR_OK + text = "OK" + elseif self.status == SelfTestStatusEnum.PASS then + color = self.COLOR_PASS + text = "PASS" + elseif self.status == SelfTestStatusEnum.ERROR then + color = self.COLOR_ERROR + text = "ERROR" + end + + gfx.TextAlign(gfx.TEXT_ALIGN_LEFT | gfx.TEXT_ALIGN_TOP) + gfx.FillColor(table.unpack(color)) + gfx.Text(text, 0, 0) +end + +function SelfTestField:render(deltaTime) + self:tick(deltaTime) + ServiceField.render(self, deltaTime) +end + +return SelfTestField \ No newline at end of file diff --git a/scripts/titlescreen/fields/service/colorgradientfield.lua b/scripts/titlescreen/fields/service/colorgradientfield.lua new file mode 100644 index 0000000..97302eb --- /dev/null +++ b/scripts/titlescreen/fields/service/colorgradientfield.lua @@ -0,0 +1,46 @@ +require("common.class") +local Util = require("common.util") +local ServiceField = require("titlescreen.fields.service.servicefield") + +---@class ColorGradientField: ServiceField +local ColorGradientField = { + __tostring = function() return "ColorGradientField" end, + GRADIENT_X_OFFSET = 128, + GRADIENT_WIDTH = 576, + GRADIENT_STEPS = 32 +} + +---Create a new ColorGradientField instance +---@param o? table # initial parameters +---@return ColorGradientField +function ColorGradientField.new(o) + o = o or {} + + o.value = o.value or {0, 0, 0, 255} + + return CreateInstance(ColorGradientField, o, ServiceField) +end + +---@param obj? any # message object for the field +function ColorGradientField:activate(obj) end + +---@param obj? any # message object for the field +function ColorGradientField:focus(obj) end + +---@param obj? any # message object for the field +function ColorGradientField:deactivate(obj) end + +---@param deltaTime number # frametime in seconds +function ColorGradientField:drawValue(deltaTime) + local stepW = self.GRADIENT_WIDTH / self.GRADIENT_STEPS + for i = 0, self.GRADIENT_STEPS - 1 do + local posX = self.GRADIENT_X_OFFSET + i * stepW + local colorA = math.ceil(Util.lerp(i, 0, 0, self.GRADIENT_STEPS - 1, self.value[4])) + gfx.BeginPath() + gfx.Rect(posX, 0, stepW, self.aabbH) + gfx.FillColor(self.value[1], self.value[2], self.value[3], colorA) + gfx.Fill() + end +end + +return ColorGradientField diff --git a/scripts/titlescreen/fields/service/inputbuttonfield.lua b/scripts/titlescreen/fields/service/inputbuttonfield.lua new file mode 100644 index 0000000..294a455 --- /dev/null +++ b/scripts/titlescreen/fields/service/inputbuttonfield.lua @@ -0,0 +1,43 @@ +require("common.class") +local ServiceField = require("titlescreen.fields.service.servicefield") + +---@class InputButtonField: ServiceField +---@field button integer +local InputButtonField = { + __tostring = function() return "InputButtonField" end, +} + +---Create a new InputButtonField instance +---@param o? table # initial parameters +---@return InputButtonField +function InputButtonField.new(o) + o = o or {} + + o.button = o.button or nil + + return CreateInstance(InputButtonField, o, ServiceField) +end + +---@param obj? any # message object for the field +function InputButtonField:activate(obj) end + +---@param obj? any # message object for the field +function InputButtonField:focus(obj) end + +---@param obj? any # message object for the field +function InputButtonField:deactivate(obj) end + +---@param deltaTime number # frametime in seconds +function InputButtonField:drawValue(deltaTime) + gfx.Translate(self.VALUE_OFFSETX, 0) + + if not self.button then + gfx.Text("