diff --git a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
index dbfb13f7a6..fb843d7ea0 100644
--- a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
+++ b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.cpp
@@ -13,10 +13,11 @@
#include "Core/AchievementManager.h"
#include "Core/Config/AchievementSettings.h"
+#include "Core/Config/FreeLookSettings.h"
#include "Core/Config/MainSettings.h"
#include "Core/Core.h"
+#include "Core/Movie.h"
-#include "DolphinQt/Achievements/AchievementsWindow.h"
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
#include "DolphinQt/Config/ToolTipControls/ToolTipCheckBox.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
@@ -24,11 +25,7 @@
#include "DolphinQt/QtUtils/SignalBlocking.h"
#include "DolphinQt/Settings.h"
-static constexpr bool hardcore_mode_enabled = false;
-
-AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent,
- AchievementsWindow* parent_window)
- : QWidget(parent), parent_window(parent_window)
+AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent) : QWidget(parent)
{
CreateLayout();
LoadSettings();
@@ -36,6 +33,15 @@ AchievementSettingsWidget::AchievementSettingsWidget(QWidget* parent,
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
&AchievementSettingsWidget::LoadSettings);
+
+ // If hardcore is enabled when the emulator starts, make sure it turns off what it needs to
+ if (Config::Get(Config::RA_HARDCORE_ENABLED))
+ ToggleHardcore();
+}
+
+void AchievementSettingsWidget::UpdateData()
+{
+ LoadSettings();
}
void AchievementSettingsWidget::CreateLayout()
@@ -75,6 +81,20 @@ void AchievementSettingsWidget::CreateLayout()
"achievements.
Unofficial achievements may be optional or unfinished achievements "
"that have not been deemed official by RetroAchievements and may be useful for testing or "
"simply for fun."));
+ m_common_hardcore_enabled_input = new ToolTipCheckBox(tr("Enable Hardcore Mode"));
+ m_common_hardcore_enabled_input->SetDescription(
+ tr("Enable Hardcore Mode on RetroAchievements.
Hardcore Mode is intended to provide "
+ "an experience as close to gaming on the original hardware as possible. RetroAchievements "
+ "rankings are primarily oriented towards Hardcore points (Softcore points are tracked but "
+ "not as heavily emphasized) and leaderboards require Hardcore Mode to be on.
To "
+ "ensure this experience, the following features will be disabled, as they give emulator "
+ "players an advantage over console players:
- Loading states
-- Saving states is "
+ "allowed
- Emulator speeds below 100%
-- Frame advance is disabled
-- Turbo is "
+ "allowed
- Cheats
- Memory patches
-- File patches are allowed
- Debug "
+ "UI
- Freelook
This cannot be turned on while a game is "
+ "playing.
Close your current game before enabling.
Be aware that "
+ "turning Hardcore Mode off while a game is running requires the game to be closed before "
+ "re-enabling."));
m_common_progress_enabled_input = new ToolTipCheckBox(tr("Enable Progress Notifications"));
m_common_progress_enabled_input->SetDescription(
tr("Enable progress notifications on achievements.
Displays a brief popup message "
@@ -102,6 +122,7 @@ void AchievementSettingsWidget::CreateLayout()
m_common_layout->addWidget(m_common_achievements_enabled_input);
m_common_layout->addWidget(m_common_leaderboards_enabled_input);
m_common_layout->addWidget(m_common_rich_presence_enabled_input);
+ m_common_layout->addWidget(m_common_hardcore_enabled_input);
m_common_layout->addWidget(m_common_progress_enabled_input);
m_common_layout->addWidget(m_common_badges_enabled_input);
m_common_layout->addWidget(m_common_unofficial_enabled_input);
@@ -123,6 +144,8 @@ void AchievementSettingsWidget::ConnectWidgets()
&AchievementSettingsWidget::ToggleLeaderboards);
connect(m_common_rich_presence_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleRichPresence);
+ connect(m_common_hardcore_enabled_input, &QCheckBox::toggled, this,
+ &AchievementSettingsWidget::ToggleHardcore);
connect(m_common_progress_enabled_input, &QCheckBox::toggled, this,
&AchievementSettingsWidget::ToggleProgress);
connect(m_common_badges_enabled_input, &QCheckBox::toggled, this,
@@ -145,6 +168,7 @@ void AchievementSettingsWidget::LoadSettings()
{
bool enabled = Config::Get(Config::RA_ENABLED);
bool achievements_enabled = Config::Get(Config::RA_ACHIEVEMENTS_ENABLED);
+ bool hardcore_enabled = Config::Get(Config::RA_HARDCORE_ENABLED);
bool logged_out = Config::Get(Config::RA_API_TOKEN).empty();
std::string username = Config::Get(Config::RA_USERNAME);
@@ -167,12 +191,19 @@ void AchievementSettingsWidget::LoadSettings()
SignalBlocking(m_common_leaderboards_enabled_input)
->setChecked(Config::Get(Config::RA_LEADERBOARDS_ENABLED));
- SignalBlocking(m_common_leaderboards_enabled_input)->setEnabled(enabled && hardcore_mode_enabled);
+ SignalBlocking(m_common_leaderboards_enabled_input)->setEnabled(enabled && hardcore_enabled);
SignalBlocking(m_common_rich_presence_enabled_input)
->setChecked(Config::Get(Config::RA_RICH_PRESENCE_ENABLED));
SignalBlocking(m_common_rich_presence_enabled_input)->setEnabled(enabled);
+ SignalBlocking(m_common_hardcore_enabled_input)
+ ->setChecked(Config::Get(Config::RA_HARDCORE_ENABLED));
+ SignalBlocking(m_common_hardcore_enabled_input)
+ ->setEnabled(enabled &&
+ (hardcore_enabled ||
+ (Core::GetState() == Core::State::Uninitialized && !Movie::IsPlayingInput())));
+
SignalBlocking(m_common_progress_enabled_input)
->setChecked(Config::Get(Config::RA_PROGRESS_ENABLED));
SignalBlocking(m_common_progress_enabled_input)->setEnabled(enabled && achievements_enabled);
@@ -199,6 +230,8 @@ void AchievementSettingsWidget::SaveSettings()
m_common_leaderboards_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_RICH_PRESENCE_ENABLED,
m_common_rich_presence_enabled_input->isChecked());
+ Config::SetBaseOrCurrent(Config::RA_HARDCORE_ENABLED,
+ m_common_hardcore_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_PROGRESS_ENABLED,
m_common_unofficial_enabled_input->isChecked());
Config::SetBaseOrCurrent(Config::RA_BADGES_ENABLED, m_common_badges_enabled_input->isChecked());
@@ -250,6 +283,20 @@ void AchievementSettingsWidget::ToggleRichPresence()
AchievementManager::GetInstance()->ActivateDeactivateRichPresence();
}
+void AchievementSettingsWidget::ToggleHardcore()
+{
+ SaveSettings();
+ if (Config::Get(Config::RA_HARDCORE_ENABLED))
+ {
+ if (Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f)
+ Config::SetBaseOrCurrent(Config::MAIN_EMULATION_SPEED, 1.0f);
+ Config::SetBaseOrCurrent(Config::FREE_LOOK_ENABLED, false);
+ Settings::Instance().SetCheatsEnabled(false);
+ Settings::Instance().SetDebugModeEnabled(false);
+ }
+ emit Settings::Instance().EmulationStateChanged(Core::GetState());
+}
+
void AchievementSettingsWidget::ToggleProgress()
{
SaveSettings();
diff --git a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.h b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.h
index edf22b7350..eb3f237389 100644
--- a/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.h
+++ b/Source/Core/DolphinQt/Achievements/AchievementSettingsWidget.h
@@ -6,7 +6,6 @@
#ifdef USE_RETRO_ACHIEVEMENTS
#include
-class AchievementsWindow;
class QGroupBox;
class QVBoxLayout;
class QLabel;
@@ -18,7 +17,8 @@ class AchievementSettingsWidget final : public QWidget
{
Q_OBJECT
public:
- explicit AchievementSettingsWidget(QWidget* parent, AchievementsWindow* parent_window);
+ explicit AchievementSettingsWidget(QWidget* parent);
+ void UpdateData();
private:
void OnControllerInterfaceConfigure();
@@ -41,8 +41,6 @@ private:
void ToggleUnofficial();
void ToggleEncore();
- AchievementsWindow* parent_window;
-
QGroupBox* m_common_box;
QVBoxLayout* m_common_layout;
ToolTipCheckBox* m_common_integration_enabled_input;
@@ -56,6 +54,7 @@ private:
ToolTipCheckBox* m_common_achievements_enabled_input;
ToolTipCheckBox* m_common_leaderboards_enabled_input;
ToolTipCheckBox* m_common_rich_presence_enabled_input;
+ ToolTipCheckBox* m_common_hardcore_enabled_input;
ToolTipCheckBox* m_common_progress_enabled_input;
ToolTipCheckBox* m_common_badges_enabled_input;
ToolTipCheckBox* m_common_unofficial_enabled_input;
diff --git a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp
index 4a278c3649..6665fdd871 100644
--- a/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp
+++ b/Source/Core/DolphinQt/Achievements/AchievementsWindow.cpp
@@ -16,6 +16,7 @@
#include "DolphinQt/Achievements/AchievementSettingsWidget.h"
#include "DolphinQt/QtUtils/QueueOnObject.h"
#include "DolphinQt/QtUtils/WrapInScrollArea.h"
+#include "DolphinQt/Settings.h"
AchievementsWindow::AchievementsWindow(QWidget* parent) : QDialog(parent)
{
@@ -26,6 +27,8 @@ AchievementsWindow::AchievementsWindow(QWidget* parent) : QDialog(parent)
ConnectWidgets();
AchievementManager::GetInstance()->SetUpdateCallback(
[this] { QueueOnObject(this, &AchievementsWindow::UpdateData); });
+ connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
+ &AchievementsWindow::UpdateData);
UpdateData();
}
@@ -42,11 +45,10 @@ void AchievementsWindow::CreateMainLayout()
m_header_widget = new AchievementHeaderWidget(this);
m_tab_widget = new QTabWidget();
+ m_settings_widget = new AchievementSettingsWidget(m_tab_widget);
m_progress_widget = new AchievementProgressWidget(m_tab_widget);
m_leaderboard_widget = new AchievementLeaderboardWidget(m_tab_widget);
- m_tab_widget->addTab(
- GetWrappedWidget(new AchievementSettingsWidget(m_tab_widget, this), this, 125, 100),
- tr("Settings"));
+ m_tab_widget->addTab(GetWrappedWidget(m_settings_widget, this, 125, 100), tr("Settings"));
m_tab_widget->addTab(GetWrappedWidget(m_progress_widget, this, 125, 100), tr("Progress"));
m_tab_widget->setTabVisible(1, AchievementManager::GetInstance()->IsGameLoaded());
m_tab_widget->addTab(GetWrappedWidget(m_leaderboard_widget, this, 125, 100), tr("Leaderboards"));
@@ -72,7 +74,7 @@ void AchievementsWindow::UpdateData()
std::lock_guard lg{*AchievementManager::GetInstance()->GetLock()};
m_header_widget->UpdateData();
m_header_widget->setVisible(AchievementManager::GetInstance()->IsLoggedIn());
- // Settings tab handles its own updates ... indeed, that calls this
+ m_settings_widget->UpdateData();
m_progress_widget->UpdateData();
m_tab_widget->setTabVisible(1, AchievementManager::GetInstance()->IsGameLoaded());
m_leaderboard_widget->UpdateData();
diff --git a/Source/Core/DolphinQt/Achievements/AchievementsWindow.h b/Source/Core/DolphinQt/Achievements/AchievementsWindow.h
index 381a0aafb5..4559159a64 100644
--- a/Source/Core/DolphinQt/Achievements/AchievementsWindow.h
+++ b/Source/Core/DolphinQt/Achievements/AchievementsWindow.h
@@ -11,6 +11,7 @@
class AchievementHeaderWidget;
class AchievementLeaderboardWidget;
+class AchievementSettingsWidget;
class AchievementProgressWidget;
class QDialogButtonBox;
class QTabWidget;
@@ -31,6 +32,7 @@ private:
AchievementHeaderWidget* m_header_widget;
QTabWidget* m_tab_widget;
+ AchievementSettingsWidget* m_settings_widget;
AchievementProgressWidget* m_progress_widget;
AchievementLeaderboardWidget* m_leaderboard_widget;
QDialogButtonBox* m_button_box;