mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-02-18 11:55:38 +00:00
Merge pull request #2243 from CookiePLMonster/unofficial-achievements
Add an "Unofficial Test Mode" to allow unlocking non-core achievements
This commit is contained in:
commit
0ba405ef2d
|
@ -18,6 +18,8 @@ AchievementSettingsWidget::AchievementSettingsWidget(QtHostInterface* host_inter
|
||||||
|
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.richPresence, "Cheevos", "RichPresence", true);
|
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.richPresence, "Cheevos", "RichPresence", true);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.testMode, "Cheevos", "TestMode", false);
|
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.testMode, "Cheevos", "TestMode", false);
|
||||||
|
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.unofficialTestMode, "Cheevos",
|
||||||
|
"UnofficialTestMode", false);
|
||||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.useFirstDiscFromPlaylist, "Cheevos",
|
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.useFirstDiscFromPlaylist, "Cheevos",
|
||||||
"UseFirstDiscFromPlaylist", true);
|
"UseFirstDiscFromPlaylist", true);
|
||||||
m_ui.enable->setChecked(m_host_interface->GetBoolSettingValue("Cheevos", "Enabled", false));
|
m_ui.enable->setChecked(m_host_interface->GetBoolSettingValue("Cheevos", "Enabled", false));
|
||||||
|
@ -28,6 +30,10 @@ AchievementSettingsWidget::AchievementSettingsWidget(QtHostInterface* host_inter
|
||||||
dialog->registerWidgetHelp(m_ui.testMode, tr("Enable Test Mode"), tr("Unchecked"),
|
dialog->registerWidgetHelp(m_ui.testMode, tr("Enable Test Mode"), tr("Unchecked"),
|
||||||
tr("When enabled, DuckStation will assume all achievements are locked and not send any "
|
tr("When enabled, DuckStation will assume all achievements are locked and not send any "
|
||||||
"unlock notifications to the server."));
|
"unlock notifications to the server."));
|
||||||
|
dialog->registerWidgetHelp(
|
||||||
|
m_ui.unofficialTestMode, tr("Test Unofficial Achievements"), tr("Unchecked"),
|
||||||
|
tr("When enabled, DuckStation will list achievements from unofficial sets. Please note that these achievements are "
|
||||||
|
"not tracked by RetroAchievements, so they unlock every time."));
|
||||||
dialog->registerWidgetHelp(
|
dialog->registerWidgetHelp(
|
||||||
m_ui.richPresence, tr("Enable Rich Presence"), tr("Unchecked"),
|
m_ui.richPresence, tr("Enable Rich Presence"), tr("Unchecked"),
|
||||||
tr("When enabled, rich presence information will be collected and sent to the server where supported."));
|
tr("When enabled, rich presence information will be collected and sent to the server where supported."));
|
||||||
|
|
|
@ -67,6 +67,13 @@
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QCheckBox" name="unofficialTestMode">
|
||||||
|
<property name="text">
|
||||||
|
<string>Test Unofficial Achievements</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|
|
@ -55,6 +55,7 @@ u32 g_game_id = 0;
|
||||||
|
|
||||||
static bool s_logged_in = false;
|
static bool s_logged_in = false;
|
||||||
static bool s_test_mode = false;
|
static bool s_test_mode = false;
|
||||||
|
static bool s_unofficial_test_mode = false;
|
||||||
static bool s_use_first_disc_from_playlist = true;
|
static bool s_use_first_disc_from_playlist = true;
|
||||||
static bool s_rich_presence_enabled = false;
|
static bool s_rich_presence_enabled = false;
|
||||||
|
|
||||||
|
@ -212,7 +213,8 @@ static std::string GetUserAgent()
|
||||||
return StringUtil::StdStringFromFormat("DuckStation for %s (%s) %s", SYSTEM_STR, CPU_ARCH_STR, g_scm_tag_str);
|
return StringUtil::StdStringFromFormat("DuckStation for %s (%s) %s", SYSTEM_STR, CPU_ARCH_STR, g_scm_tag_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Initialize(bool test_mode, bool use_first_disc_from_playlist, bool enable_rich_presence, bool challenge_mode)
|
bool Initialize(bool test_mode, bool use_first_disc_from_playlist, bool enable_rich_presence, bool challenge_mode,
|
||||||
|
bool include_unofficial)
|
||||||
{
|
{
|
||||||
s_http_downloader = FrontendCommon::HTTPDownloader::Create(GetUserAgent().c_str());
|
s_http_downloader = FrontendCommon::HTTPDownloader::Create(GetUserAgent().c_str());
|
||||||
if (!s_http_downloader)
|
if (!s_http_downloader)
|
||||||
|
@ -224,6 +226,7 @@ bool Initialize(bool test_mode, bool use_first_disc_from_playlist, bool enable_r
|
||||||
g_active = true;
|
g_active = true;
|
||||||
g_challenge_mode = challenge_mode;
|
g_challenge_mode = challenge_mode;
|
||||||
s_test_mode = test_mode;
|
s_test_mode = test_mode;
|
||||||
|
s_unofficial_test_mode = include_unofficial;
|
||||||
s_use_first_disc_from_playlist = use_first_disc_from_playlist;
|
s_use_first_disc_from_playlist = use_first_disc_from_playlist;
|
||||||
s_rich_presence_enabled = enable_rich_presence;
|
s_rich_presence_enabled = enable_rich_presence;
|
||||||
rc_runtime_init(&s_rcheevos_runtime);
|
rc_runtime_init(&s_rcheevos_runtime);
|
||||||
|
@ -298,6 +301,11 @@ bool IsTestModeActive()
|
||||||
return s_test_mode;
|
return s_test_mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsUnofficialTestModeActive()
|
||||||
|
{
|
||||||
|
return s_unofficial_test_mode;
|
||||||
|
}
|
||||||
|
|
||||||
bool IsUsingFirstDiscFromPlaylist()
|
bool IsUsingFirstDiscFromPlaylist()
|
||||||
{
|
{
|
||||||
return s_use_first_disc_from_playlist;
|
return s_use_first_disc_from_playlist;
|
||||||
|
@ -672,16 +680,16 @@ static void GetPatchesCallback(s32 status_code, const FrontendCommon::HTTPDownlo
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 id = achievement["ID"].GetUint();
|
const u32 id = achievement["ID"].GetUint();
|
||||||
const u32 category = achievement["Flags"].GetUint();
|
const AchievementCategory category = static_cast<AchievementCategory>(achievement["Flags"].GetUint());
|
||||||
const char* memaddr = achievement["MemAddr"].GetString();
|
const char* memaddr = achievement["MemAddr"].GetString();
|
||||||
std::string title = achievement["Title"].GetString();
|
std::string title = achievement["Title"].GetString();
|
||||||
std::string description = GetOptionalString(achievement, "Description");
|
std::string description = GetOptionalString(achievement, "Description");
|
||||||
std::string badge_name = GetOptionalString(achievement, "BadgeName");
|
std::string badge_name = GetOptionalString(achievement, "BadgeName");
|
||||||
const u32 points = GetOptionalUInt(achievement, "Points");
|
const u32 points = GetOptionalUInt(achievement, "Points");
|
||||||
|
|
||||||
// Skip local and unofficial achievements for now.
|
// Skip local and unofficial achievements for now, unless "Test Unofficial Achievements" is enabled
|
||||||
if (static_cast<AchievementCategory>(category) == AchievementCategory::Local ||
|
if (!s_unofficial_test_mode &&
|
||||||
static_cast<AchievementCategory>(category) == AchievementCategory::Unofficial)
|
(category == AchievementCategory::Local || category == AchievementCategory::Unofficial))
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("Skipping unofficial achievement %u (%s)", id, title.c_str());
|
Log_WarningPrintf("Skipping unofficial achievement %u (%s)", id, title.c_str());
|
||||||
continue;
|
continue;
|
||||||
|
@ -701,6 +709,7 @@ static void GetPatchesCallback(s32 status_code, const FrontendCommon::HTTPDownlo
|
||||||
cheevo.locked = true;
|
cheevo.locked = true;
|
||||||
cheevo.active = false;
|
cheevo.active = false;
|
||||||
cheevo.points = points;
|
cheevo.points = points;
|
||||||
|
cheevo.category = category;
|
||||||
|
|
||||||
if (!badge_name.empty())
|
if (!badge_name.empty())
|
||||||
{
|
{
|
||||||
|
@ -1101,6 +1110,13 @@ void UnlockAchievement(u32 achievement_id, bool add_notification /* = true*/)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (achievement->category != AchievementCategory::Core)
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Skipping sending achievement %u unlock to server because it's not from the core set.",
|
||||||
|
achievement_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char url[512];
|
char url[512];
|
||||||
rc_url_award_cheevo(url, sizeof(url), s_username.c_str(), s_login_token.c_str(), achievement_id,
|
rc_url_award_cheevo(url, sizeof(url), s_username.c_str(), s_login_token.c_str(), achievement_id,
|
||||||
static_cast<int>(g_challenge_mode), s_game_hash.c_str());
|
static_cast<int>(g_challenge_mode), s_game_hash.c_str());
|
||||||
|
|
|
@ -23,6 +23,7 @@ struct Achievement
|
||||||
std::string locked_badge_path;
|
std::string locked_badge_path;
|
||||||
std::string unlocked_badge_path;
|
std::string unlocked_badge_path;
|
||||||
u32 points;
|
u32 points;
|
||||||
|
AchievementCategory category;
|
||||||
bool locked;
|
bool locked;
|
||||||
bool active;
|
bool active;
|
||||||
};
|
};
|
||||||
|
@ -56,13 +57,15 @@ ALWAYS_INLINE u32 GetGameID()
|
||||||
return g_game_id;
|
return g_game_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Initialize(bool test_mode, bool use_first_disc_from_playlist, bool enable_rich_presence, bool challenge_mode);
|
bool Initialize(bool test_mode, bool use_first_disc_from_playlist, bool enable_rich_presence, bool challenge_mode,
|
||||||
|
bool include_unofficial);
|
||||||
void Reset();
|
void Reset();
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
void Update();
|
void Update();
|
||||||
|
|
||||||
bool IsLoggedIn();
|
bool IsLoggedIn();
|
||||||
bool IsTestModeActive();
|
bool IsTestModeActive();
|
||||||
|
bool IsUnofficialTestModeActive();
|
||||||
bool IsUsingFirstDiscFromPlaylist();
|
bool IsUsingFirstDiscFromPlaylist();
|
||||||
bool IsRichPresenceEnabled();
|
bool IsRichPresenceEnabled();
|
||||||
const std::string& GetUsername();
|
const std::string& GetUsername();
|
||||||
|
|
|
@ -2807,6 +2807,7 @@ void CommonHostInterface::SetDefaultSettings(SettingsInterface& si)
|
||||||
#ifdef WITH_CHEEVOS
|
#ifdef WITH_CHEEVOS
|
||||||
si.SetBoolValue("Cheevos", "Enabled", false);
|
si.SetBoolValue("Cheevos", "Enabled", false);
|
||||||
si.SetBoolValue("Cheevos", "TestMode", false);
|
si.SetBoolValue("Cheevos", "TestMode", false);
|
||||||
|
si.SetBoolValue("Cheevos", "UnofficialTestMode", false);
|
||||||
si.SetBoolValue("Cheevos", "UseFirstDiscFromPlaylist", true);
|
si.SetBoolValue("Cheevos", "UseFirstDiscFromPlaylist", true);
|
||||||
si.DeleteValue("Cheevos", "Username");
|
si.DeleteValue("Cheevos", "Username");
|
||||||
si.DeleteValue("Cheevos", "Token");
|
si.DeleteValue("Cheevos", "Token");
|
||||||
|
@ -3818,11 +3819,13 @@ void CommonHostInterface::UpdateCheevosActive()
|
||||||
{
|
{
|
||||||
const bool cheevos_enabled = GetBoolSettingValue("Cheevos", "Enabled", false);
|
const bool cheevos_enabled = GetBoolSettingValue("Cheevos", "Enabled", false);
|
||||||
const bool cheevos_test_mode = GetBoolSettingValue("Cheevos", "TestMode", false);
|
const bool cheevos_test_mode = GetBoolSettingValue("Cheevos", "TestMode", false);
|
||||||
|
const bool cheevos_unofficial_test_mode = GetBoolSettingValue("Cheevos", "UnofficialTestMode", false);
|
||||||
const bool cheevos_use_first_disc_from_playlist = GetBoolSettingValue("Cheevos", "UseFirstDiscFromPlaylist", true);
|
const bool cheevos_use_first_disc_from_playlist = GetBoolSettingValue("Cheevos", "UseFirstDiscFromPlaylist", true);
|
||||||
const bool cheevos_rich_presence = GetBoolSettingValue("Cheevos", "RichPresence", true);
|
const bool cheevos_rich_presence = GetBoolSettingValue("Cheevos", "RichPresence", true);
|
||||||
const bool cheevos_hardcore = GetBoolSettingValue("Cheevos", "ChallengeMode", false);
|
const bool cheevos_hardcore = GetBoolSettingValue("Cheevos", "ChallengeMode", false);
|
||||||
|
|
||||||
if (cheevos_enabled != Cheevos::IsActive() || cheevos_test_mode != Cheevos::IsTestModeActive() ||
|
if (cheevos_enabled != Cheevos::IsActive() || cheevos_test_mode != Cheevos::IsTestModeActive() ||
|
||||||
|
cheevos_unofficial_test_mode != Cheevos::IsUnofficialTestModeActive() ||
|
||||||
cheevos_use_first_disc_from_playlist != Cheevos::IsUsingFirstDiscFromPlaylist() ||
|
cheevos_use_first_disc_from_playlist != Cheevos::IsUsingFirstDiscFromPlaylist() ||
|
||||||
cheevos_rich_presence != Cheevos::IsRichPresenceEnabled() ||
|
cheevos_rich_presence != Cheevos::IsRichPresenceEnabled() ||
|
||||||
cheevos_hardcore != Cheevos::IsChallengeModeEnabled())
|
cheevos_hardcore != Cheevos::IsChallengeModeEnabled())
|
||||||
|
@ -3831,7 +3834,7 @@ void CommonHostInterface::UpdateCheevosActive()
|
||||||
if (cheevos_enabled)
|
if (cheevos_enabled)
|
||||||
{
|
{
|
||||||
if (!Cheevos::Initialize(cheevos_test_mode, cheevos_use_first_disc_from_playlist, cheevos_rich_presence,
|
if (!Cheevos::Initialize(cheevos_test_mode, cheevos_use_first_disc_from_playlist, cheevos_rich_presence,
|
||||||
cheevos_hardcore))
|
cheevos_hardcore, cheevos_unofficial_test_mode))
|
||||||
ReportError("Failed to initialize cheevos after settings change.");
|
ReportError("Failed to initialize cheevos after settings change.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2281,6 +2281,11 @@ void DrawSettingsWindow()
|
||||||
"When enabled, DuckStation will assume all achievements are locked and not "
|
"When enabled, DuckStation will assume all achievements are locked and not "
|
||||||
"send any unlock notifications to the server.",
|
"send any unlock notifications to the server.",
|
||||||
"Cheevos", "TestMode", false);
|
"Cheevos", "TestMode", false);
|
||||||
|
settings_changed |=
|
||||||
|
ToggleButtonForNonSetting(ICON_FA_MEDAL " Test Unofficial Achievements",
|
||||||
|
"When enabled, DuckStation will list achievements from unofficial sets. These "
|
||||||
|
"achievements are not tracked by RetroAchievements.",
|
||||||
|
"Cheevos", "UnofficialTestMode", false);
|
||||||
settings_changed |= ToggleButtonForNonSetting(ICON_FA_COMPACT_DISC " Use First Disc From Playlist",
|
settings_changed |= ToggleButtonForNonSetting(ICON_FA_COMPACT_DISC " Use First Disc From Playlist",
|
||||||
"When enabled, the first disc in a playlist will be used for "
|
"When enabled, the first disc in a playlist will be used for "
|
||||||
"achievements, regardless of which disc is active.",
|
"achievements, regardless of which disc is active.",
|
||||||
|
|
Loading…
Reference in a new issue