From f8d80221cc58f0d576c50a21e539d01d2853fdd0 Mon Sep 17 00:00:00 2001 From: ssyn02 Date: Fri, 19 Jun 2026 01:36:07 -0300 Subject: [PATCH 1/5] added menu tab, empty skeleton --- soh/soh/SohGui/SohMenu.cpp | 3 ++- soh/soh/SohGui/SohMenu.h | 1 + soh/soh/SohGui/SohMenuAchievements.cpp | 31 ++++++++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 soh/soh/SohGui/SohMenuAchievements.cpp diff --git a/soh/soh/SohGui/SohMenu.cpp b/soh/soh/SohGui/SohMenu.cpp index ff793deb247..b63704c7af0 100644 --- a/soh/soh/SohGui/SohMenu.cpp +++ b/soh/soh/SohGui/SohMenu.cpp @@ -90,7 +90,8 @@ void SohMenu::AddMenuElements() { AddMenuRandomizer(); AddMenuNetwork(); AddMenuDevTools(); - + AddMenuAchievements(); + if (CVarGetInteger(CVAR_SETTING("Menu.SidebarSearch"), 0)) { InsertSidebarSearch(); } diff --git a/soh/soh/SohGui/SohMenu.h b/soh/soh/SohGui/SohMenu.h index c50c4367409..5d5a38322d2 100644 --- a/soh/soh/SohGui/SohMenu.h +++ b/soh/soh/SohGui/SohMenu.h @@ -47,6 +47,7 @@ class SohMenu : public Ship::Menu { void AddMenuDevTools(); void AddMenuRandomizer(); void AddMenuNetwork(); + void AddMenuAchievements(); static void UpdateLanguageMap(std::map& languageMap); private: diff --git a/soh/soh/SohGui/SohMenuAchievements.cpp b/soh/soh/SohGui/SohMenuAchievements.cpp new file mode 100644 index 00000000000..c4a881f8721 --- /dev/null +++ b/soh/soh/SohGui/SohMenuAchievements.cpp @@ -0,0 +1,31 @@ +#include "SohMenu.h" +#include "soh/OTRGlobals.h" + +extern "C" { +#include "variables.h" +} + +namespace SohGui { + +extern std::shared_ptr mSohMenu; +using namespace UIWidgets; + +void SohMenu::AddMenuAchievements() { + // Add Achievements section + AddMenuEntry("Achievements", CVAR_SETTING("Menu.AchievementsSidebarSection")); + WidgetPath path = {"Achievements", "Test 1", SECTION_COLUMN_1}; + AddSidebarEntry("Achievements", path.sidebarName, 2); + + //Test 1 + AddWidget(path, "Obtained Achievements", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Test", WIDGET_TEXT); + AddWidget(path, "Locked Achievements", WIDGET_SEPARATOR_TEXT); + AddWidget(path, "Test", WIDGET_TEXT); + + //Test 2 + path.sidebarName = "Test 2"; + AddSidebarEntry("Achievements", path.sidebarName, 2); + AddWidget(path, "Test", WIDGET_TEXT); +} // namespace SohGui + +} \ No newline at end of file From 952a4144409b594c748c10b6bfcb3588392c56ed Mon Sep 17 00:00:00 2001 From: ssyn02 Date: Fri, 19 Jun 2026 16:19:39 -0300 Subject: [PATCH 2/5] first working prototype -achievements for every major boss death -achievements persist across savefiles -achievement notifications are displayed on screen todo: -better notifications -tracking UI -more achievements --- soh/include/z64save.h | 5 ++ soh/soh/Enhancements/achievements.cpp | 75 +++++++++++++++++++ soh/soh/Enhancements/achievements.h | 26 +++++++ soh/soh/SaveManager.cpp | 2 + soh/soh/SaveManager.h | 1 + .../actors/ovl_Boss_Dodongo/z_boss_dodongo.c | 7 ++ .../overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c | 7 ++ .../actors/ovl_Boss_Ganon/z_boss_ganon.c | 7 ++ .../actors/ovl_Boss_Ganon2/z_boss_ganon2.c | 7 ++ .../ovl_Boss_Ganondrof/z_boss_ganondrof.c | 7 ++ .../actors/ovl_Boss_Goma/z_boss_goma.c | 7 ++ .../overlays/actors/ovl_Boss_Mo/z_boss_mo.c | 7 ++ .../overlays/actors/ovl_Boss_Sst/z_boss_sst.c | 7 ++ .../overlays/actors/ovl_Boss_Tw/z_boss_tw.c | 7 ++ .../overlays/actors/ovl_Boss_Va/z_boss_va.c | 7 ++ 15 files changed, 179 insertions(+) create mode 100644 soh/soh/Enhancements/achievements.cpp create mode 100644 soh/soh/Enhancements/achievements.h diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 35f30c26398..3743629defa 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -222,6 +222,10 @@ typedef struct ShipQuestSaveContextData { ShipQuestSpecificSaveContextData data; } ShipQuestSaveContextData; +typedef struct ShipAchievementSaveContextData { + u16 achievementFlags; +} ShipAchievementSaveContextData; + typedef struct ShipSaveContextData { u16 pendingSale; u16 pendingSaleMod; @@ -229,6 +233,7 @@ typedef struct ShipSaveContextData { SohStats stats; FaroresWindData backupFW; ShipQuestSaveContextData quest; + ShipAchievementSaveContextData achievements; u8 maskMemory; u8 filenameLanguage; //TODO: Move non-rando specific flags to a new sohInf and move the remaining randomizerInf to ShipRandomizerSaveContextData diff --git a/soh/soh/Enhancements/achievements.cpp b/soh/soh/Enhancements/achievements.cpp new file mode 100644 index 00000000000..39845bd8667 --- /dev/null +++ b/soh/soh/Enhancements/achievements.cpp @@ -0,0 +1,75 @@ +#include "soh/Enhancements/achievements.h" +#include "soh/SaveManager.h" +#include "soh/Notification/Notification.h" +#include "soh/ShipInit.hpp" +#include "z64.h" + +extern "C" SaveContext gSaveContext; + +static RegisterShipInitFunc initFunc(Achievements_Init); + +void Achievements_Load(); +void Achievements_Save(SaveContext* saveContext, int sectionID, bool fullSave); +void Achievements_InitDefaults(bool isDebug); +const char* Achievements_GetName(AchievementId id); + +void Achievements_Init() { + SaveManager::Instance->AddLoadFunction("achievements", 1, Achievements_Load); + SaveManager::Instance->AddSaveFunction("achievements", 1, Achievements_Save, true, SECTION_PARENT_NONE); + SaveManager::Instance->AddInitFunction(Achievements_InitDefaults); +} + +void Achievements_InitDefaults(bool isDebug) { + gSaveContext.ship.achievements.achievementFlags = 0; +} + +void Achievements_Load() { + SaveManager::Instance->LoadData("achievementFlags", gSaveContext.ship.achievements.achievementFlags); +} + +void Achievements_Save(SaveContext* saveContext, int sectionID, bool fullSave) { + SaveManager::Instance->SaveData("achievementFlags", saveContext->ship.achievements.achievementFlags); +} + +extern "C" bool Achievements_IsUnlocked(AchievementId id) { + return (gSaveContext.ship.achievements.achievementFlags & (1ULL << id)) != 0; +} + +extern "C" void Achievements_TryUnlock(AchievementId id) { + if (!Achievements_IsUnlocked(id)) { + gSaveContext.ship.achievements.achievementFlags |= (1ULL << id); + Notification::Emit({ + .itemIcon = "__OTR__textures/icon_item_24_static/gQuestIconGoldSkulltulaTex", + .prefix = "", + .message = Achievements_GetName(id), + .suffix = "", + }); + } +} + +const char* Achievements_GetName(AchievementId id) { + switch (id) { + case ACHIEVEMENT_DEFEAT_GOHMA: + return "Defeat Gohma"; + case ACHIEVEMENT_DEFEAT_KD: + return "Defeat King Dodongo"; + case ACHIEVEMENT_DEFEAT_BARINADE: + return "Defeat Barinade"; + case ACHIEVEMENT_DEFEAT_PG: + return "Defeat Phantom Ganon"; + case ACHIEVEMENT_DEFEAT_VOLVAGIA: + return "Defeat Volvagia"; + case ACHIEVEMENT_DEFEAT_MORPHA: + return "Defeat Morpha"; + case ACHIEVEMENT_DEFEAT_BONGO: + return "Defeat Bongo Bongo"; + case ACHIEVEMENT_DEFEAT_TWINROVA: + return "Defeat Twinrova"; + case ACHIEVEMENT_DEFEAT_GANONDORF: + return "Defeat Ganondorf"; + case ACHIEVEMENT_DEFEAT_GANON: + return "Defeat Ganon"; + default: + return "Unknown Achievement"; + } +} \ No newline at end of file diff --git a/soh/soh/Enhancements/achievements.h b/soh/soh/Enhancements/achievements.h new file mode 100644 index 00000000000..c0a7db25812 --- /dev/null +++ b/soh/soh/Enhancements/achievements.h @@ -0,0 +1,26 @@ +#pragma once + +typedef enum { + ACHIEVEMENT_DEFEAT_GOHMA = 0, + ACHIEVEMENT_DEFEAT_KD = 1, + ACHIEVEMENT_DEFEAT_BARINADE = 2, + ACHIEVEMENT_DEFEAT_PG = 3, + ACHIEVEMENT_DEFEAT_VOLVAGIA = 4, + ACHIEVEMENT_DEFEAT_MORPHA = 5, + ACHIEVEMENT_DEFEAT_BONGO = 6, + ACHIEVEMENT_DEFEAT_TWINROVA = 7, + ACHIEVEMENT_DEFEAT_GANONDORF = 8, + ACHIEVEMENT_DEFEAT_GANON = 9, +} AchievementId; + +#ifdef __cplusplus +extern "C" { +#endif + +void Achievements_Init(); +bool Achievements_IsUnlocked(AchievementId id); +void Achievements_TryUnlock(AchievementId id); + +#ifdef __cplusplus +} +#endif diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 67e250a58c3..15c93408328 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -593,6 +593,8 @@ void SaveManager::StartupCheckAndInitMeta(int fileNum) { SohUtils::CopyStringToCharArray(fileMetaInfo[fileNum].buildVersion, metaSaveBlock["sections"]["sohStats"]["data"]["buildVersion"], ARRAY_COUNT(fileMetaInfo[fileNum].buildVersion)); + + fileMetaInfo[fileNum].achievementFlags = 0; } void SaveManager::InitMeta(int fileNum) { diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index 80f58b915e5..e297fcd1aea 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -20,6 +20,7 @@ typedef struct { s16 buildVersionMajor; s16 buildVersionMinor; s16 buildVersionPatch; + u16 achievementFlags; u8 inventoryItems[24]; u16 equipment; diff --git a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c index 16391b36f17..c3848b55d35 100644 --- a/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c +++ b/soh/src/overlays/actors/ovl_Boss_Dodongo/z_boss_dodongo.c @@ -7,6 +7,7 @@ #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" +#include "soh/Enhancements/achievements.h" #include // malloc #include // memcpy @@ -23,6 +24,7 @@ void BossDodongo_Init(Actor* thisx, PlayState* play); void BossDodongo_Destroy(Actor* thisx, PlayState* play); void BossDodongo_Update(Actor* thisx, PlayState* play); void BossDodongo_Draw(Actor* thisx, PlayState* play); +void BossDodongo_TryUnlockDeathAchievement(); void BossDodongo_SetupIntroCutscene(BossDodongo* this, PlayState* play); void BossDodongo_IntroCutscene(BossDodongo* this, PlayState* play); @@ -1481,6 +1483,7 @@ void BossDodongo_UpdateDamage(BossDodongo* this, PlayState* play) { s16 i; if ((this->health <= 0) && (this->actionFunc != BossDodongo_DeathCutscene)) { + BossDodongo_TryUnlockDeathAchievement(); BossDodongo_SetupDeathCutscene(this); Enemy_StartFinishingBlow(play, &this->actor); return; @@ -1958,3 +1961,7 @@ void BossDodongo_DrawEffects(PlayState* play) { CLOSE_DISPS(gfxCtx); } + +void BossDodongo_TryUnlockDeathAchievement() { + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_KD); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c b/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c index 1a00b983b70..5fd8d18fe4e 100644 --- a/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c +++ b/soh/src/overlays/actors/ovl_Boss_Fd2/z_boss_fd2.c @@ -11,6 +11,7 @@ #include "vt.h" #include "soh/frame_interpolation.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #define FLAGS \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ @@ -49,6 +50,7 @@ void BossFd2_Vulnerable(BossFd2* this, PlayState* play); void BossFd2_Damaged(BossFd2* this, PlayState* play); void BossFd2_Death(BossFd2* this, PlayState* play); void BossFd2_Wait(BossFd2* this, PlayState* play); +void BossFd2_TryUnlockDeathAchievement(); const ActorInit Boss_Fd2_InitVars = { ACTOR_BOSS_FD2, @@ -892,6 +894,7 @@ void BossFd2_CollisionCheck(BossFd2* this, PlayState* play) { if ((s8)bossFd->actor.colChkInfo.health <= 0) { bossFd->actor.colChkInfo.health = 0; + BossFd2_TryUnlockDeathAchievement(); BossFd2_SetupDeath(this, play); this->work[FD2_DAMAGE_FLASH_TIMER] = 10; this->work[FD2_INVINC_TIMER] = 30000; @@ -1227,3 +1230,7 @@ void BossFd2_Draw(Actor* thisx, PlayState* play) { } CLOSE_DISPS(play->state.gfxCtx); } + +void BossFd2_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_VOLVAGIA); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c index 4aa8984a2b4..676528bc9ef 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon/z_boss_ganon.c @@ -13,6 +13,7 @@ #include "soh/frame_interpolation.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #include @@ -31,6 +32,7 @@ void func_808E229C(Actor* thisx, PlayState* play); // draw void func_808E324C(Actor* thisx, PlayState* play); // draw void BossGanon_LightBall_Draw(Actor* thisx, PlayState* play); void BossGanon_Reset(void); +void BossGanon_TryUnlockDeathAchievement(); void BossGanon_SetupIntroCutscene(BossGanon* this, PlayState* play); void BossGanon_SetupTowerCutscene(BossGanon* this, PlayState* play); @@ -2801,6 +2803,7 @@ void BossGanon_UpdateDamage(BossGanon* this, PlayState* play) { } if ((s8)this->actor.colChkInfo.health <= 0) { + BossGanon_TryUnlockDeathAchievement(); BossGanon_SetupDeathCutscene(this, play); Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_DEAD); Audio_PlayActorSound2(&this->actor, NA_SE_EN_GANON_DD_THUNDER); @@ -5102,3 +5105,7 @@ void BossGanon_Reset(void) { sBossGanonCape = NULL; memset(sBossGanonEffectBuf, 0, sizeof(sBossGanonEffectBuf)); } + +void BossGanon_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_GANONDORF); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index 21a849cfaa3..430dfd71a59 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -10,6 +10,7 @@ #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #include @@ -22,6 +23,7 @@ void BossGanon2_Destroy(Actor* thisx, PlayState* play); void BossGanon2_Update(Actor* thisx, PlayState* play); void BossGanon2_Draw(Actor* thisx, PlayState* play); void BossGanon2_Reset(void); +void BossGanon2_TryUnlockDeathAchievement(); void func_808FD5C4(BossGanon2* this, PlayState* play); void func_808FD5F4(BossGanon2* this, PlayState* play); @@ -1962,6 +1964,7 @@ void BossGanon2_CollisionCheck(BossGanon2* this, PlayState* play) { this->actor.colChkInfo.health -= 2; temp_v0_4 = this->actor.colChkInfo.health; if (temp_v0_4 < 0x15 && this->unk_334 == 0) { + BossGanon2_TryUnlockDeathAchievement(); func_80900818(this, play); } else { if (temp_v0_4 <= 0) { @@ -3156,3 +3159,7 @@ void BossGanon2_Reset(void) { memset(D_80910608, 0, sizeof(D_80910608)); memset(sBossGanon2Particles, 0, sizeof(sBossGanon2Particles)); } + +void BossGanon2_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_GANON); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c index 984da2d915f..a3908862a32 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c @@ -13,6 +13,7 @@ #include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #define FLAGS \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ @@ -56,6 +57,7 @@ void BossGanondrof_SetupCharge(BossGanondrof* this, PlayState* play); void BossGanondrof_Charge(BossGanondrof* this, PlayState* play); void BossGanondrof_Stunned(BossGanondrof* this, PlayState* play); void BossGanondrof_Death(BossGanondrof* this, PlayState* play); +void BossGanondrof_TryUnlockDeathAchievement(); const ActorInit Boss_Ganondrof_InitVars = { ACTOR_BOSS_GANONDROF, @@ -1224,6 +1226,7 @@ void BossGanondrof_CollisionCheck(BossGanondrof* this, PlayState* play) { } if ((s8)this->actor.colChkInfo.health <= 0) { + BossGanondrof_TryUnlockDeathAchievement(); BossGanondrof_SetupDeath(this, play); Enemy_StartFinishingBlow(play, &this->actor); GameInteractor_ExecuteOnBossDefeat(&this->actor); @@ -1493,3 +1496,7 @@ void BossGanondrof_Draw(Actor* thisx, PlayState* play) { CLOSE_DISPS(play->state.gfxCtx); osSyncPrintf("DRAW END %d\n", this->actor.params); } + +void BossGanondrof_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_PG); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c index 3920cca5e47..ad9e4a8c638 100644 --- a/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c +++ b/soh/src/overlays/actors/ovl_Boss_Goma/z_boss_goma.c @@ -7,6 +7,7 @@ #include "soh/OTRGlobals.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #define FLAGS \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ @@ -54,6 +55,7 @@ void BossGoma_FloorMain(BossGoma* this, PlayState* play); void BossGoma_WallClimb(BossGoma* this, PlayState* play); void BossGoma_CeilingMoveToCenter(BossGoma* this, PlayState* play); void BossGoma_SpawnChildGohma(BossGoma* this, PlayState* play, s16 i); +void BossGoma_TryUnlockDeathAchievement(); const ActorInit Boss_Goma_InitVars = { ACTOR_BOSS_GOMA, @@ -410,6 +412,7 @@ void BossGoma_SetupDefeated(BossGoma* this, PlayState* play) { this->actor.shape.shadowScale = 0.0f; Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x100FF); Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_DEAD); + BossGoma_TryUnlockDeathAchievement(); } /** @@ -2190,3 +2193,7 @@ void BossGoma_SpawnChildGohma(BossGoma* this, PlayState* play, s16 i) { this->childrenGohmaState[i] = 1; } + +void BossGoma_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_GOHMA); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c index a13eb154774..d755cb78b11 100644 --- a/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c +++ b/soh/src/overlays/actors/ovl_Boss_Mo/z_boss_mo.c @@ -14,6 +14,7 @@ #include "soh/frame_interpolation.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #include @@ -69,6 +70,7 @@ void BossMo_SetupTentacle(BossMo* this, PlayState* play); void BossMo_Tentacle(BossMo* this, PlayState* play); void BossMo_Unknown(void); +void BossMo_TryUnlockDeathAchievement(); typedef enum { /* 0 */ MO_FX_NONE, @@ -1801,6 +1803,7 @@ void BossMo_CoreCollisionCheck(BossMo* this, PlayState* play) { if ((s8)this->actor.colChkInfo.health <= 0) { if (((sMorphaTent1->csCamera == 0) && (sMorphaTent2 == NULL)) || ((sMorphaTent1->csCamera == 0) && (sMorphaTent2 != NULL) && (sMorphaTent2->csCamera == 0))) { + BossMo_TryUnlockDeathAchievement(); Enemy_StartFinishingBlow(play, &this->actor); GameInteractor_ExecuteOnBossDefeat(&this->actor); Audio_QueueSeqCmd(0x1 << 28 | SEQ_PLAYER_BGM_MAIN << 24 | 0x100FF); @@ -3623,3 +3626,7 @@ void BossMo_Reset(void) { sBossGanonSeed2 = 0; sBossGanonSeed3 = 0; } + +void BossMo_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_MORPHA); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c index aa68a5866b1..341e609db36 100644 --- a/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c +++ b/soh/src/overlays/actors/ovl_Boss_Sst/z_boss_sst.c @@ -14,6 +14,7 @@ #include "soh/ResourceManagerHelpers.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #define FLAGS \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ @@ -62,6 +63,7 @@ void BossSst_DrawHead(Actor* thisx, PlayState* play); void BossSst_UpdateEffect(Actor* thisx, PlayState* play); void BossSst_DrawEffect(Actor* thisx, PlayState* play); void BossSst_Reset(void); +void BossSst_TryUnlockDeathAchievement(); void BossSst_HeadSfx(BossSst* this, u16 sfxId); @@ -2572,6 +2574,7 @@ void BossSst_HeadCollisionCheck(BossSst* this, PlayState* play) { if ((this->actor.colChkInfo.damageEffect != 0) || (this->actor.colChkInfo.damage != 0)) { if (this->actionFunc == BossSst_HeadVulnerable) { if (Actor_ApplyDamage(&this->actor) == 0) { + BossSst_TryUnlockDeathAchievement(); Enemy_StartFinishingBlow(play, &this->actor); BossSst_HeadSetupDeath(this, play); GameInteractor_ExecuteOnBossDefeat(&this->actor); @@ -3302,3 +3305,7 @@ void BossSst_Reset(void) { sStaticColor.g = 0; sStaticColor.b = 0; } + +void BossSst_TryUnlockDeathAchievement() { + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_BONGO); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c index 3f83322c44d..145693cbd5b 100644 --- a/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c +++ b/soh/src/overlays/actors/ovl_Boss_Tw/z_boss_tw.c @@ -6,6 +6,7 @@ #include "soh/frame_interpolation.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #include @@ -30,6 +31,7 @@ void BossTw_Destroy(Actor* thisx, PlayState* play); void BossTw_Update(Actor* thisx, PlayState* play); void BossTw_Draw(Actor* thisx, PlayState* play); void BossTw_Reset(void); +void BossTw_TryUnlockDeathAchievement(); void BossTw_TwinrovaDamage(BossTw* this, PlayState* play, u8 arg2); void BossTw_TwinrovaSetupFly(BossTw* this, PlayState* play); @@ -5270,6 +5272,7 @@ void BossTw_TwinrovaDamage(BossTw* this, PlayState* play, u8 damage) { } if ((s8)this->actor.colChkInfo.health <= 0) { + BossTw_TryUnlockDeathAchievement(); BossTw_TwinrovaSetupDeathCS(this, play); Enemy_StartFinishingBlow(play, &this->actor); Audio_PlayActorSound2(&this->actor, NA_SE_EN_TWINROBA_YOUNG_DEAD); @@ -5470,3 +5473,7 @@ void BossTw_Reset(void) { sTwInitalized = false; memset(sTwEffects, 0, sizeof(sTwEffects)); } + +void BossTw_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_TWINROVA); +} diff --git a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c index f30f9660407..ecc71615378 100644 --- a/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c +++ b/soh/src/overlays/actors/ovl_Boss_Va/z_boss_va.c @@ -18,6 +18,7 @@ #include "soh/frame_interpolation.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/Enhancements/achievements.h" #define FLAGS \ (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE | ACTOR_FLAG_UPDATE_CULLING_DISABLED | \ @@ -199,6 +200,7 @@ void BossVa_SpawnSparkBall(PlayState* play, BossVaEffect* effect, BossVa* this, void BossVa_SpawnBloodDroplets(PlayState* play, BossVaEffect* effect, Vec3f* pos, s16 scale, s16 phase, s16 yaw); void BossVa_Tumor(PlayState* play, BossVa* this, s32 count, s16 scale, f32 xzSpread, f32 ySpread, u8 mode, f32 range, u8 fixed); +void BossVa_TryUnlockDeathAchievement(); const ActorInit Boss_Va_InitVars = { ACTOR_BOSS_VA, @@ -1406,6 +1408,7 @@ void BossVa_BodyPhase4(BossVa* this, PlayState* play) { sFightPhase++; sPhase4HP += 3; if (sFightPhase >= PHASE_DEATH) { + BossVa_TryUnlockDeathAchievement(); BossVa_SetupBodyDeath(this, play); Enemy_StartFinishingBlow(play, &this->actor); GameInteractor_ExecuteOnBossDefeat(&this->actor); @@ -4051,3 +4054,7 @@ void BossVa_Reset(void) { sBodyBari[i] = 0; } } + +void BossVa_TryUnlockDeathAchievement(){ + Achievements_TryUnlock(ACHIEVEMENT_DEFEAT_BARINADE); +} From fccee687c50ee455c828844f6b1ce44dc0469d64 Mon Sep 17 00:00:00 2001 From: ssyn02 Date: Sat, 20 Jun 2026 23:15:10 -0300 Subject: [PATCH 3/5] fixed UI not updating, corrected Ganon's death event --- soh/include/z64save.h | 2 +- soh/soh/Enhancements/achievements.cpp | 61 ++++++++++--------- soh/soh/Enhancements/achievements.h | 9 +++ soh/soh/SaveManager.cpp | 1 - soh/soh/SaveManager.h | 1 - soh/soh/SohGui/SohMenuAchievements.cpp | 32 ++++++---- .../actors/ovl_Boss_Ganon2/z_boss_ganon2.c | 2 +- 7 files changed, 63 insertions(+), 45 deletions(-) diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 3743629defa..adbcf754de0 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -223,7 +223,7 @@ typedef struct ShipQuestSaveContextData { } ShipQuestSaveContextData; typedef struct ShipAchievementSaveContextData { - u16 achievementFlags; + u32 achievementFlags; } ShipAchievementSaveContextData; typedef struct ShipSaveContextData { diff --git a/soh/soh/Enhancements/achievements.cpp b/soh/soh/Enhancements/achievements.cpp index 39845bd8667..5c061eec577 100644 --- a/soh/soh/Enhancements/achievements.cpp +++ b/soh/soh/Enhancements/achievements.cpp @@ -8,9 +8,9 @@ extern "C" SaveContext gSaveContext; static RegisterShipInitFunc initFunc(Achievements_Init); +void Achievements_InitDefaults(bool isDebug); void Achievements_Load(); void Achievements_Save(SaveContext* saveContext, int sectionID, bool fullSave); -void Achievements_InitDefaults(bool isDebug); const char* Achievements_GetName(AchievementId id); void Achievements_Init() { @@ -25,6 +25,8 @@ void Achievements_InitDefaults(bool isDebug) { void Achievements_Load() { SaveManager::Instance->LoadData("achievementFlags", gSaveContext.ship.achievements.achievementFlags); + + SPDLOG_INFO("Loaded achievementFlags={}",gSaveContext.ship.achievements.achievementFlags); } void Achievements_Save(SaveContext* saveContext, int sectionID, bool fullSave) { @@ -38,38 +40,37 @@ extern "C" bool Achievements_IsUnlocked(AchievementId id) { extern "C" void Achievements_TryUnlock(AchievementId id) { if (!Achievements_IsUnlocked(id)) { gSaveContext.ship.achievements.achievementFlags |= (1ULL << id); + const AchievementInfo* info = Achievements_GetInfo(id); Notification::Emit({ - .itemIcon = "__OTR__textures/icon_item_24_static/gQuestIconGoldSkulltulaTex", - .prefix = "", - .message = Achievements_GetName(id), - .suffix = "", + .itemIcon = "__OTR__textures/object_goma/gGohmaTitleCardENGTex", + .message = info->name, }); + + SPDLOG_INFO("Unlock {} -> flags={}", static_cast(id), gSaveContext.ship.achievements.achievementFlags); } } -const char* Achievements_GetName(AchievementId id) { - switch (id) { - case ACHIEVEMENT_DEFEAT_GOHMA: - return "Defeat Gohma"; - case ACHIEVEMENT_DEFEAT_KD: - return "Defeat King Dodongo"; - case ACHIEVEMENT_DEFEAT_BARINADE: - return "Defeat Barinade"; - case ACHIEVEMENT_DEFEAT_PG: - return "Defeat Phantom Ganon"; - case ACHIEVEMENT_DEFEAT_VOLVAGIA: - return "Defeat Volvagia"; - case ACHIEVEMENT_DEFEAT_MORPHA: - return "Defeat Morpha"; - case ACHIEVEMENT_DEFEAT_BONGO: - return "Defeat Bongo Bongo"; - case ACHIEVEMENT_DEFEAT_TWINROVA: - return "Defeat Twinrova"; - case ACHIEVEMENT_DEFEAT_GANONDORF: - return "Defeat Ganondorf"; - case ACHIEVEMENT_DEFEAT_GANON: - return "Defeat Ganon"; - default: - return "Unknown Achievement"; +const AchievementInfo* Achievements_GetInfo(AchievementId id) { + for (size_t i = 0; i < gAchievementCount; i++) { + if (gAchievements[i].id == id) { + return &gAchievements[i]; + } } -} \ No newline at end of file + return NULL; +} + +const AchievementInfo gAchievements[] = { + { ACHIEVEMENT_DEFEAT_GOHMA, "Defeat Gohma" }, + { ACHIEVEMENT_DEFEAT_KD, "Defeat King Dodongo" }, + { ACHIEVEMENT_DEFEAT_BARINADE, "Defeat Barinade" }, + { ACHIEVEMENT_DEFEAT_PG, "Defeat Phantom Ganon" }, + { ACHIEVEMENT_DEFEAT_VOLVAGIA, "Defeat Volvagia" }, + { ACHIEVEMENT_DEFEAT_MORPHA, "Defeat Morpha" }, + { ACHIEVEMENT_DEFEAT_BONGO, "Defeat Bongo Bongo" }, + { ACHIEVEMENT_DEFEAT_TWINROVA, "Defeat Twinrova" }, + { ACHIEVEMENT_DEFEAT_GANONDORF, "Defeat Ganondorf" }, + { ACHIEVEMENT_DEFEAT_GANON, "Defeat Ganon" }, +}; + +const size_t gAchievementCount = + sizeof(gAchievements) / sizeof(gAchievements[0]); \ No newline at end of file diff --git a/soh/soh/Enhancements/achievements.h b/soh/soh/Enhancements/achievements.h index c0a7db25812..d596003c880 100644 --- a/soh/soh/Enhancements/achievements.h +++ b/soh/soh/Enhancements/achievements.h @@ -13,6 +13,14 @@ typedef enum { ACHIEVEMENT_DEFEAT_GANON = 9, } AchievementId; +typedef struct { + AchievementId id; + const char* name; +} AchievementInfo; + +extern const AchievementInfo gAchievements[]; +extern const size_t gAchievementCount; + #ifdef __cplusplus extern "C" { #endif @@ -20,6 +28,7 @@ extern "C" { void Achievements_Init(); bool Achievements_IsUnlocked(AchievementId id); void Achievements_TryUnlock(AchievementId id); +const AchievementInfo* Achievements_GetInfo(AchievementId id); #ifdef __cplusplus } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index 15c93408328..b073f4b2608 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -594,7 +594,6 @@ void SaveManager::StartupCheckAndInitMeta(int fileNum) { metaSaveBlock["sections"]["sohStats"]["data"]["buildVersion"], ARRAY_COUNT(fileMetaInfo[fileNum].buildVersion)); - fileMetaInfo[fileNum].achievementFlags = 0; } void SaveManager::InitMeta(int fileNum) { diff --git a/soh/soh/SaveManager.h b/soh/soh/SaveManager.h index e297fcd1aea..80f58b915e5 100644 --- a/soh/soh/SaveManager.h +++ b/soh/soh/SaveManager.h @@ -20,7 +20,6 @@ typedef struct { s16 buildVersionMajor; s16 buildVersionMinor; s16 buildVersionPatch; - u16 achievementFlags; u8 inventoryItems[24]; u16 equipment; diff --git a/soh/soh/SohGui/SohMenuAchievements.cpp b/soh/soh/SohGui/SohMenuAchievements.cpp index c4a881f8721..5f634933f29 100644 --- a/soh/soh/SohGui/SohMenuAchievements.cpp +++ b/soh/soh/SohGui/SohMenuAchievements.cpp @@ -1,5 +1,6 @@ #include "SohMenu.h" #include "soh/OTRGlobals.h" +#include "soh/Enhancements/achievements.h" extern "C" { #include "variables.h" @@ -10,22 +11,31 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +void DrawAchievementsWidget(WidgetInfo& widget) { + ImGui::SeparatorText("Obtained achievements"); + + for (size_t i = 0; i < gAchievementCount; i++) { + if (Achievements_IsUnlocked(gAchievements[i].id)) { + ImGui::Text("%s", gAchievements[i].name); + } + } + + ImGui::SeparatorText("Locked achievements"); + + for (size_t i = 0; i < gAchievementCount; i++) { + if (!Achievements_IsUnlocked(gAchievements[i].id)) { + ImGui::Text("%s", gAchievements[i].name); + } + } +} + void SohMenu::AddMenuAchievements() { // Add Achievements section AddMenuEntry("Achievements", CVAR_SETTING("Menu.AchievementsSidebarSection")); - WidgetPath path = {"Achievements", "Test 1", SECTION_COLUMN_1}; + WidgetPath path = {"Achievements", "Progress", SECTION_COLUMN_1}; AddSidebarEntry("Achievements", path.sidebarName, 2); - //Test 1 - AddWidget(path, "Obtained Achievements", WIDGET_SEPARATOR_TEXT); - AddWidget(path, "Test", WIDGET_TEXT); - AddWidget(path, "Locked Achievements", WIDGET_SEPARATOR_TEXT); - AddWidget(path, "Test", WIDGET_TEXT); - - //Test 2 - path.sidebarName = "Test 2"; - AddSidebarEntry("Achievements", path.sidebarName, 2); - AddWidget(path, "Test", WIDGET_TEXT); + AddWidget(path, "Achievements", WIDGET_CUSTOM).CustomFunction(DrawAchievementsWidget).HideInSearch(true); } // namespace SohGui } \ No newline at end of file diff --git a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c index 430dfd71a59..ebb8061f0b3 100644 --- a/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c +++ b/soh/src/overlays/actors/ovl_Boss_Ganon2/z_boss_ganon2.c @@ -1964,7 +1964,6 @@ void BossGanon2_CollisionCheck(BossGanon2* this, PlayState* play) { this->actor.colChkInfo.health -= 2; temp_v0_4 = this->actor.colChkInfo.health; if (temp_v0_4 < 0x15 && this->unk_334 == 0) { - BossGanon2_TryUnlockDeathAchievement(); func_80900818(this, play); } else { if (temp_v0_4 <= 0) { @@ -2001,6 +2000,7 @@ void BossGanon2_CollisionCheck(BossGanon2* this, PlayState* play) { if ((temp_v0_4 < 0x15) && (this->unk_334 == 0)) { func_80900818(this, play); } else if ((temp_v0_4 <= 0) && (phi_v1_2 >= 2)) { + BossGanon2_TryUnlockDeathAchievement(); func_80901020(this, play); } else { if (temp_v0_4 <= 0) { From bea6334ee452260d88d86073d8e0705dfe01f682 Mon Sep 17 00:00:00 2001 From: ssyn02 Date: Sun, 21 Jun 2026 04:40:50 -0300 Subject: [PATCH 4/5] revamped UI - custom notifications for achievements - added custom achievement icons - icons are now displayed in the achievement section of the menu and greyed out when not achieved todo: - more achievements - description tooltip on hover - maybe keep refining the notification --- .../gAchieveBarinadeDefeat.png | Bin 0 -> 8711 bytes .../gAchieveBarinadeDefeat_Grayed.png | Bin 0 -> 4601 bytes .../achievement_icons/gAchieveBongoDefeat.png | Bin 0 -> 6591 bytes .../gAchieveBongoDefeat_Grayed.png | Bin 0 -> 3404 bytes .../achievement_icons/gAchieveGanonDefeat.png | Bin 0 -> 6171 bytes .../gAchieveGanonDefeat_Grayed.png | Bin 0 -> 3282 bytes .../gAchieveGanondorfDefeat.png | Bin 0 -> 8162 bytes .../gAchieveGanondorfDefeat_Grayed.png | Bin 0 -> 4378 bytes .../achievement_icons/gAchieveGohmaDefeat.png | Bin 0 -> 8320 bytes .../gAchieveGohmaDefeat_Grayed.png | Bin 0 -> 4528 bytes .../achievement_icons/gAchieveKDDefeat.png | Bin 0 -> 8700 bytes .../gAchieveKDDefeat_Grayed.png | Bin 0 -> 4133 bytes .../gAchieveMorphaDefeat.png | Bin 0 -> 8333 bytes .../gAchieveMorphaDefeat_Grayed.png | Bin 0 -> 4179 bytes .../achievement_icons/gAchievePGDefeat.png | Bin 0 -> 5543 bytes .../gAchievePGDefeat_Grayed.png | Bin 0 -> 3116 bytes .../gAchieveTwinrovaDefeat.png | Bin 0 -> 8661 bytes .../gAchieveTwinrovaDefeat_Grayed.png | Bin 0 -> 4678 bytes .../gAchieveVolvagiaDefeat.png | Bin 0 -> 8868 bytes .../gAchieveVolvagiaDefeat_Grayed.png | Bin 0 -> 4642 bytes soh/soh/Enhancements/achievements.cpp | 58 +++++++++++--- soh/soh/Enhancements/achievements.h | 2 + soh/soh/Notification/Notification.cpp | 71 ++++++++++++++---- soh/soh/Notification/Notification.h | 1 + soh/soh/SohGui/SohMenuAchievements.cpp | 15 +++- 25 files changed, 117 insertions(+), 30 deletions(-) create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveBarinadeDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveBarinadeDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveBongoDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveBongoDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveGanonDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveGanonDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveGanondorfDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveGanondorfDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveGohmaDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveGohmaDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveKDDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveKDDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveMorphaDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveMorphaDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchievePGDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchievePGDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveTwinrovaDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveTwinrovaDefeat_Grayed.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveVolvagiaDefeat.png create mode 100644 soh/assets/custom/textures/achievement_icons/gAchieveVolvagiaDefeat_Grayed.png diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveBarinadeDefeat.png b/soh/assets/custom/textures/achievement_icons/gAchieveBarinadeDefeat.png new file mode 100644 index 0000000000000000000000000000000000000000..534f34726c11c52c18eae87082d6a91c402195b3 GIT binary patch literal 8711 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 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveBongoDefeat.png b/soh/assets/custom/textures/achievement_icons/gAchieveBongoDefeat.png new file mode 100644 index 0000000000000000000000000000000000000000..21732d2b2c5ab983ffa3a57282775c40663e5cf7 GIT binary patch literal 6591 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 xgY~8`X(ZZ=QrwP%Pv3o-D@PgGP?N=iyT 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 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveGanonDefeat_Grayed.png b/soh/assets/custom/textures/achievement_icons/gAchieveGanonDefeat_Grayed.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac5d6922cd94fa1a1865098fab4ac3f6df55a56 GIT binary patch literal 3282 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 QxBvhE07*qoM6N<$g0HgKC;$Ke literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveGanondorfDefeat.png b/soh/assets/custom/textures/achievement_icons/gAchieveGanondorfDefeat.png new file mode 100644 index 0000000000000000000000000000000000000000..1f43634a07e2d679bcf8b432032d6faca66a603b GIT binary patch literal 8162 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 IM6N<$g5RF9v;Y7A literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveGanondorfDefeat_Grayed.png b/soh/assets/custom/textures/achievement_icons/gAchieveGanondorfDefeat_Grayed.png new file mode 100644 index 0000000000000000000000000000000000000000..58a985a12856b6f412360318fe93b73f8efa2a10 GIT binary patch literal 4378 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 O0000yq literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveKDDefeat.png b/soh/assets/custom/textures/achievement_icons/gAchieveKDDefeat.png new file mode 100644 index 0000000000000000000000000000000000000000..53d94c00e037298e6249ee6488b337a24491c1b8 GIT binary patch literal 8700 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 a{{I7u|8Jerq$a2U0000=>+ literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveKDDefeat_Grayed.png b/soh/assets/custom/textures/achievement_icons/gAchieveKDDefeat_Grayed.png new file mode 100644 index 0000000000000000000000000000000000000000..035147dfde47694ce76b697e37ed454446184bb4 GIT binary patch literal 4133 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 literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveMorphaDefeat.png b/soh/assets/custom/textures/achievement_icons/gAchieveMorphaDefeat.png new file mode 100644 index 0000000000000000000000000000000000000000..681bff8e9eb85b1e69fb2e1399065c18cadeec52 GIT binary patch literal 8333 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 IM6N<$g7E>|{Qv*} literal 0 HcmV?d00001 diff --git a/soh/assets/custom/textures/achievement_icons/gAchieveVolvagiaDefeat.png b/soh/assets/custom/textures/achievement_icons/gAchieveVolvagiaDefeat.png new file mode 100644 index 0000000000000000000000000000000000000000..20be8d48bafe7e743eb8ae5773b8bacb8b10d68e GIT binary patch literal 8868 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 Y0m6aiSmd-8H2?qr07*qoM6N<$g8!T6DgXcg literal 0 HcmV?d00001 diff --git a/soh/soh/Enhancements/achievements.cpp b/soh/soh/Enhancements/achievements.cpp index 5c061eec577..ce9297698aa 100644 --- a/soh/soh/Enhancements/achievements.cpp +++ b/soh/soh/Enhancements/achievements.cpp @@ -3,6 +3,9 @@ #include "soh/Notification/Notification.h" #include "soh/ShipInit.hpp" #include "z64.h" +#include "functions.h" +#include "variables.h" +#include extern "C" SaveContext gSaveContext; @@ -11,9 +14,34 @@ static RegisterShipInitFunc initFunc(Achievements_Init); void Achievements_InitDefaults(bool isDebug); void Achievements_Load(); void Achievements_Save(SaveContext* saveContext, int sectionID, bool fullSave); -const char* Achievements_GetName(AchievementId id); + +void Achievements_LoadIcons() { + auto gui = std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()); + + gui->LoadTextureFromRawImage("gAchieveGohmaDefeat", "textures/achievement_icons/gAchieveGohmaDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveGohmaDefeat_Grayed", "textures/achievement_icons/gAchieveGohmaDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveKDDefeat", "textures/achievement_icons/gAchieveKDDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveKDDefeat_Grayed", "textures/achievement_icons/gAchieveKDDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveBarinadeDefeat", "textures/achievement_icons/gAchieveBarinadeDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveBarinadeDefeat_Grayed", "textures/achievement_icons/gAchieveBarinadeDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchievePGDefeat", "textures/achievement_icons/gAchievePGDefeat.png"); + gui->LoadTextureFromRawImage("gAchievePGDefeat_Grayed", "textures/achievement_icons/gAchievePGDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveVolvagiaDefeat", "textures/achievement_icons/gAchieveVolvagiaDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveVolvagiaDefeat_Grayed", "textures/achievement_icons/gAchieveVolvagiaDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveMorphaDefeat", "textures/achievement_icons/gAchieveMorphaDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveMorphaDefeat_Grayed", "textures/achievement_icons/gAchieveMorphaDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveBongoDefeat", "textures/achievement_icons/gAchieveBongoDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveBongoDefeat_Grayed", "textures/achievement_icons/gAchieveBongoDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveTwinrovaDefeat", "textures/achievement_icons/gAchieveTwinrovaDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveTwinrovaDefeat_Grayed", "textures/achievement_icons/gAchieveTwinrovaDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveGanondorfDefeat", "textures/achievement_icons/gAchieveGanondorfDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveGanondorfDefeat_Grayed", "textures/achievement_icons/gAchieveGanondorfDefeat_Grayed.png"); + gui->LoadTextureFromRawImage("gAchieveGanonDefeat", "textures/achievement_icons/gAchieveGanonDefeat.png"); + gui->LoadTextureFromRawImage("gAchieveGanonDefeat_Grayed", "textures/achievement_icons/gAchieveGanonDefeat_Grayed.png"); +} void Achievements_Init() { + Achievements_LoadIcons(); SaveManager::Instance->AddLoadFunction("achievements", 1, Achievements_Load); SaveManager::Instance->AddSaveFunction("achievements", 1, Achievements_Save, true, SECTION_PARENT_NONE); SaveManager::Instance->AddInitFunction(Achievements_InitDefaults); @@ -42,9 +70,15 @@ extern "C" void Achievements_TryUnlock(AchievementId id) { gSaveContext.ship.achievements.achievementFlags |= (1ULL << id); const AchievementInfo* info = Achievements_GetInfo(id); Notification::Emit({ - .itemIcon = "__OTR__textures/object_goma/gGohmaTitleCardENGTex", + .itemIcon = info->icon, + .prefix = "Achievement Unlocked!", + .prefixColor = ImVec4(1.0f, 0.85f, 0.0f, 1.0f), .message = info->name, + .messageColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f), + .achievement = true, }); + Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); SPDLOG_INFO("Unlock {} -> flags={}", static_cast(id), gSaveContext.ship.achievements.achievementFlags); } @@ -60,16 +94,16 @@ const AchievementInfo* Achievements_GetInfo(AchievementId id) { } const AchievementInfo gAchievements[] = { - { ACHIEVEMENT_DEFEAT_GOHMA, "Defeat Gohma" }, - { ACHIEVEMENT_DEFEAT_KD, "Defeat King Dodongo" }, - { ACHIEVEMENT_DEFEAT_BARINADE, "Defeat Barinade" }, - { ACHIEVEMENT_DEFEAT_PG, "Defeat Phantom Ganon" }, - { ACHIEVEMENT_DEFEAT_VOLVAGIA, "Defeat Volvagia" }, - { ACHIEVEMENT_DEFEAT_MORPHA, "Defeat Morpha" }, - { ACHIEVEMENT_DEFEAT_BONGO, "Defeat Bongo Bongo" }, - { ACHIEVEMENT_DEFEAT_TWINROVA, "Defeat Twinrova" }, - { ACHIEVEMENT_DEFEAT_GANONDORF, "Defeat Ganondorf" }, - { ACHIEVEMENT_DEFEAT_GANON, "Defeat Ganon" }, + { ACHIEVEMENT_DEFEAT_GOHMA, "Parasitic Armored Arachnid", "gAchieveGohmaDefeat", "gAchieveGohmaDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_KD, "Infernal Dinosaur", "gAchieveKDDefeat", "gAchieveKDDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_BARINADE, "Bio-Electric Anemone", "gAchieveBarinadeDefeat", "gAchieveBarinadeDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_PG, "Evil Spirit from Beyond", "gAchievePGDefeat", "gAchievePGDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_VOLVAGIA, "Subterranean Lava Dragon", "gAchieveVolvagiaDefeat", "gAchieveVolvagiaDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_MORPHA, "Giant Aquatic Amoeba", "gAchieveMorphaDefeat", "gAchieveMorphaDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_BONGO, "Phantom Shadow Beast", "gAchieveBongoDefeat", "gAchieveBongoDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_TWINROVA, "Sorceress Sisters", "gAchieveTwinrovaDefeat", "gAchieveTwinrovaDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_GANONDORF, "Great King of Evil", "gAchieveGanondorfDefeat", "gAchieveGanondorfDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_GANON, "Ganon", "gAchieveGanonDefeat", "gAchieveGanonDefeat_Grayed" }, }; const size_t gAchievementCount = diff --git a/soh/soh/Enhancements/achievements.h b/soh/soh/Enhancements/achievements.h index d596003c880..b272d644447 100644 --- a/soh/soh/Enhancements/achievements.h +++ b/soh/soh/Enhancements/achievements.h @@ -16,6 +16,8 @@ typedef enum { typedef struct { AchievementId id; const char* name; + const char* icon; + const char* grayedIcon; } AchievementInfo; extern const AchievementInfo gAchievements[]; diff --git a/soh/soh/Notification/Notification.cpp b/soh/soh/Notification/Notification.cpp index b101e2e7531..748b0989ad1 100644 --- a/soh/soh/Notification/Notification.cpp +++ b/soh/soh/Notification/Notification.cpp @@ -18,6 +18,9 @@ namespace Notification { static uint32_t nextId = 0; static std::vector notifications = {}; +void drawStandardNotification(const Options& notification); +void drawAchievementNotification(const Options& notification); + void Window::Draw() { auto vp = ImGui::GetMainViewport(); @@ -61,6 +64,11 @@ void Window::Draw() { ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 1.0f); } + if(notification.achievement) { + ImGui::PushStyleColor(ImGuiCol_Border, IM_COL32(255, 215, 0, 255)); + ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 3.0f); + } + ImGui::Begin(("notification#" + std::to_string(notification.id)).c_str(), nullptr, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar | @@ -91,24 +99,17 @@ void Window::Draw() { ImGui::SetWindowPos(notificationPos); - if (notification.itemIcon != nullptr) { - ImGui::Image( - std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(notification.itemIcon), - ImVec2(24, 24)); - ImGui::SameLine(); - } - if (!notification.prefix.empty()) { - ImGui::TextColored(notification.prefixColor, "%s", notification.prefix.c_str()); - ImGui::SameLine(); - } - ImGui::TextColored(notification.messageColor, "%s", notification.message.c_str()); - if (!notification.suffix.empty()) { - ImGui::SameLine(); - ImGui::TextColored(notification.suffixColor, "%s", notification.suffix.c_str()); + if (notification.achievement) { + drawAchievementNotification(notification); + } else { + drawStandardNotification(notification); } ImGui::End(); + if(notification.achievement) { + ImGui::PopStyleVar(); + ImGui::PopStyleColor(); + } ImGui::PopStyleVar(); } @@ -137,10 +138,48 @@ void Emit(Options notification) { notification.remainingTime = CVarGetFloat(CVAR_SETTING("Notifications.Duration"), 10.0f); } notifications.push_back(notification); - if (!notification.mute && !CVarGetInteger(CVAR_SETTING("Notifications.Mute"), 0)) { + if (!notification.mute && !notification.achievement && !CVarGetInteger(CVAR_SETTING("Notifications.Mute"), 0)) { Audio_PlaySoundGeneral(NA_SE_SY_METRONOME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } } +void drawStandardNotification(const Options& notification) { + if (notification.itemIcon != nullptr) { + ImGui::Image( + std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) + ->GetTextureByName(notification.itemIcon), + ImVec2(24, 24)); + ImGui::SameLine(); + } + if (!notification.prefix.empty()) { + ImGui::TextColored(notification.prefixColor, "%s", notification.prefix.c_str()); + ImGui::SameLine(); + } + ImGui::TextColored(notification.messageColor, "%s", notification.message.c_str()); + if (!notification.suffix.empty()) { + ImGui::SameLine(); + ImGui::TextColored(notification.suffixColor, "%s", notification.suffix.c_str()); + } +} + +void drawAchievementNotification(const Options& notification) { + if (notification.itemIcon != nullptr) { + ImGui::Image( + std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) + ->GetTextureByName(notification.itemIcon), + ImVec2(64, 64)); + ImGui::SameLine(); + } + + ImGui::BeginGroup(); + + if (!notification.prefix.empty()) { + ImGui::TextColored(notification.prefixColor, "%s", notification.prefix.c_str()); + ImGui::Dummy(ImVec2(0.0f, 5.0f)); //spacing + } + ImGui::TextColored(notification.messageColor, "%s", notification.message.c_str()); + ImGui::EndGroup(); +} + } // namespace Notification diff --git a/soh/soh/Notification/Notification.h b/soh/soh/Notification/Notification.h index bf1d4ec04e3..7fee86b5c38 100644 --- a/soh/soh/Notification/Notification.h +++ b/soh/soh/Notification/Notification.h @@ -18,6 +18,7 @@ struct Options { ImVec4 suffixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f); float remainingTime = 0.0f; // Seconds bool mute = false; // whether notification should make a noise + bool achievement = true; // whether this notification is for an achievement (custom visuals) }; class Window final : public Ship::GuiWindow { diff --git a/soh/soh/SohGui/SohMenuAchievements.cpp b/soh/soh/SohGui/SohMenuAchievements.cpp index 5f634933f29..c710cfe6d49 100644 --- a/soh/soh/SohGui/SohMenuAchievements.cpp +++ b/soh/soh/SohGui/SohMenuAchievements.cpp @@ -1,6 +1,7 @@ #include "SohMenu.h" #include "soh/OTRGlobals.h" #include "soh/Enhancements/achievements.h" +#include extern "C" { #include "variables.h" @@ -11,12 +12,22 @@ namespace SohGui { extern std::shared_ptr mSohMenu; using namespace UIWidgets; +void DrawAchievementEntry(const AchievementInfo& achievement, bool unlocked) { + auto gui = std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()); + const char* icon = unlocked ? achievement.icon : achievement.grayedIcon; + auto texture = gui->GetTextureByName(icon); + + ImGui::Image(texture, ImVec2(64, 64), ImVec2(0, 0), ImVec2(1, 1)); + ImGui::SameLine(); + ImGui::Text("%s", achievement.name); +} + void DrawAchievementsWidget(WidgetInfo& widget) { ImGui::SeparatorText("Obtained achievements"); for (size_t i = 0; i < gAchievementCount; i++) { if (Achievements_IsUnlocked(gAchievements[i].id)) { - ImGui::Text("%s", gAchievements[i].name); + DrawAchievementEntry(gAchievements[i], true); } } @@ -24,7 +35,7 @@ void DrawAchievementsWidget(WidgetInfo& widget) { for (size_t i = 0; i < gAchievementCount; i++) { if (!Achievements_IsUnlocked(gAchievements[i].id)) { - ImGui::Text("%s", gAchievements[i].name); + DrawAchievementEntry(gAchievements[i], false); } } } From f22cffe52a59a28d79efa080e81303fde76674c2 Mon Sep 17 00:00:00 2001 From: ssyn02 Date: Sun, 21 Jun 2026 20:14:16 -0300 Subject: [PATCH 5/5] achievements v1.0 - achievement menu has a custom top right button - achievement menu header hidden - notifications a bit more polished - description tooltip on hover - better unlock sound - so far only 9 basic major boss kill achievements. need ideas --- soh/soh/Enhancements/achievements.cpp | 32 +++++++++++++++++--------- soh/soh/Enhancements/achievements.h | 1 + soh/soh/Notification/Notification.cpp | 4 ++-- soh/soh/Notification/Notification.h | 2 +- soh/soh/SohGui/Menu.cpp | 23 ++++++++++++++++-- soh/soh/SohGui/SohMenuAchievements.cpp | 7 ++++++ 6 files changed, 53 insertions(+), 16 deletions(-) diff --git a/soh/soh/Enhancements/achievements.cpp b/soh/soh/Enhancements/achievements.cpp index ce9297698aa..4cae2330cdb 100644 --- a/soh/soh/Enhancements/achievements.cpp +++ b/soh/soh/Enhancements/achievements.cpp @@ -77,7 +77,7 @@ extern "C" void Achievements_TryUnlock(AchievementId id) { .messageColor = ImVec4(1.0f, 1.0f, 1.0f, 1.0f), .achievement = true, }); - Audio_PlaySoundGeneral(NA_SE_SY_CORRECT_CHIME, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, + Audio_PlaySoundGeneral(NA_SE_SY_KINSTA_MARK_APPEAR, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); SPDLOG_INFO("Unlock {} -> flags={}", static_cast(id), gSaveContext.ship.achievements.achievementFlags); @@ -94,16 +94,26 @@ const AchievementInfo* Achievements_GetInfo(AchievementId id) { } const AchievementInfo gAchievements[] = { - { ACHIEVEMENT_DEFEAT_GOHMA, "Parasitic Armored Arachnid", "gAchieveGohmaDefeat", "gAchieveGohmaDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_KD, "Infernal Dinosaur", "gAchieveKDDefeat", "gAchieveKDDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_BARINADE, "Bio-Electric Anemone", "gAchieveBarinadeDefeat", "gAchieveBarinadeDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_PG, "Evil Spirit from Beyond", "gAchievePGDefeat", "gAchievePGDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_VOLVAGIA, "Subterranean Lava Dragon", "gAchieveVolvagiaDefeat", "gAchieveVolvagiaDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_MORPHA, "Giant Aquatic Amoeba", "gAchieveMorphaDefeat", "gAchieveMorphaDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_BONGO, "Phantom Shadow Beast", "gAchieveBongoDefeat", "gAchieveBongoDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_TWINROVA, "Sorceress Sisters", "gAchieveTwinrovaDefeat", "gAchieveTwinrovaDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_GANONDORF, "Great King of Evil", "gAchieveGanondorfDefeat", "gAchieveGanondorfDefeat_Grayed" }, - { ACHIEVEMENT_DEFEAT_GANON, "Ganon", "gAchieveGanonDefeat", "gAchieveGanonDefeat_Grayed" }, + { ACHIEVEMENT_DEFEAT_GOHMA, "Parasitic Armored Arachnid", "gAchieveGohmaDefeat", "gAchieveGohmaDefeat_Grayed", + "Defeat Queen Gohma." }, + { ACHIEVEMENT_DEFEAT_KD, "Infernal Dinosaur", "gAchieveKDDefeat", "gAchieveKDDefeat_Grayed", + "Defeat King Dodongo." }, + { ACHIEVEMENT_DEFEAT_BARINADE, "Bio-Electric Anemone", "gAchieveBarinadeDefeat", "gAchieveBarinadeDefeat_Grayed", + "Defeat Barinade." }, + { ACHIEVEMENT_DEFEAT_PG, "Evil Spirit from Beyond", "gAchievePGDefeat", "gAchievePGDefeat_Grayed", + "Defeat Phantom Ganon." }, + { ACHIEVEMENT_DEFEAT_VOLVAGIA, "Subterranean Lava Dragon", "gAchieveVolvagiaDefeat", "gAchieveVolvagiaDefeat_Grayed", + "Defeat Volvagia." }, + { ACHIEVEMENT_DEFEAT_MORPHA, "Giant Aquatic Amoeba", "gAchieveMorphaDefeat", "gAchieveMorphaDefeat_Grayed", + "Defeat Morpha." }, + { ACHIEVEMENT_DEFEAT_BONGO, "Phantom Shadow Beast", "gAchieveBongoDefeat", "gAchieveBongoDefeat_Grayed", + "Defeat Bongo." }, + { ACHIEVEMENT_DEFEAT_TWINROVA, "Sorceress Sisters", "gAchieveTwinrovaDefeat", "gAchieveTwinrovaDefeat_Grayed", + "Defeat Twinrova." }, + { ACHIEVEMENT_DEFEAT_GANONDORF, "Great King of Evil", "gAchieveGanondorfDefeat", "gAchieveGanondorfDefeat_Grayed", + "Defeat Ganondorf." }, + { ACHIEVEMENT_DEFEAT_GANON, "Ganon", "gAchieveGanonDefeat", "gAchieveGanonDefeat_Grayed", + "Defeat Ganon." }, }; const size_t gAchievementCount = diff --git a/soh/soh/Enhancements/achievements.h b/soh/soh/Enhancements/achievements.h index b272d644447..232760e4611 100644 --- a/soh/soh/Enhancements/achievements.h +++ b/soh/soh/Enhancements/achievements.h @@ -18,6 +18,7 @@ typedef struct { const char* name; const char* icon; const char* grayedIcon; + const char* description; } AchievementInfo; extern const AchievementInfo gAchievements[]; diff --git a/soh/soh/Notification/Notification.cpp b/soh/soh/Notification/Notification.cpp index 748b0989ad1..576417e40fd 100644 --- a/soh/soh/Notification/Notification.cpp +++ b/soh/soh/Notification/Notification.cpp @@ -168,7 +168,7 @@ void drawAchievementNotification(const Options& notification) { ImGui::Image( std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) ->GetTextureByName(notification.itemIcon), - ImVec2(64, 64)); + ImVec2(80, 80)); ImGui::SameLine(); } @@ -176,7 +176,7 @@ void drawAchievementNotification(const Options& notification) { if (!notification.prefix.empty()) { ImGui::TextColored(notification.prefixColor, "%s", notification.prefix.c_str()); - ImGui::Dummy(ImVec2(0.0f, 5.0f)); //spacing + ImGui::Dummy(ImVec2(0.0f, 2.0f)); //spacing } ImGui::TextColored(notification.messageColor, "%s", notification.message.c_str()); ImGui::EndGroup(); diff --git a/soh/soh/Notification/Notification.h b/soh/soh/Notification/Notification.h index 7fee86b5c38..35509ddd790 100644 --- a/soh/soh/Notification/Notification.h +++ b/soh/soh/Notification/Notification.h @@ -18,7 +18,7 @@ struct Options { ImVec4 suffixColor = ImVec4(1.0f, 0.5f, 0.5f, 1.0f); float remainingTime = 0.0f; // Seconds bool mute = false; // whether notification should make a noise - bool achievement = true; // whether this notification is for an achievement (custom visuals) + bool achievement = false; // whether this notification is for an achievement (custom visuals) }; class Window final : public Ship::GuiWindow { diff --git a/soh/soh/SohGui/Menu.cpp b/soh/soh/SohGui/Menu.cpp index c41bfe74a41..b2823e952f8 100644 --- a/soh/soh/SohGui/Menu.cpp +++ b/soh/soh/SohGui/Menu.cpp @@ -672,6 +672,10 @@ void Menu::DrawElement() { headerWidth += 200.0f; } for (auto& label : menuOrder) { + if (label == "Achievements") { + continue; //ignore achievements for header sizing + } + ImVec2 size = ImGui::CalcTextSize(label.c_str()); headerSizes.push_back(size); headerWidth += size.x + style.FramePadding.x * 2 + style.ItemSpacing.x; @@ -713,10 +717,17 @@ void Menu::DrawElement() { ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_HorizontalScrollbar); uint8_t curIndex = 0; for (auto& label : menuOrder) { + auto& entry = menuEntries.at(label); + + if (label == "Achievements") { + if (headerIndex == label) { + sidebar = &entry.sidebars; + } + continue; //make the achievement menu header hidden + } if (curIndex != 0) { ImGui::SameLine(); } - auto& entry = menuEntries.at(label); std::string nextIndex = label; UIWidgets::PushStyleButton(menuThemeIndex); if (headerIndex != label) { @@ -763,7 +774,15 @@ void Menu::DrawElement() { ImGui::PopStyleColor(); } ImGui::EndChild(); - ImGui::SameLine(menuSize.x - (buttonSize.x * 3) - (style.ItemSpacing.x * 2)); + ImGui::SameLine(menuSize.x - (buttonSize.x * 4) - (style.ItemSpacing.x * 3)); + UIWidgets::ButtonOptions options4 = {}; + options4.color = UIWidgets::Colors::Violet; + options4.size = UIWidgets::Sizes::Inline; + options4.tooltip = "Achievements"; + if (UIWidgets::Button(ICON_FA_TROPHY, options4)) { + CVarSetString(CVAR_SETTING("Menu.ActiveHeader"), "Achievements"); + } + ImGui::SameLine(); UIWidgets::ButtonOptions options3 = {}; options3.color = UIWidgets::Colors::Red; options3.size = UIWidgets::Sizes::Inline; diff --git a/soh/soh/SohGui/SohMenuAchievements.cpp b/soh/soh/SohGui/SohMenuAchievements.cpp index c710cfe6d49..6d0198ebaf5 100644 --- a/soh/soh/SohGui/SohMenuAchievements.cpp +++ b/soh/soh/SohGui/SohMenuAchievements.cpp @@ -18,8 +18,15 @@ void DrawAchievementEntry(const AchievementInfo& achievement, bool unlocked) { auto texture = gui->GetTextureByName(icon); ImGui::Image(texture, ImVec2(64, 64), ImVec2(0, 0), ImVec2(1, 1)); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", achievement.description); + } ImGui::SameLine(); + ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 16.0f); ImGui::Text("%s", achievement.name); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("%s", achievement.description); + } } void DrawAchievementsWidget(WidgetInfo& widget) {