3 Commits 12b86aea19 ... 7f49175a5e

Author SHA1 Message Date
  kiwec 7f49175a5e Add anti-flashlight mod 2 months ago
  kiwec e42f87f997 Fail to edit score screen 2 months ago
  kiwec e7843a0635 Add keybind to open skin selection menu 2 months ago

+ 2 - 0
src/App/Osu/BanchoSubmitter.cpp

@@ -4,7 +4,9 @@
 #include <sys/random.h>
 #endif
 
+#ifndef LZMA_API_STATIC
 #define LZMA_API_STATIC
+#endif
 #include <lzma.h>
 
 #include "Bancho.h"

+ 8 - 11
src/App/Osu/Beatmap.cpp

@@ -119,6 +119,7 @@ ConVar osu_followpoints_prevfadetime("osu_followpoints_prevfadetime", 400.0f,
 
 ConVar osu_auto_and_relax_block_user_input("osu_auto_and_relax_block_user_input", true, FCVAR_DEFAULT);
 
+ConVar mod_anti_flashlight("mod_anti_flashlight", false, FCVAR_DEFAULT);
 ConVar osu_mod_timewarp("osu_mod_timewarp", false, FCVAR_UNLOCKED);
 ConVar osu_mod_timewarp_multiplier("osu_mod_timewarp_multiplier", 1.5f, FCVAR_DEFAULT);
 ConVar osu_mod_minimize("osu_mod_minimize", false, FCVAR_UNLOCKED);
@@ -293,7 +294,6 @@ Beatmap::Beatmap() {
     m_fposu_mod_strafing_strength_x_ref = convar->getConVarByName("fposu_mod_strafing_strength_x");
     m_fposu_mod_strafing_strength_y_ref = convar->getConVarByName("fposu_mod_strafing_strength_y");
     m_fposu_mod_strafing_strength_z_ref = convar->getConVarByName("fposu_mod_strafing_strength_z");
-    m_fposu_mod_3d_depthwobble_ref = convar->getConVarByName("fposu_mod_3d_depthwobble");
     m_osu_slider_scorev2_ref = convar->getConVarByName("osu_slider_scorev2");
 
     // vars
@@ -1155,7 +1155,7 @@ void Beatmap::stop(bool quit) {
     m_bIsPaused = false;
     m_bContinueScheduled = false;
 
-    saveAndSubmitScore(quit);
+    auto score = saveAndSubmitScore(quit);
 
     // Auto mod was "temporary" since it was set from Ctrl+Clicking a map, not from the mod selector
     if(osu->m_bModAutoTemp) {
@@ -1177,7 +1177,7 @@ void Beatmap::stop(bool quit) {
 
     if(bancho.is_playing_a_multi_map()) {
         if(quit) {
-            osu->onPlayEnd(true);
+            osu->onPlayEnd(score, true);
             osu->m_room->ragequit();
         } else {
             osu->m_room->onClientScoreChange(true);
@@ -1186,7 +1186,7 @@ void Beatmap::stop(bool quit) {
             send_packet(packet);
         }
     } else {
-        osu->onPlayEnd(quit);
+        osu->onPlayEnd(score, quit);
     }
 }
 
@@ -3701,7 +3701,7 @@ Vector2 Beatmap::getFirstPersonCursorDelta() const {
 
 float Beatmap::getHitcircleDiameter() const { return m_fHitcircleDiameter; }
 
-void Beatmap::saveAndSubmitScore(bool quit) {
+FinishedScore Beatmap::saveAndSubmitScore(bool quit) {
     // calculate stars
     double aim = 0.0;
     double aimSliderFactor = 0.0;
@@ -3814,8 +3814,6 @@ void Beatmap::saveAndSubmitScore(bool quit) {
     score.has_replay = true;
     score.replay = live_replay;
 
-    int scoreIndex = -1;
-
     if(!isCheated) {
         RichPresence::onPlayEnd(quit);
 
@@ -3826,16 +3824,13 @@ void Beatmap::saveAndSubmitScore(bool quit) {
         }
 
         if(score.passed) {
-            scoreIndex = osu->getSongBrowser()->getDatabase()->addScore(m_selectedDifficulty2->getMD5Hash(), score);
+            int scoreIndex = osu->getSongBrowser()->getDatabase()->addScore(m_selectedDifficulty2->getMD5Hash(), score);
             if(scoreIndex == -1) {
                 osu->getNotificationOverlay()->addNotification("Failed saving score!", 0xffff0000, false, 3.0f);
             }
         }
     }
 
-    osu->getScore()->setIndex(scoreIndex);
-    osu->getScore()->setComboFull(maxPossibleCombo);  // used in RankingScreen/UIRankingScreenRankingPanel
-
     if(!bancho.spectators.empty()) {
         broadcast_spectator_frames();
 
@@ -3853,6 +3848,8 @@ void Beatmap::saveAndSubmitScore(bool quit) {
     if(!isComplete) {
         osu->getScore()->setPPv2(0.0f);
     }
+
+    return score;
 }
 
 void Beatmap::updateAutoCursorPos() {

+ 2 - 3
src/App/Osu/Beatmap.h

@@ -178,7 +178,7 @@ class Beatmap {
                                                               m_speedNotesForNumHitObjects.size() - 1)]
                     : 0);
     }
-    
+
     std::vector<double> m_aimStrains;
     std::vector<double> m_speedStrains;
 
@@ -399,7 +399,6 @@ class Beatmap {
     ConVar *m_fposu_mod_strafing_strength_x_ref = NULL;
     ConVar *m_fposu_mod_strafing_strength_y_ref = NULL;
     ConVar *m_fposu_mod_strafing_strength_z_ref = NULL;
-    ConVar *m_fposu_mod_3d_depthwobble_ref = NULL;
     ConVar *m_osu_slider_scorev2_ref = NULL;
 
     static inline Vector2 mapNormalizedCoordsOntoUnitCircle(const Vector2 &in) {
@@ -418,7 +417,7 @@ class Beatmap {
         }
     }
 
-    void saveAndSubmitScore(bool quit);
+    FinishedScore saveAndSubmitScore(bool quit);
 
     void drawFollowPoints(Graphics *g);
     void drawHitObjects(Graphics *g);

+ 5 - 6
src/App/Osu/Changelog.cpp

@@ -29,12 +29,15 @@ Changelog::Changelog() : ScreenBackable() {
     CHANGELOG latest;
     latest.title =
         UString::format("%.2f (%s, %s)", convar->getConVarByName("osu_version")->getFloat(), __DATE__, __TIME__);
-    latest.changes.push_back("- Added slider instafade setting");
     latest.changes.push_back(
         "- Added \"tooearly.wav\" and \"toolate.wav\" hitsounds, which play when you hit too early or too late (if "
         "your skin has them)");
+    latest.changes.push_back("- Added \"Anti-flashlight\" experimental mod");
+    latest.changes.push_back("- Added keybind to open skin selection menu");
+    latest.changes.push_back("- Added slider instafade setting");
     latest.changes.push_back("- Fixed local scores not saving avatar");
     latest.changes.push_back("- Fixed Nightcore getting auto-selected instead of Double Time in some cases");
+    latest.changes.push_back("- Linux: fixed \"Skin.ini\" failing to load");
     changelogs.push_back(latest);
 
     CHANGELOG v35_09;
@@ -393,11 +396,7 @@ void Changelog::updateLayout() {
     m_scrollView->setScrollSizeToContent(15 * dpiScale);
 }
 
-void Changelog::onBack() {
-    engine->getSound()->play(osu->getSkin()->m_menuBack);
-
-    osu->toggleChangelog();
-}
+void Changelog::onBack() { osu->toggleChangelog(); }
 
 void Changelog::onChangeClicked(CBaseUIButton *button) {
     const UString changeTextMaybeContainingClickableURL = button->getText();

+ 0 - 4
src/App/Osu/Downloader.cpp

@@ -269,10 +269,6 @@ i32 extract_beatmapset_id(const u8* data, size_t data_s) {
         set_id = get_beatmapset_id_from_osu_file(osu_data, s_osu_data);
         mz_free(osu_data);
         if(set_id != -1) break;
-
-    skip_file:;
-        // When a file can't be extracted we just ignore it (as long as the archive is valid).
-        // We'll check for errors when loading the beatmap.
     }
 
     mz_zip_reader_end(&zip);

+ 6 - 0
src/App/Osu/HitObject.cpp

@@ -208,6 +208,9 @@ void HitObject::drawHitResult(Graphics *g, Skin *skin, float hitcircleDiameter,
                 hitImageScale =
                     (rawHitcircleDiameter / skin->getHit300g()->getSizeBaseRaw().x) * osuCoordScaleMultiplier;
                 break;
+
+            default:
+                break;
         }
 
         // non-misses have a special scale animation (the type of which depends on hasParticle)
@@ -292,6 +295,9 @@ void HitObject::drawHitResult(Graphics *g, Skin *skin, float hitcircleDiameter,
                         (doScaleOrRotateAnim ? scale : 1.0f) * hitImageScale * osu_hitresult_scale.getFloat());
                 }
                 break;
+
+            default:
+                break;
         }
     }
     g->popTransform();

+ 2 - 0
src/App/Osu/KeyBindings.cpp

@@ -37,6 +37,7 @@ ConVar KeyBindings::SAVE_SCREENSHOT("osu_key_save_screenshot", (int)KEY_F12, FCV
 ConVar KeyBindings::DISABLE_MOUSE_BUTTONS("osu_key_disable_mouse_buttons", (int)KEY_F10, FCVAR_DEFAULT);
 ConVar KeyBindings::TOGGLE_MAP_BACKGROUND("key_toggle_map_background", 0, FCVAR_DEFAULT);
 ConVar KeyBindings::BOSS_KEY("osu_key_boss", (int)KEY_INSERT, FCVAR_DEFAULT);
+ConVar KeyBindings::OPEN_SKIN_SELECT_MENU("key_open_skin_select_menu", 0, FCVAR_DEFAULT);
 
 ConVar KeyBindings::TOGGLE_MODSELECT("osu_key_toggle_modselect", (int)KEY_F1, FCVAR_DEFAULT);
 ConVar KeyBindings::RANDOM_BEATMAP("osu_key_random_beatmap", (int)KEY_F2, FCVAR_DEFAULT);
@@ -83,6 +84,7 @@ std::vector<ConVar*> KeyBindings::ALL = {&KeyBindings::LEFT_CLICK,
                                          &KeyBindings::DISABLE_MOUSE_BUTTONS,
                                          &KeyBindings::TOGGLE_MAP_BACKGROUND,
                                          &KeyBindings::BOSS_KEY,
+                                         &KeyBindings::OPEN_SKIN_SELECT_MENU,
 
                                          &KeyBindings::TOGGLE_MODSELECT,
                                          &KeyBindings::RANDOM_BEATMAP,

+ 1 - 0
src/App/Osu/KeyBindings.h

@@ -43,6 +43,7 @@ class KeyBindings {
     static ConVar DISABLE_MOUSE_BUTTONS;
     static ConVar TOGGLE_MAP_BACKGROUND;
     static ConVar BOSS_KEY;
+    static ConVar OPEN_SKIN_SELECT_MENU;
 
     static ConVar TOGGLE_MODSELECT;
     static ConVar RANDOM_BEATMAP;

+ 1 - 4
src/App/Osu/ModFPoSu.cpp

@@ -71,8 +71,6 @@ ConVar fposu_mod_strafing_frequency_y("fposu_mod_strafing_frequency_y", 0.2f, FC
 ConVar fposu_mod_strafing_strength_z("fposu_mod_strafing_strength_z", 0.15f, FCVAR_DEFAULT);
 ConVar fposu_mod_strafing_frequency_z("fposu_mod_strafing_frequency_z", 0.15f, FCVAR_DEFAULT);
 
-ConVar fposu_mod_3d_depthwobble("fposu_mod_3d_depthwobble", false, FCVAR_UNLOCKED);
-
 constexpr const float ModFPoSu::SIZEDIV3D;
 constexpr const int ModFPoSu::SUBDIVISIONS;
 
@@ -497,8 +495,7 @@ Vector2 ModFPoSu::intersectRayMesh(Vector3 pos, Vector3 dir) {
                         const float downLength = (Down - TopLeft).length();
                         const float x = u / (rightLength * rightLength);
                         const float y = v / (downLength * downLength);
-                        const float distancePerFace =
-                            (float)osu->getScreenWidth() / pow(2.0f, (float)SUBDIVISIONS);
+                        const float distancePerFace = (float)osu->getScreenWidth() / pow(2.0f, (float)SUBDIVISIONS);
                         const float distanceInFace = distancePerFace * x;
 
                         const Vector2 newMousePos =

+ 2 - 4
src/App/Osu/ModSelector.cpp

@@ -205,13 +205,11 @@ ModSelector::ModSelector() : OsuScreen() {
 
     // build experimental buttons
     addExperimentalLabel(" Experimental Mods (!)");
+    addExperimentalCheckbox("Anti-flashlight", "Flashlight, but reversed",
+                            convar->getConVarByName("mod_anti_flashlight"));
     addExperimentalCheckbox("FPoSu: Strafing",
                             "Playfield moves in 3D space (see fposu_mod_strafing_...).\nOnly works in FPoSu mode!",
                             convar->getConVarByName("fposu_mod_strafing"));
-    addExperimentalCheckbox("FPoSu 4D: Z Wobble",
-                            "Each hitobject individually moves in 3D space (see fposu_mod_3d_depthwobble_...)\nOnly "
-                            "works in FPoSu \"4D Mode\"!",
-                            convar->getConVarByName("fposu_mod_3d_depthwobble"));
     addExperimentalCheckbox("Wobble", "Playfield rotates and moves.", convar->getConVarByName("osu_mod_wobble"));
     addExperimentalCheckbox("AR Wobble", "Approach rate oscillates between -1 and +1.",
                             convar->getConVarByName("osu_mod_arwobble"));

+ 30 - 11
src/App/Osu/OptionsMenu.cpp

@@ -994,6 +994,7 @@ OptionsMenu::OptionsMenu() : ScreenBackable() {
     addKeyBindButton("Disable Mouse Buttons", &KeyBindings::DISABLE_MOUSE_BUTTONS);
     addKeyBindButton("Toggle Map Background", &KeyBindings::TOGGLE_MAP_BACKGROUND);
     addKeyBindButton("Boss Key (Minimize)", &KeyBindings::BOSS_KEY);
+    addKeyBindButton("Open Skin Selection Menu", &KeyBindings::OPEN_SKIN_SELECT_MENU);
     addSubSection("Keys - Song Select", keyboardSectionTags);
     addKeyBindButton("Toggle Mod Selection Screen", &KeyBindings::TOGGLE_MODSELECT)
         ->setTooltipText("(F1 can not be unbound. This is just an additional key.)");
@@ -1390,7 +1391,10 @@ OptionsMenu::~OptionsMenu() {
 
 void OptionsMenu::draw(Graphics *g) {
     const bool isAnimating = anim->isAnimating(&m_fAnimation);
-    if(!m_bVisible && !isAnimating) return;
+    if(!m_bVisible && !isAnimating) {
+        m_contextMenu->draw(g);
+        return;
+    }
 
     m_sliderPreviewElement->setDrawSliderHack(!isAnimating);
 
@@ -1468,12 +1472,12 @@ void OptionsMenu::draw(Graphics *g) {
 }
 
 void OptionsMenu::mouse_update(bool *propagate_clicks) {
-    if(!m_bVisible) return;
-
     // force context menu focus
     m_contextMenu->mouse_update(propagate_clicks);
     if(!*propagate_clicks) return;
 
+    if(!m_bVisible) return;
+
     ScreenBackable::mouse_update(propagate_clicks);
     if(!*propagate_clicks) return;
 
@@ -1749,13 +1753,10 @@ void OptionsMenu::setVisibleInt(bool visible, bool fromOnBack) {
     m_bVisible = visible;
     osu->m_chat->updateVisibility();
 
-    if(visible)
+    if(visible) {
         updateLayout();
-    else {
+    } else {
         m_contextMenu->setVisible2(false);
-
-        // anim->deleteExistingAnimation(&m_fAnimation);
-        // m_fAnimation = 0.0f;
     }
 
     // usability: auto scroll to fposu settings if opening options while in fposu gamemode
@@ -2219,7 +2220,6 @@ void OptionsMenu::updateLayout() {
 void OptionsMenu::onBack() {
     osu->getNotificationOverlay()->stopWaitingForKey();
 
-    engine->getSound()->play(osu->getSkin()->m_menuBack);
     save();
 
     if(m_bFullscreen)
@@ -2406,6 +2406,8 @@ void OptionsMenu::openCurrentSkinFolder() {
 }
 
 void OptionsMenu::onSkinSelect() {
+    // XXX: Instead of a dropdown, we should make a dedicated skin select screen with search bar
+
     updateOsuFolder();
 
     if(osu->isSkinLoading()) return;
@@ -2448,8 +2450,16 @@ void OptionsMenu::onSkinSelect() {
     }
 
     if(skinFolders.size() > 0) {
-        m_contextMenu->setPos(m_skinSelectLocalButton->getPos());
-        m_contextMenu->setRelPos(m_skinSelectLocalButton->getRelPos());
+        m_contextMenu->setVisible2(false);
+
+        if(m_bVisible) {
+            m_contextMenu->setPos(m_skinSelectLocalButton->getPos());
+            m_contextMenu->setRelPos(m_skinSelectLocalButton->getRelPos());
+        } else {
+            // Put it 50px from top, we'll move it later
+            m_contextMenu->setPos(Vector2{0, 100});
+        }
+
         m_contextMenu->begin();
 
         const UString defaultText = "default";
@@ -2465,6 +2475,15 @@ void OptionsMenu::onSkinSelect() {
         }
         m_contextMenu->end(false, true);
         m_contextMenu->setClickCallback(fastdelegate::MakeDelegate(this, &OptionsMenu::onSkinSelect2));
+
+        if(!m_bVisible) {
+            // Center context menu
+            m_contextMenu->setPos(Vector2{
+                osu->getScreenWidth() / 2.f - m_contextMenu->getSize().x / 2.f,
+                osu->getScreenHeight() / 2.f - m_contextMenu->getSize().y / 2.f,
+            });
+            m_contextMenu->setVisible(true);
+        }
     } else {
         osu->getNotificationOverlay()->addNotification("Error: Couldn't find any skins", 0xffff0000);
         m_options->scrollToTop();

+ 63 - 12
src/App/Osu/Osu.cpp

@@ -171,6 +171,7 @@ ConVar *Osu::ui_scale = &osu_ui_scale;
 Vector2 Osu::g_vInternalResolution;
 Vector2 Osu::osuBaseResolution = Vector2(640.0f, 480.0f);
 
+Shader *anti_flashlight_shader = NULL;
 Shader *flashlight_shader = NULL;
 
 Osu::Osu() {
@@ -206,7 +207,6 @@ Osu::Osu() {
 
     // experimental mods list
     m_experimentalMods.push_back(convar->getConVarByName("fposu_mod_strafing"));
-    m_experimentalMods.push_back(convar->getConVarByName("fposu_mod_3d_depthwobble"));
     m_experimentalMods.push_back(convar->getConVarByName("osu_mod_wobble"));
     m_experimentalMods.push_back(convar->getConVarByName("osu_mod_arwobble"));
     m_experimentalMods.push_back(convar->getConVarByName("osu_mod_timewarp"));
@@ -503,6 +503,24 @@ Osu::Osu() {
     m_osu_mod_fposu_ref->setCallback(fastdelegate::MakeDelegate(this, &Osu::onModFPoSuChange));
 
     // Not the type of shader you want players to tweak or delete, so loading from string
+    anti_flashlight_shader = engine->getGraphics()->createShaderFromSource(
+        "#version 110\n"
+        "varying vec2 tex_coord;\n"
+        "void main() {\n"
+        "    gl_Position = gl_ModelViewProjectionMatrix * vec4(gl_Vertex.x, gl_Vertex.y, 0.0, 1.0);\n"
+        "    gl_FrontColor = gl_Color;\n"
+        "    tex_coord = gl_MultiTexCoord0.xy;\n"
+        "}",
+        "#version 110\n"
+        "uniform float max_opacity;\n"
+        "uniform float flashlight_radius;\n"
+        "uniform vec2 flashlight_center;\n"
+        "void main(void) {\n"
+        "    float dist = distance(flashlight_center, gl_FragCoord.xy);\n"
+        "    float opacity = smoothstep(flashlight_radius, flashlight_radius * 1.4, dist);\n"
+        "    opacity = 1.0 - min(opacity, max_opacity);\n"
+        "    gl_FragColor = vec4(0.0, 0.0, 0.0, opacity);\n"
+        "}");
     flashlight_shader = engine->getGraphics()->createShaderFromSource(
         "#version 110\n"
         "varying vec2 tex_coord;\n"
@@ -521,6 +539,7 @@ Osu::Osu() {
         "    opacity = 1.0 - min(opacity, max_opacity);\n"
         "    gl_FragColor = vec4(0.0, 0.0, 0.0, opacity);\n"
         "}");
+    engine->getResourceManager()->loadResource(anti_flashlight_shader);
     engine->getResourceManager()->loadResource(flashlight_shader);
 }
 
@@ -568,7 +587,8 @@ void Osu::draw(Graphics *g) {
 
         getSelectedBeatmap()->draw(g);
 
-        if(m_bModFlashlight) {
+        auto anti_flashlight_enabled = convar->getConVarByName("mod_anti_flashlight")->getBool();
+        if(m_bModFlashlight || anti_flashlight_enabled) {
             // Dim screen when holding a slider
             float max_opacity = 1.f;
             if(holding_slider && !avoid_flashes.getBool()) {
@@ -589,20 +609,42 @@ void Osu::draw(Graphics *g) {
             Vector2 flashlightPos =
                 flashlight_position * GameRules::getPlayfieldScaleFactor() + GameRules::getPlayfieldOffset();
 
-            float fl_radius = flashlight_radius.getFloat() * GameRules::getPlayfieldScaleFactor();
+            float base_fl_radius = flashlight_radius.getFloat() * GameRules::getPlayfieldScaleFactor();
+
+            float anti_fl_radius = base_fl_radius * 0.625f;
+            float fl_radius = base_fl_radius;
             if(getScore()->getCombo() >= 200 || convar->getConVarByName("flashlight_always_hard")->getBool()) {
+                anti_fl_radius = base_fl_radius;
                 fl_radius *= 0.625f;
             } else if(getScore()->getCombo() >= 100) {
+                anti_fl_radius = base_fl_radius * 0.8125f;
                 fl_radius *= 0.8125f;
             }
 
-            flashlight_shader->enable();
-            flashlight_shader->setUniform1f("max_opacity", max_opacity);
-            flashlight_shader->setUniform1f("flashlight_radius", fl_radius);
-            flashlight_shader->setUniform2f("flashlight_center", flashlightPos.x, getScreenSize().y - flashlightPos.y);
-            g->setColor(COLOR(255, 0, 0, 0));
-            g->fillRect(0, 0, getScreenWidth(), getScreenHeight());
-            flashlight_shader->disable();
+            if(m_bModFlashlight) {
+                flashlight_shader->enable();
+                flashlight_shader->setUniform1f("max_opacity", max_opacity);
+                flashlight_shader->setUniform1f("flashlight_radius", fl_radius);
+                flashlight_shader->setUniform2f("flashlight_center", flashlightPos.x,
+                                                getScreenSize().y - flashlightPos.y);
+
+                g->setColor(COLOR(255, 0, 0, 0));
+                g->fillRect(0, 0, getScreenWidth(), getScreenHeight());
+
+                flashlight_shader->disable();
+            }
+            if(anti_flashlight_enabled) {
+                anti_flashlight_shader->enable();
+                anti_flashlight_shader->setUniform1f("max_opacity", max_opacity);
+                anti_flashlight_shader->setUniform1f("flashlight_radius", anti_fl_radius);
+                anti_flashlight_shader->setUniform2f("flashlight_center", flashlightPos.x,
+                                                     getScreenSize().y - flashlightPos.y);
+
+                g->setColor(COLOR(255, 0, 0, 0));
+                g->fillRect(0, 0, getScreenWidth(), getScreenHeight());
+
+                anti_flashlight_shader->disable();
+            }
         }
 
         if(!isFPoSu) m_hud->draw(g);
@@ -1227,6 +1269,12 @@ void Osu::onKeyDown(KeyboardEvent &key) {
         key.consume();
     }
 
+    if(key == (KEYCODE)KeyBindings::OPEN_SKIN_SELECT_MENU.getInt()) {
+        m_optionsMenu->onSkinSelect();
+        key.consume();
+        return;
+    }
+
     // disable mouse buttons hotkey
     if(key == (KEYCODE)KeyBindings::DISABLE_MOUSE_BUTTONS.getInt()) {
         if(osu_disable_mousebuttons.getBool()) {
@@ -1245,6 +1293,8 @@ void Osu::onKeyDown(KeyboardEvent &key) {
         } else {
             diff->draw_background = !diff->draw_background;
         }
+        key.consume();
+        return;
     }
 
     // F8 toggle chat
@@ -1650,12 +1700,13 @@ void Osu::saveScreenshot() {
                        screenshot_path.toUtf8());
 }
 
-void Osu::onPlayEnd(bool quit, bool aborted) {
+void Osu::onPlayEnd(FinishedScore score, bool quit, bool aborted) {
     m_snd_change_check_interval_ref->setValue(m_snd_change_check_interval_ref->getDefaultFloat());
 
     if(!quit) {
         if(!osu_mod_endless.getBool()) {
-            m_rankingScreen->setScore(m_score);
+            // NOTE: the order of these two calls matters
+            m_rankingScreen->setScore(score);
             m_rankingScreen->setBeatmapInfo(getSelectedBeatmap(), getSelectedBeatmap()->getSelectedDifficulty2());
 
             engine->getSound()->play(m_skin->getApplause());

+ 1 - 2
src/App/Osu/Osu.h

@@ -81,8 +81,7 @@ class Osu : public App, public MouseListener {
     virtual void onMinimized();
     virtual bool onShutdown();
 
-    void onPlayEnd(bool quit = true,
-                   bool aborted = false);  // called when a beatmap is finished playing (or the player quit)
+    void onPlayEnd(FinishedScore score, bool quit = true, bool aborted = false);
 
     void toggleModSelection(bool waitForF1KeyUp = false);
     void toggleSongBrowser();

+ 61 - 133
src/App/Osu/RankingScreen.cpp

@@ -1,10 +1,3 @@
-//================ Copyright (c) 2016, PG, All rights reserved. =================//
-//
-// Purpose:		score/results/ranking screen
-//
-// $NoKeywords: $osuss
-//===============================================================================//
-
 #include "RankingScreen.h"
 
 #include "AnimationHandler.h"
@@ -33,6 +26,7 @@
 #include "SongBrowser/SongBrowser.h"
 #include "SoundEngine.h"
 #include "TooltipOverlay.h"
+#include "UIButton.h"
 #include "UIRankingScreenInfoLabel.h"
 #include "UIRankingScreenRankingPanel.h"
 #include "score.h"
@@ -159,10 +153,10 @@ RankingScreen::RankingScreen() : ScreenBackable() {
 
     m_rankings = new CBaseUIScrollView(-1, 0, 0, 0, "");
     m_rankings->setHorizontalScrolling(false);
-    m_rankings->setVerticalScrolling(true);
+    m_rankings->setVerticalScrolling(false);
     m_rankings->setDrawFrame(false);
     m_rankings->setDrawBackground(false);
-    m_rankings->setDrawScrollbars(true);
+    m_rankings->setDrawScrollbars(false);
     addBaseUIElement(m_rankings);
 
     m_songInfo = new UIRankingScreenInfoLabel(5, 5, 0, 0, "");
@@ -193,19 +187,12 @@ RankingScreen::RankingScreen() : ScreenBackable() {
     m_rankingIndex->setTextColor(0xffffcb21);
     m_rankings->getContainer()->addBaseUIElement(m_rankingIndex);
 
-    m_rankingScrollDownInfoButton = new RankingScreenScrollDownInfoButton();
-    m_rankingScrollDownInfoButton->setFont(osu->getFontIcons());
-    m_rankingScrollDownInfoButton->setClickCallback(
-        fastdelegate::MakeDelegate(this, &RankingScreen::onScrollDownClicked));
-    UString iconString;
-    iconString.insert(0, Icons::ARROW_DOWN);
-    iconString.append("   ");
-    iconString.insert(iconString.length(), Icons::ARROW_DOWN);
-    iconString.append("   ");
-    iconString.insert(iconString.length(), Icons::ARROW_DOWN);
-    m_rankingScrollDownInfoButton->setText(iconString);
-    addBaseUIElement(m_rankingScrollDownInfoButton);
-    m_fRankingScrollDownInfoButtonAlphaAnim = 1.0f;
+    m_retry_btn = new UIButton(0, 0, 0, 0, "", "Retry");
+    m_retry_btn->setClickCallback(fastdelegate::MakeDelegate(this, &RankingScreen::onRetryClicked));
+    addBaseUIElement(m_retry_btn);
+    m_watch_btn = new UIButton(0, 0, 0, 0, "", "Watch replay");
+    m_watch_btn->setClickCallback(fastdelegate::MakeDelegate(this, &RankingScreen::onWatchClicked));
+    addBaseUIElement(m_watch_btn);
 
     setGrade(FinishedScore::Grade::D);
     setIndex(0);  // TEMP
@@ -333,7 +320,7 @@ void RankingScreen::draw(Graphics *g) {
     // draw pp
     if(osu_rankingscreen_pp.getBool() && !m_bIsLegacyScore) {
         const UString ppString = getPPString();
-        const Vector2 ppPos = getPPPosRaw() + m_vPPCursorMagnetAnimation;
+        const Vector2 ppPos = getPPPosRaw();
 
         g->pushTransform();
         {
@@ -347,8 +334,6 @@ void RankingScreen::draw(Graphics *g) {
         g->popTransform();
     }
 
-    if(m_osu_scores_enabled->getBool()) m_rankingScrollDownInfoButton->draw(g);
-
     // draw top black bar
     g->setColor(0xff000000);
     g->fillRect(0, 0, osu->getScreenWidth(),
@@ -373,9 +358,6 @@ void RankingScreen::mouse_update(bool *propagate_clicks) {
     if(!m_bVisible) return;
     ScreenBackable::mouse_update(propagate_clicks);
 
-    // HACKHACK:
-    if(osu->getOptionsMenu()->isMouseInside()) engine->getMouse()->resetWheelDelta();
-
     // tooltip (pp + accuracy + unstable rate)
     if(!osu->getOptionsMenu()->isMouseInside() && !m_bIsLegacyScore &&
        engine->getMouse()->getPos().x < osu->getScreenWidth() * 0.5f) {
@@ -401,33 +383,6 @@ void RankingScreen::mouse_update(bool *propagate_clicks) {
         }
         osu->getTooltipOverlay()->end();
     }
-
-    // frustration multiplier
-    Vector2 cursorDelta = getPPPosCenterRaw() - engine->getMouse()->getPos();
-    Vector2 norm;
-    const float dist = 150.0f;
-    if(cursorDelta.length() > dist) {
-        cursorDelta.x = 0;
-        cursorDelta.y = 0;
-    } else {
-        norm = cursorDelta;
-        norm.normalize();
-    }
-    float percent = 1.0f - (cursorDelta.length() / dist);
-    Vector2 target = norm * percent * percent * (dist + 50);
-    anim->moveQuadOut(&m_vPPCursorMagnetAnimation.x, target.x, 0.20f, true);
-    anim->moveQuadOut(&m_vPPCursorMagnetAnimation.y, target.y, 0.20f, true);
-
-    // button transparency
-    const float transparencyStart = getPos().y + getSize().y;
-    const float transparencyEnd = getPos().y + getSize().y + m_rankingIndex->getSize().y / 2;
-    const float alpha =
-        clamp<float>((m_rankingIndex->getPos().y + (transparencyEnd - transparencyStart) - transparencyStart) /
-                         (transparencyEnd - transparencyStart),
-                     0.0f, 1.0f);
-    anim->moveLinear(&m_fRankingScrollDownInfoButtonAlphaAnim, alpha, 0.075 * m_fRankingScrollDownInfoButtonAlphaAnim,
-                     true);
-    m_rankingScrollDownInfoButton->setAlpha(m_fRankingScrollDownInfoButtonAlphaAnim);
 }
 
 CBaseUIContainer *RankingScreen::setVisible(bool visible) {
@@ -435,77 +390,61 @@ CBaseUIContainer *RankingScreen::setVisible(bool visible) {
 
     if(m_bVisible) {
         m_backButton->resetAnimation();
-        m_rankings->scrollToY(0, false);
-
         updateLayout();
-    } else if(bancho.is_in_a_multi_room()) {
-        // We backed out of the ranking screen, display the room again
-        osu->m_room->setVisible(true);
-        osu->m_chat->updateVisibility();
-        engine->getSound()->play(osu->getSkin()->m_menuBack);
-
-        // Since we prevented on_map_change() from running while the ranking screen was visible, run it now.
-        osu->m_room->on_map_change();
+    } else {
+        // Stop applause sound
+        if(osu->getSkin()->getApplause() != NULL && osu->getSkin()->getApplause()->isPlaying()) {
+            engine->getSound()->stop(osu->getSkin()->getApplause());
+        }
+
+        if(bancho.is_in_a_multi_room()) {
+            // We backed out of the ranking screen, display the room again
+            osu->m_room->setVisible(true);
+            osu->m_chat->updateVisibility();
+
+            // Since we prevented on_map_change() from running while the ranking screen was visible, run it now.
+            osu->m_room->on_map_change();
+        } else {
+            osu->m_songBrowser2->setVisible(true);
+        }
     }
 
     return this;
 }
 
-void RankingScreen::setScore(LiveScore *score) {
-    m_rankingPanel->setScore(score);
-    setGrade(score->getGrade());
-    setIndex(score->getIndex());
-
-    m_fUnstableRate = score->getUnstableRate();
-    m_fHitErrorAvgMin = score->getHitErrorAvgMin();
-    m_fHitErrorAvgMax = score->getHitErrorAvgMax();
-    m_fStarsTomTotal = score->getStarsTomTotal();
-    m_fStarsTomAim = score->getStarsTomAim();
-    m_fStarsTomSpeed = score->getStarsTomSpeed();
-    m_fPPv2 = score->getPPv2();
-
-    const UString modsString = ScoreButton::getModsStringForDisplay(score->getModsLegacy());
-    if(modsString.length() > 0) {
-        m_sMods = "Mods: ";
-        m_sMods.append(modsString);
-    } else
-        m_sMods = "";
+void RankingScreen::onRetryClicked() {
+    // TODO @kiwec: test this
+    setVisible(false);
+    osu->getSelectedBeatmap()->play();
+}
 
-    m_bModSS = osu->getModSS();
-    m_bModSD = osu->getModSD();
-    m_bModEZ = osu->getModEZ();
-    m_bModHD = osu->getModHD();
-    m_bModHR = osu->getModHR();
-    m_bModNC = osu->getModNC();
-    m_bModDT = osu->getModDT();
-    m_bModNightmare = osu->getModNightmare();
-    m_bModScorev2 = osu->getModScorev2();
-    m_bModTarget = osu->getModTarget();
-    m_bModSpunout = osu->getModSpunout();
-    m_bModRelax = osu->getModRelax();
-    m_bModNF = osu->getModNF();
-    m_bModHT = osu->getModHT();
-    m_bModAutopilot = osu->getModAutopilot();
-    m_bModAuto = osu->getModAuto();
-    m_bModTD = osu->getModTD();
+void RankingScreen::onWatchClicked() {
+    // TODO @kiwec: doesn't work, just backs out to song browser, idk why
+    setVisible(false);
+    osu->getSelectedBeatmap()->watch(m_score, 0.0);
+}
 
-    m_enabledExperimentalMods.clear();
-    std::vector<ConVar *> allExperimentalMods = osu->getExperimentalMods();
-    for(int i = 0; i < allExperimentalMods.size(); i++) {
-        if(allExperimentalMods[i]->getBool()) m_enabledExperimentalMods.push_back(allExperimentalMods[i]);
-    }
+void RankingScreen::setScore(FinishedScore score) {
+    auto current_name = convar->getConVarByName("name")->getString();
+    bool is_same_player = !score.playerName.compare(current_name.toUtf8());
 
-    m_bIsLegacyScore = false;
-    m_bIsImportedLegacyScore = false;
-    m_bIsUnranked = score->isUnranked();
-}
+    m_score = score;
+    // TODO @kiwec: broken
+    m_retry_btn->setVisible(false);
+    m_watch_btn->setVisible(false);
+    // m_retry_btn->setVisible(is_same_player && !bancho.is_in_a_multi_room());
+    // m_watch_btn->setVisible(score.has_replay && !bancho.is_in_a_multi_room());
 
-void RankingScreen::setScore(FinishedScore score, UString dateTime) {
     m_bIsLegacyScore = score.isLegacyScore;
     m_bIsImportedLegacyScore = score.isImportedLegacyScore;
     m_bIsUnranked = false;
 
-    m_songInfo->setDate(dateTime.toUtf8());
+    char dateString[64];
+    memset(dateString, '\0', 64);
+    std::tm *tm = std::localtime((std::time_t *)(&score.unixTimestamp));
+    std::strftime(dateString, 63, "%d-%b-%y %H:%M:%S", tm);
+
+    m_songInfo->setDate(dateString);
     m_songInfo->setPlayer(score.playerName);
 
     m_rankingPanel->setScore(score);
@@ -572,6 +511,7 @@ void RankingScreen::setScore(FinishedScore score, UString dateTime) {
 }
 
 void RankingScreen::setBeatmapInfo(Beatmap *beatmap, DatabaseBeatmap *diff2) {
+    m_score.diff2 = diff2;
     m_songInfo->setFromBeatmap(beatmap, diff2);
 
     UString local_name = convar->getConVarByName("name")->getString();
@@ -603,6 +543,14 @@ void RankingScreen::updateLayout() {
                         max(m_songInfo->getMinimumHeight(),
                             m_rankingTitle->getSize().y * osu_rankingscreen_topbar_height_percent.getFloat()));
 
+    // TODO @kiwec: buttons are not placed at the given coords, idk why
+    m_retry_btn->setSize(150 * uiScale, 50 * uiScale);
+    m_watch_btn->setSize(150 * uiScale, 50 * uiScale);
+    m_retry_btn->setPos(osu->getScreenSize().x - (150 * uiScale + 10.f * uiScale),
+                        osu->getScreenSize().y - (50 * uiScale + 10.f * uiScale));
+    m_watch_btn->setPos(osu->getScreenSize().x - (150 * uiScale + 10.f * uiScale),
+                        osu->getScreenSize().y - (50 * uiScale * 2.f + 20.f * uiScale));
+
     m_rankings->setSize(osu->getScreenSize().x + 2, osu->getScreenSize().y - m_songInfo->getSize().y + 3);
     m_rankings->setRelPosY(m_songInfo->getSize().y - 1);
     update_pos();
@@ -625,11 +573,6 @@ void RankingScreen::updateLayout() {
     m_rankingBottom->setSize(m_rankings->getSize().x + 2, osu->getScreenHeight() * 0.2f);
     m_rankingBottom->setRelPosY(m_rankingIndex->getRelPos().y + m_rankingIndex->getSize().y);
 
-    m_rankingScrollDownInfoButton->setSize(getSize().x * 0.2f * uiScale, getSize().y * 0.1f * uiScale);
-    m_rankingScrollDownInfoButton->setRelPos(
-        getPos().x + getSize().x / 2 - m_rankingScrollDownInfoButton->getSize().x / 2,
-        getSize().y - m_rankingScrollDownInfoButton->getSize().y);
-
     setGrade(m_grade);
 
     update_pos();
@@ -637,20 +580,7 @@ void RankingScreen::updateLayout() {
     m_rankings->setScrollSizeToContent(0);
 }
 
-void RankingScreen::onBack() {
-    engine->getSound()->play(osu->getSkin()->m_menuBack);
-
-    // stop applause sound
-    if(osu->getSkin()->getApplause() != NULL && osu->getSkin()->getApplause()->isPlaying())
-        engine->getSound()->stop(osu->getSkin()->getApplause());
-
-    setVisible(false);
-    if(!bancho.is_in_a_multi_room() && osu->m_songBrowser2 != NULL) {
-        osu->m_songBrowser2->setVisible(true);
-    }
-}
-
-void RankingScreen::onScrollDownClicked() { m_rankings->scrollToBottom(); }
+void RankingScreen::onBack() { setVisible(false); }
 
 void RankingScreen::setGrade(FinishedScore::Grade grade) {
     m_grade = grade;
@@ -712,11 +642,9 @@ void RankingScreen::setIndex(int index) {
         m_rankingIndex->setText(UString::format("You achieved the #%i score on local rankings!", (index + 1)));
         m_rankingIndex->setVisible2(true);
         m_rankingBottom->setVisible2(true);
-        m_rankingScrollDownInfoButton->setVisible2(index < 1);  // only show button if we made a new highscore
     } else {
         m_rankingIndex->setVisible2(false);
         m_rankingBottom->setVisible2(false);
-        m_rankingScrollDownInfoButton->setVisible2(false);
     }
 }
 

+ 9 - 22
src/App/Osu/RankingScreen.h

@@ -1,13 +1,4 @@
-//================ Copyright (c) 2016, PG, All rights reserved. =================//
-//
-// Purpose:		score/results/ranking screen
-//
-// $NoKeywords: $osuss
-//===============================================================================//
-
-#ifndef OSU_OSURANKINGSCREEN_H
-#define OSU_OSURANKINGSCREEN_H
-
+#pragma once
 #include "Database.h"
 #include "ScreenBackable.h"
 #include "score.h"
@@ -20,13 +11,11 @@ class CBaseUILabel;
 class Beatmap;
 class DatabaseBeatmap;
 class SkinImage;
-
+class UIButton;
 class UIRankingScreenInfoLabel;
 class UIRankingScreenRankingPanel;
-
 class RankingScreenIndexLabel;
 class RankingScreenBottomElement;
-class RankingScreenScrollDownInfoButton;
 
 class ConVar;
 
@@ -39,8 +28,10 @@ class RankingScreen : public ScreenBackable {
 
     virtual CBaseUIContainer *setVisible(bool visible);
 
-    void setScore(LiveScore *score);
-    void setScore(FinishedScore score, UString dateTime);
+    void onRetryClicked();
+    void onWatchClicked();
+
+    void setScore(FinishedScore score);
     void setBeatmapInfo(Beatmap *beatmap, DatabaseBeatmap *diff2);
 
    private:
@@ -49,8 +40,6 @@ class RankingScreen : public ScreenBackable {
 
     void drawModImage(Graphics *g, SkinImage *image, Vector2 &pos, Vector2 &max);
 
-    void onScrollDownClicked();
-
     void setGrade(FinishedScore::Grade grade);
     void setIndex(int index);
 
@@ -69,8 +58,8 @@ class RankingScreen : public ScreenBackable {
     RankingScreenIndexLabel *m_rankingIndex;
     RankingScreenBottomElement *m_rankingBottom;
 
-    RankingScreenScrollDownInfoButton *m_rankingScrollDownInfoButton;
-    float m_fRankingScrollDownInfoButtonAlphaAnim;
+    UIButton *m_retry_btn;
+    UIButton *m_watch_btn;
 
     FinishedScore::Grade m_grade;
     float m_fUnstableRate;
@@ -110,10 +99,8 @@ class RankingScreen : public ScreenBackable {
     std::vector<ConVar *> m_enabledExperimentalMods;
 
     // custom
-    Vector2 m_vPPCursorMagnetAnimation;
+    FinishedScore m_score;
     bool m_bIsLegacyScore;
     bool m_bIsImportedLegacyScore;
     bool m_bIsUnranked;
 };
-
-#endif

+ 4 - 1
src/App/Osu/Replay.cpp

@@ -1,9 +1,12 @@
 #include "Replay.h"
 
+#ifndef LZMA_API_STATIC
 #define LZMA_API_STATIC
+#endif
 #include <lzma.h>
-#include <string>
+
 #include <sstream>
+#include <string>
 
 #include "Bancho.h"
 #include "BanchoProtocol.h"

+ 37 - 2
src/App/Osu/RoomScreen.cpp

@@ -705,11 +705,46 @@ void RoomScreen::on_player_failed(i32 slot_id) {
     bancho.room.slots[slot_id].died = true;
 }
 
+FinishedScore RoomScreen::get_approximate_score() {
+    FinishedScore score;
+    score.isLegacyScore = true;
+    score.version = LiveScore::VERSION;
+    score.player_id = bancho.user_id;
+    score.playerName = bancho.username.toUtf8();
+    score.diff2 = osu->getSelectedBeatmap()->getSelectedDifficulty2();
+
+    for(int i = 0; i < 16; i++) {
+        auto slot = &bancho.room.slots[i];
+        if(slot->player_id != bancho.user_id) continue;
+
+        score.modsLegacy = slot->mods;
+        score.passed = !slot->died;
+        score.unixTimestamp = slot->last_update_tms;
+        score.num300s = slot->num300;
+        score.num100s = slot->num100;
+        score.num50s = slot->num50;
+        score.numGekis = slot->num_geki;
+        score.numKatus = slot->num_katu;
+        score.numMisses = slot->num_miss;
+        score.score = slot->total_score;
+        score.comboMax = slot->max_combo;
+        score.perfect = slot->is_perfect;
+    }
+
+    score.grade =
+        LiveScore::calculateGrade(score.num300s, score.num100s, score.num50s, score.numMisses,
+                                  score.modsLegacy & ModFlags::Hidden, score.modsLegacy & ModFlags::Flashlight);
+
+    return score;
+}
+
 // All players have finished.
 void RoomScreen::on_match_finished() {
     if(!bancho.is_playing_a_multi_map()) return;
     memcpy(bancho.last_scores, bancho.room.slots, sizeof(bancho.room.slots));
-    osu->onPlayEnd(false, false);
+
+    osu->onPlayEnd(get_approximate_score(), false, false);
+
     bancho.match_started = false;
     osu->m_rankingScreen->setVisible(true);
     osu->m_chat->updateVisibility();
@@ -728,7 +763,7 @@ void RoomScreen::on_player_skip(i32 user_id) {
 
 void RoomScreen::on_match_aborted() {
     if(!bancho.is_playing_a_multi_map()) return;
-    osu->onPlayEnd(false, true);
+    osu->onPlayEnd(get_approximate_score(), false, true);
     m_bVisible = true;
     bancho.match_started = false;
 }

+ 3 - 0
src/App/Osu/RoomScreen.h

@@ -6,6 +6,7 @@
 #include "BanchoProtocol.h"
 #include "CBaseUIScrollView.h"
 #include "OsuScreen.h"
+#include "score.h"
 
 class CBaseUICheckbox;
 class CBaseUILabel;
@@ -57,6 +58,8 @@ class RoomScreen : public OsuScreen {
     void onClientScoreChange(bool force = false);
     void onReadyButtonClick();
 
+    FinishedScore get_approximate_score();
+
     // Host only
     void onStartGameClicked();
     void onSelectModsClicked();

+ 3 - 0
src/App/Osu/ScreenBackable.cpp

@@ -1,10 +1,12 @@
 #include "ScreenBackable.h"
 
+#include "Engine.h"
 #include "KeyBindings.h"
 #include "Keyboard.h"
 #include "Osu.h"
 #include "ResourceManager.h"
 #include "Skin.h"
+#include "SoundEngine.h"
 #include "UIBackButton.h"
 
 ScreenBackable::ScreenBackable() : OsuScreen() {
@@ -34,6 +36,7 @@ void ScreenBackable::onKeyDown(KeyboardEvent &e) {
     if(!m_bVisible || e.isConsumed()) return;
 
     if(e == KEY_ESCAPE || e == (KEYCODE)KeyBindings::GAME_PAUSE.getInt()) {
+        engine->getSound()->play(osu->getSkin()->m_menuBack);
         onBack();
         e.consume();
         return;

+ 2 - 7
src/App/Osu/Skin.cpp

@@ -486,7 +486,8 @@ void Skin::load() {
     // skin ini
     randomizeFilePath();
     m_sSkinIniFilePath = m_sFilePath;
-    m_sSkinIniFilePath.append("skin.ini");
+    m_sSkinIniFilePath.append(fix_filename_casing(m_sFilePath, "skin.ini"));
+
     bool parseSkinIni1Status = true;
     bool parseSkinIni2Status = true;
     if(!parseSkinINI(m_sSkinIniFilePath)) {
@@ -1297,14 +1298,11 @@ void Skin::playHitCircleSound(int sampleType, float pan, long delta) {
         pan *= osu_sound_panning_multiplier.getFloat();
     }
 
-    debugLog("delta: %d\n", delta);
     if(delta < 0 && m_tooearly != NULL) {
-        debugLog("Too early!\n");
         engine->getSound()->play(m_tooearly, pan);
         return;
     }
     if(delta > 0 && m_toolate != NULL) {
-        debugLog("Too late!\n");
         engine->getSound()->play(m_toolate, pan);
         return;
     }
@@ -1589,7 +1587,6 @@ void Skin::checkLoadSound(Sound **addressOfPointer, std::string skinElementName,
 
             std::string path = base_path;
             path.append(fn);
-            debugLog("Loading %s\n", path.c_str());
 
             if(env->fileExists(path)) {
                 if(osu_skin_async.getBool()) {
@@ -1599,8 +1596,6 @@ void Skin::checkLoadSound(Sound **addressOfPointer, std::string skinElementName,
             }
         }
 
-        debugLog("Failed to load %s\n", filename.c_str());
-
         return (Sound *)NULL;
     };
 

+ 3 - 7
src/App/Osu/SongBrowser/SongBrowser.cpp

@@ -2467,10 +2467,7 @@ void SongBrowser::updateLayout() {
     m_search->setSize(m_songBrowser->getSize());
 }
 
-void SongBrowser::onBack() {
-    engine->getSound()->play(osu->getSkin()->m_menuBack);
-    osu->toggleSongBrowser();
-}
+void SongBrowser::onBack() { osu->toggleSongBrowser(); }
 
 void SongBrowser::updateScoreBrowserLayout() {
     const float dpiScale = Osu::getUIScale();
@@ -3544,10 +3541,9 @@ void SongBrowser::onUserCardChange(UString new_username) {
 void SongBrowser::onScoreClicked(CBaseUIButton *button) {
     ScoreButton *scoreButton = (ScoreButton *)button;
 
-    // NOTE: the order of these two calls matters (score data overwrites relevant fields, but base values are coming
-    // from the beatmap)
+    // NOTE: the order of these two calls matters
+    osu->getRankingScreen()->setScore(scoreButton->getScore());
     osu->getRankingScreen()->setBeatmapInfo(m_selectedBeatmap, m_selectedBeatmap->getSelectedDifficulty2());
-    osu->getRankingScreen()->setScore(scoreButton->getScore(), scoreButton->getDateTime());
 
     osu->getSongBrowser()->setVisible(false);
     osu->getRankingScreen()->setVisible(true);

+ 2 - 0
src/App/Osu/VolumeOverlay.cpp

@@ -19,6 +19,7 @@
 #include "SongBrowser/SongBrowser.h"
 #include "Sound.h"
 #include "SoundEngine.h"
+#include "UIContextMenu.h"
 #include "UIVolumeSlider.h"
 
 VolumeOverlay::VolumeOverlay() : OsuScreen() {
@@ -244,6 +245,7 @@ bool VolumeOverlay::canChangeVolume() {
         can_scroll = false;
     }
     if(osu->m_optionsMenu->isVisible()) can_scroll = false;
+    if(osu->m_optionsMenu->m_contextMenu->isVisible()) can_scroll = false;
     if(osu->m_changelog->isVisible()) can_scroll = false;
     if(osu->m_rankingScreen->isVisible()) can_scroll = false;
     if(osu->m_modSelector->isMouseInScrollView()) can_scroll = false;