|
@@ -140,6 +140,7 @@ ConVar flashlight_radius("flashlight_radius", 100.f, FCVAR_CHEAT);
|
|
|
ConVar flashlight_follow_delay("flashlight_follow_delay", 0.120f, FCVAR_CHEAT);
|
|
|
ConVar flashlight_always_hard("flashlight_always_hard", false, FCVAR_NONE, "always use 200+ combo flashlight radius");
|
|
|
|
|
|
+ConVar start_first_main_menu_song_at_preview_point("start_first_main_menu_song_at_preview_point", false, FCVAR_NONE);
|
|
|
ConVar nightcore_enjoyer("nightcore_enjoyer", false, FCVAR_NONE, "automatically select nightcore when speed modifying");
|
|
|
ConVar scoreboard_animations("scoreboard_animations", true, FCVAR_NONE, "animate in-game scoreboard");
|
|
|
|
|
@@ -317,7 +318,6 @@ Osu::Osu(int instanceID) {
|
|
|
m_bKeyboardKey22Down = false;
|
|
|
m_bMouseKey1Down = false;
|
|
|
m_bMouseKey2Down = false;
|
|
|
- m_bSkipDownCheck = false;
|
|
|
m_bSkipScheduled = false;
|
|
|
m_bQuickRetryDown = false;
|
|
|
m_fQuickRetryTime = 0.0f;
|
|
@@ -505,16 +505,6 @@ Osu::Osu(int instanceID) {
|
|
|
m_screens.push_back(m_mainMenu);
|
|
|
m_screens.push_back(m_tooltipOverlay);
|
|
|
|
|
|
- // make primary screen visible
|
|
|
- // m_optionsMenu->setVisible(true);
|
|
|
- // m_modSelector->setVisible(true);
|
|
|
- // m_songBrowser2->setVisible(true);
|
|
|
- // m_pauseMenu->setVisible(true);
|
|
|
- // m_rankingScreen->setVisible(true);
|
|
|
- // m_changelog->setVisible(true);
|
|
|
- // m_editor->setVisible(true);
|
|
|
- // m_userStatsScreen->setVisible(true);
|
|
|
-
|
|
|
// Init online functionality (multiplayer/leaderboards/etc)
|
|
|
bancho.osu = this;
|
|
|
init_networking_thread();
|
|
@@ -527,23 +517,6 @@ Osu::Osu(int instanceID) {
|
|
|
|
|
|
m_updateHandler->checkForUpdates();
|
|
|
|
|
|
- /*
|
|
|
- // DEBUG: immediately start diff of a beatmap
|
|
|
- {
|
|
|
- UString debugFolder = "S:/GAMES/osu!/Songs/41823 The Quick Brown Fox - The Big Black/";
|
|
|
- UString debugDiffFileName = "The Quick Brown Fox - The Big Black (Blue Dragon) [WHO'S AFRAID OF THE BIG
|
|
|
- BLACK].osu";
|
|
|
-
|
|
|
- UString beatmapPath = debugFolder;
|
|
|
- beatmapPath.append(debugDiffFileName);
|
|
|
-
|
|
|
- OsuDatabaseBeatmap *debugDiff = new OsuDatabaseBeatmap(this, beatmapPath, debugFolder);
|
|
|
-
|
|
|
- m_songBrowser2->onDifficultySelected(debugDiff, true);
|
|
|
- // WARNING: this will leak memory (one OsuDatabaseBeatmap object), but who cares (since debug only)
|
|
|
- }
|
|
|
- */
|
|
|
-
|
|
|
// memory/performance optimization; if osu_mod_mafham is not enabled, reduce the two rendertarget sizes to 64x64,
|
|
|
m_osu_mod_mafham_ref->setCallback(fastdelegate::MakeDelegate(this, &Osu::onModMafhamChange));
|
|
|
m_osu_mod_fposu_ref->setCallback(fastdelegate::MakeDelegate(this, &Osu::onModFPoSuChange));
|
|
@@ -824,69 +797,29 @@ void Osu::update() {
|
|
|
// NOTE: force keep loaded background images while playing
|
|
|
m_backgroundImageHandler->scheduleFreezeCache();
|
|
|
|
|
|
- // scrubbing/seeking
|
|
|
- if(m_bSeekKey || getSelectedBeatmap()->m_bIsWatchingReplay) {
|
|
|
- if(!bancho.is_playing_a_multi_map()) {
|
|
|
- m_bSeeking = true;
|
|
|
- const float mousePosX = (int)engine->getMouse()->getPos().x;
|
|
|
- const float percent = clamp<float>(mousePosX / (float)getScreenWidth(), 0.0f, 1.0f);
|
|
|
-
|
|
|
- if(engine->getMouse()->isLeftDown()) {
|
|
|
- if(mousePosX != m_fPrevSeekMousePosX || !osu_scrubbing_smooth.getBool()) {
|
|
|
- m_fPrevSeekMousePosX = mousePosX;
|
|
|
-
|
|
|
- // special case: allow cancelling the failing animation here
|
|
|
- if(getSelectedBeatmap()->hasFailed()) getSelectedBeatmap()->cancelFailing();
|
|
|
-
|
|
|
- getSelectedBeatmap()->seekPercentPlayable(percent);
|
|
|
- } else {
|
|
|
- // special case: keep player invulnerable even if scrubbing position does not change
|
|
|
- getSelectedBeatmap()->resetScore();
|
|
|
- }
|
|
|
- } else {
|
|
|
- m_fPrevSeekMousePosX = -1.0f;
|
|
|
- }
|
|
|
-
|
|
|
- if(engine->getMouse()->isRightDown()) {
|
|
|
- m_fQuickSaveTime = clamp<float>((float)((getSelectedBeatmap()->getStartTimePlayable() +
|
|
|
- getSelectedBeatmap()->getLengthPlayable()) *
|
|
|
- percent) /
|
|
|
- (float)getSelectedBeatmap()->getLength(),
|
|
|
- 0.0f, 1.0f);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
// skip button clicking
|
|
|
- if(getSelectedBeatmap()->isInSkippableSection() && !getSelectedBeatmap()->isPaused() && !m_bSeeking &&
|
|
|
- !m_volumeOverlay->isBusy()) {
|
|
|
+ bool can_skip = getSelectedBeatmap()->isInSkippableSection() && !m_bClickedSkipButton;
|
|
|
+ can_skip &= !getSelectedBeatmap()->isPaused() && !m_volumeOverlay->isBusy();
|
|
|
+ if(can_skip) {
|
|
|
const bool isAnyOsuKeyDown = (m_bKeyboardKey1Down || m_bKeyboardKey12Down || m_bKeyboardKey2Down ||
|
|
|
m_bKeyboardKey22Down || m_bMouseKey1Down || m_bMouseKey2Down);
|
|
|
const bool isAnyKeyDown = (isAnyOsuKeyDown || engine->getMouse()->isLeftDown());
|
|
|
|
|
|
if(isAnyKeyDown) {
|
|
|
- if(!m_bSkipDownCheck) {
|
|
|
- m_bSkipDownCheck = true;
|
|
|
-
|
|
|
- const bool isCursorInsideSkipButton =
|
|
|
- m_hud->getSkipClickRect().contains(engine->getMouse()->getPos());
|
|
|
-
|
|
|
- if(isCursorInsideSkipButton) {
|
|
|
- if(!m_bSkipScheduled) {
|
|
|
- m_bSkipScheduled = true;
|
|
|
-
|
|
|
- if(bancho.is_playing_a_multi_map()) {
|
|
|
- Packet packet;
|
|
|
- packet.id = MATCH_SKIP_REQUEST;
|
|
|
- send_packet(packet);
|
|
|
- }
|
|
|
+ if(m_hud->getSkipClickRect().contains(engine->getMouse()->getPos())) {
|
|
|
+ if(!m_bSkipScheduled) {
|
|
|
+ m_bSkipScheduled = true;
|
|
|
+ m_bClickedSkipButton = true;
|
|
|
+
|
|
|
+ if(bancho.is_playing_a_multi_map()) {
|
|
|
+ Packet packet;
|
|
|
+ packet.id = MATCH_SKIP_REQUEST;
|
|
|
+ send_packet(packet);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
- } else
|
|
|
- m_bSkipDownCheck = false;
|
|
|
- } else
|
|
|
- m_bSkipDownCheck = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// skipping
|
|
|
if(m_bSkipScheduled) {
|
|
@@ -910,6 +843,47 @@ void Osu::update() {
|
|
|
if(!isLoading) m_bSkipScheduled = false;
|
|
|
}
|
|
|
|
|
|
+ // Reset m_bClickedSkipButton on mouse up
|
|
|
+ // We only use m_bClickedSkipButton to prevent seeking when clicking the skip button
|
|
|
+ if(m_bClickedSkipButton && !getSelectedBeatmap()->isInSkippableSection()) {
|
|
|
+ if(!engine->getMouse()->isLeftDown()) {
|
|
|
+ m_bClickedSkipButton = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // scrubbing/seeking
|
|
|
+ m_bSeeking = (m_bSeekKey || getSelectedBeatmap()->m_bIsWatchingReplay);
|
|
|
+ m_bSeeking &= !getSelectedBeatmap()->isPaused() && !m_volumeOverlay->isBusy();
|
|
|
+ m_bSeeking &= !bancho.is_playing_a_multi_map() && !m_bClickedSkipButton;
|
|
|
+ if(m_bSeeking) {
|
|
|
+ const float mousePosX = (int)engine->getMouse()->getPos().x;
|
|
|
+ const float percent = clamp<float>(mousePosX / (float)getScreenWidth(), 0.0f, 1.0f);
|
|
|
+
|
|
|
+ if(engine->getMouse()->isLeftDown()) {
|
|
|
+ if(mousePosX != m_fPrevSeekMousePosX || !osu_scrubbing_smooth.getBool()) {
|
|
|
+ m_fPrevSeekMousePosX = mousePosX;
|
|
|
+
|
|
|
+ // special case: allow cancelling the failing animation here
|
|
|
+ if(getSelectedBeatmap()->hasFailed()) getSelectedBeatmap()->cancelFailing();
|
|
|
+
|
|
|
+ getSelectedBeatmap()->seekPercentPlayable(percent);
|
|
|
+ } else {
|
|
|
+ // special case: keep player invulnerable even if scrubbing position does not change
|
|
|
+ getSelectedBeatmap()->resetScore();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ m_fPrevSeekMousePosX = -1.0f;
|
|
|
+ }
|
|
|
+
|
|
|
+ if(engine->getMouse()->isRightDown()) {
|
|
|
+ m_fQuickSaveTime = clamp<float>(
|
|
|
+ (float)((getSelectedBeatmap()->getStartTimePlayable() + getSelectedBeatmap()->getLengthPlayable()) *
|
|
|
+ percent) /
|
|
|
+ (float)getSelectedBeatmap()->getLength(),
|
|
|
+ 0.0f, 1.0f);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// quick retry timer
|
|
|
if(m_bQuickRetryDown && m_fQuickRetryTime != 0.0f && engine->getTime() > m_fQuickRetryTime) {
|
|
|
m_fQuickRetryTime = 0.0f;
|
|
@@ -1270,6 +1244,37 @@ void Osu::onKeyDown(KeyboardEvent &key) {
|
|
|
|
|
|
// while playing (and not in options)
|
|
|
if(isInPlayMode() && !m_optionsMenu->isVisible() && !m_chat->isVisible()) {
|
|
|
+ auto beatmap = getSelectedBeatmap();
|
|
|
+
|
|
|
+ // instant replay
|
|
|
+ if((beatmap->isPaused() || beatmap->hasFailed())) {
|
|
|
+ if(!key.isConsumed() && key == (KEYCODE)OsuKeyBindings::INSTANT_REPLAY.getInt()) {
|
|
|
+ if(!beatmap->m_bIsWatchingReplay) {
|
|
|
+ Score score;
|
|
|
+ score.replay = beatmap->live_replay;
|
|
|
+ score.md5hash = beatmap->getSelectedDifficulty2()->getMD5Hash();
|
|
|
+ score.modsLegacy = getScore()->getModsLegacy();
|
|
|
+
|
|
|
+ // XXX: code reuse from saveAndSubmitScore, also incorrect when using Auto
|
|
|
+ if(bancho.is_online()) {
|
|
|
+ score.player_id = bancho.user_id;
|
|
|
+ score.playerName = bancho.username.toUtf8();
|
|
|
+ } else {
|
|
|
+ auto local_name = convar->getConVarByName("name")->getString();
|
|
|
+ score.player_id = 0;
|
|
|
+ score.playerName = local_name.toUtf8();
|
|
|
+ }
|
|
|
+
|
|
|
+ double percentFinished = beatmap->getPercentFinished();
|
|
|
+ double offsetPercent = 10000.f / beatmap->getLength();
|
|
|
+ double seekPoint = fmax(0.f, percentFinished - offsetPercent);
|
|
|
+ beatmap->cancelFailing();
|
|
|
+ beatmap->watch(score, seekPoint);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// while playing and not paused
|
|
|
if(!getSelectedBeatmap()->isPaused()) {
|
|
|
getSelectedBeatmap()->onKeyDown(key);
|