From e163d5bc3d1e3a7978bf204a4d554f51f6324fb0 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Sun, 7 Apr 2024 22:28:20 +0100 Subject: [PATCH 01/10] Fix switch puzzle locking issues (#4027) --- soh/src/code/z_bgcheck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/src/code/z_bgcheck.c b/soh/src/code/z_bgcheck.c index 7c99e7ca2..064d59860 100644 --- a/soh/src/code/z_bgcheck.c +++ b/soh/src/code/z_bgcheck.c @@ -398,7 +398,7 @@ s32 CollisionPoly_LineVsPoly(CollisionPoly* poly, Vec3s* vtxList, Vec3f* posA, V (poly->normal.x * posB->x + poly->normal.y * posB->y + poly->normal.z * posB->z) * COLPOLY_NORMAL_FRAC + plane.originDist; -#ifdef __WIIU__ +#if defined(__SWITCH__) || defined(__WIIU__) // on some platforms this ends up as very small numbers due to rounding issues if (IS_ZERO(planeDistA)) { planeDistA = 0.0f; From ced34ab68a3b76cd27f636bd98469e962b7b9d03 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Mon, 15 Apr 2024 17:00:04 +0100 Subject: [PATCH 02/10] [Fix] Disable Lod Applies To Everything (Macready) (#4034) * make lod cvar affect everything * add to more functions * re-add to player * only add to necessary funcs --- soh/src/code/z_fcurve_data_skelanime.c | 4 ++++ soh/src/code/z_skelanime.c | 8 ++++++++ soh/src/overlays/actors/ovl_player_actor/z_player.c | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_fcurve_data_skelanime.c b/soh/src/code/z_fcurve_data_skelanime.c index c75450be2..b75c34a61 100644 --- a/soh/src/code/z_fcurve_data_skelanime.c +++ b/soh/src/code/z_fcurve_data_skelanime.c @@ -131,6 +131,10 @@ void SkelCurve_DrawLimb(PlayState* play, s32 limbIndex, SkelAnimeCurve* skelCurv Matrix_TranslateRotateZYX(&pos, &rot); Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY); + if (CVarGetInteger("gDisableLOD", 0)) { + lod = 0; + } + if (lod == 0) { s32 pad1; diff --git a/soh/src/code/z_skelanime.c b/soh/src/code/z_skelanime.c index 7440640a0..2123c2d3b 100644 --- a/soh/src/code/z_skelanime.c +++ b/soh/src/code/z_skelanime.c @@ -78,6 +78,10 @@ void SkelAnime_DrawLod(PlayState* play, void** skeleton, Vec3s* jointTable, Vec3f pos; Vec3s rot; + if (CVarGetInteger("gDisableLOD", 0)) { + lod = 0; + } + if (skeleton == NULL) { osSyncPrintf(VT_FGCOL(RED)); osSyncPrintf("Si2_Lod_draw():skelがNULLです。\n"); // "skel is NULL." @@ -191,6 +195,10 @@ void SkelAnime_DrawFlexLod(PlayState* play, void** skeleton, Vec3s* jointTable, Vec3s rot; Mtx* mtx = Graph_Alloc(play->state.gfxCtx, dListCount * sizeof(Mtx)); + if (CVarGetInteger("gDisableLOD", 0)) { + lod = 0; + } + if (skeleton == NULL) { osSyncPrintf(VT_FGCOL(RED)); osSyncPrintf("Si2_Lod_draw_SV():skelがNULLです。\n"); // "skel is NULL." diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index ca7333497..965389c40 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -11339,7 +11339,7 @@ void Player_Draw(Actor* thisx, PlayState* play2) { lod = 1; } - if (CVarGetInteger("gDisableLOD", 0) != 0) { + if (CVarGetInteger("gDisableLOD", 0)) { lod = 0; } From 0b8cc71d0d59883304aee2d3287f19bc81da03b7 Mon Sep 17 00:00:00 2001 From: Archez Date: Fri, 19 Apr 2024 09:41:04 -0400 Subject: [PATCH 03/10] fix actor init flow with object loading (#3987) --- soh/src/code/z_actor.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index c1dc66e23..0accb49d0 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1220,7 +1220,7 @@ void Actor_Init(Actor* actor, PlayState* play) { actor->floorBgId = BGCHECK_SCENE; ActorShape_Init(&actor->shape, 0.0f, NULL, 0.0f); if (Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { - //Actor_SetObjectDependency(play, actor); + Actor_SetObjectDependency(play, actor); actor->init(actor, play); actor->init = NULL; @@ -2548,6 +2548,13 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { Actor_SetObjectDependency(play, actor); actor->init(actor, play); actor->init = NULL; + + GameInteractor_ExecuteOnActorInit(actor); + + // For enemy health bar we need to know the max health during init + if (actor->category == ACTORCAT_ENEMY) { + actor->maximumHealth = actor->colChkInfo.health; + } } actor = actor->next; } else if (!Object_IsLoaded(&play->objectCtx, actor->objBankIndex)) { From 19be6e9b9973f3a94cd0f582d7de42d9e6e6b0c6 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Fri, 19 Apr 2024 06:41:46 -0700 Subject: [PATCH 04/10] Trackers MQ Cleanup (#4009) * Clean up grayed out items in file select. Tie personal notes saving to `OnExitGame()` to account for save scum resets. Hide text input box (but not window) for personal notes when a save isn't loaded to prevent saving over a save's notes while in file select. * Allow check tracker window to be visible and show the "Waiting for file load..." text in file select (ease of positioning). * Fix key label text placement. * Persist `areasSpoiled`, change trigger to `OnSceneTransition`. Add `IsAreaSpoiled` for tie-in to Item Tracker. Add `SetAreaSpoiled` to unify bitmagic. * Add proper spoiling evaluation based on specific entrance IDs, or first check collection. Add light yellow color for vanilla dungeon abbreviations to match the purple for MQ. * Initialize `areasSpoiled` to 0, so 0 gets saved on file create. * All new conditional statements around `GameInteractor::IsSaveLoaded()` were inverted. Fixed that. * Change some c-style casts to `static_cast`. * Few more cleanups, plus clarifying comment. --- .../randomizer/randomizer_check_tracker.cpp | 70 +++++++++++++------ .../randomizer/randomizer_check_tracker.h | 2 + .../randomizer/randomizer_item_tracker.cpp | 53 ++++++++------ 3 files changed, 81 insertions(+), 44 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index b9ca97a9b..7c1f99a15 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -103,6 +103,23 @@ std::map DungeonRCAreasBySceneID = { {SCENE_INSIDE_GANONS_CASTLE, RCAREA_GANONS_CASTLE}, }; +// Dungeon entrances with obvious visual differences between MQ and vanilla qualifying as spoiling on sight +std::vector spoilingEntrances = { + 0x0000, // ENTR_DEKU_TREE_0 + 0x0467, // ENTR_DODONGOS_CAVERN_1 + 0x0028, // ENTR_JABU_JABU_0 + 0x0407, // ENTR_JABU_JABU_1 + 0x0169, // ENTR_FOREST_TEMPLE_0 + 0x0165, // ENTR_FIRE_TEMPLE_0 + 0x0175, // ENTR_FIRE_TEMPLE_1 + 0x0423, // ENTR_WATER_TEMPLE_1 + 0x0082, // ENTR_SPIRIT_TEMPLE_0 + 0x02B2, // ENTR_SHADOW_TEMPLE_1 + 0x0088, // ENTR_ICE_CAVERN_0 + 0x0008, // ENTR_GERUDO_TRAINING_GROUNDS_0 + 0x0467 // ENTR_INSIDE_GANONS_CASTLE_0 +}; + std::map> checksByArea; bool areasFullyChecked[RCAREA_INVALID]; u32 areasSpoiled = 0; @@ -263,6 +280,10 @@ void SetCheckCollected(RandomizerCheck rc) { } SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true); + if (!IsAreaSpoiled(rcObj.rcArea)) { + SetAreaSpoiled(rcObj.rcArea); + } + doAreaScroll = true; UpdateOrdering(rcObj.rcArea); UpdateInventoryChecks(); @@ -467,9 +488,14 @@ void CheckTrackerLoadGame(int32_t fileNum) { areaChecksGotten[realRcObj.rcArea]++; } } - - if (areaChecksGotten[realRcObj.rcArea] != 0 || RandomizerCheckObjects::AreaIsOverworld(realRcObj.rcArea)) { - areasSpoiled |= (1 << realRcObj.rcArea); + } + for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) { + if (!IsAreaSpoiled(static_cast(i)) && (RandomizerCheckObjects::AreaIsOverworld(static_cast(i)) || !IS_RANDO || + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_NONE || + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SELECTION || + (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12))) { + SetAreaSpoiled(static_cast(i)); } } if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) { @@ -539,6 +565,9 @@ void CheckTrackerTransition(uint32_t sceneNum) { SetShopSeen(sceneNum, false); break; } + if (!IsAreaSpoiled(currentArea) && (RandomizerCheckObjects::AreaIsOverworld(currentArea) || std::find(spoilingEntrances.begin(), spoilingEntrances.end(), gPlayState->nextEntranceIndex) != spoilingEntrances.end())) { + SetAreaSpoiled(currentArea); + } } void CheckTrackerFrame() { @@ -756,6 +785,7 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) { void InitTrackerData(bool isDebug) { TrySetAreas(); + areasSpoiled = 0; for (auto& [rc, rco] : RandomizerCheckObjects::GetAllRCObjects()) { if (rc != RC_UNKNOWN_CHECK && rc != RC_MAX) { DefaultCheckData(rc); @@ -783,6 +813,7 @@ void SaveTrackerData(SaveContext* saveContext, int sectionID, bool gameSave) { SaveManager::Instance->SaveData("hintItem", saveContext->checkTrackerData[i].hintItem); }); }); + SaveManager::Instance->SaveData("areasSpoiled", areasSpoiled); } void SaveFile(SaveContext* saveContext, int sectionID, bool fullSave) { @@ -798,6 +829,7 @@ void LoadFile() { SaveManager::Instance->LoadData("hintItem", gSaveContext.checkTrackerData[i].hintItem); }); }); + SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled); } void Teardown() { @@ -809,6 +841,15 @@ void Teardown() { lastLocationChecked = RC_UNKNOWN_CHECK; } +bool IsAreaSpoiled(RandomizerCheckArea rcArea) { + return areasSpoiled & (1 << rcArea); +} + +void SetAreaSpoiled(RandomizerCheckArea rcArea) { + areasSpoiled |= (1 << rcArea); + SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true); +} + void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { auto area = RandomizerCheckObjects::GetAllRCObjects().find(static_cast(check))->second.rcArea; if ((!gSaveContext.checkTrackerData[check].skipped && data.skipped) || @@ -827,10 +868,6 @@ void UpdateCheck(uint32_t check, RandomizerCheckTrackerData data) { void CheckTrackerWindow::DrawElement() { ImGui::SetNextWindowSize(ImVec2(400, 540), ImGuiCond_FirstUseEver); - if (!initialized && (gPlayState == nullptr || gSaveContext.fileNum < 0 || gSaveContext.fileNum > 2)) { - return; - } - if (CVarGetInteger("gCheckTrackerWindowType", TRACKER_WINDOW_WINDOW) == TRACKER_WINDOW_FLOATING) { if (CVarGetInteger("gCheckTrackerShowOnlyPaused", 0) && (gPlayState == nullptr || gPlayState->pauseCtx.state == 0)) { return; @@ -851,7 +888,7 @@ void CheckTrackerWindow::DrawElement() { BeginFloatWindows("Check Tracker", mIsVisible, ImGuiWindowFlags_NoScrollbar); - if (!GameInteractor::IsSaveLoaded()) { + if (!GameInteractor::IsSaveLoaded() || !initialized) { ImGui::Text("Waiting for file load..."); //TODO Language EndFloatWindows(); return; @@ -862,8 +899,6 @@ void CheckTrackerWindow::DrawElement() { sceneId = (SceneID)gPlayState->sceneNum; } - areasSpoiled |= (1 << currentArea); - //Quick Options #ifdef __WIIU__ float headerHeight = 40.0f; @@ -925,7 +960,6 @@ void CheckTrackerWindow::DrawElement() { Color_RGBA8 mainColor; Color_RGBA8 extraColor; std::string stemp; - s32 areaMask = 1; for (auto& [rcArea, objs] : checksByArea) { RandomizerCheckArea thisArea = currentArea; @@ -978,11 +1012,7 @@ void CheckTrackerWindow::DrawElement() { ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(extraColor.r / 255.0f, extraColor.g / 255.0f, extraColor.b / 255.0f, extraColor.a / 255.0f)); - isThisAreaSpoiled = areasSpoiled & areaMask || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0) || !IS_RANDO || - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_NONE || - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SELECTION || - (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_RANDOM_MQ_DUNGEONS) == RO_MQ_DUNGEONS_SET_NUMBER && - OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12); + isThisAreaSpoiled = IsAreaSpoiled(rcArea) || CVarGetInteger("gCheckTrackerOptionMQSpoilers", 0); if (isThisAreaSpoiled) { if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) { @@ -1015,7 +1045,6 @@ void CheckTrackerWindow::DrawElement() { ImGui::TreePop(); } } - areaMask <<= 1; } ImGui::EndTable(); //Checks Lead-out @@ -1219,10 +1248,10 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj) { } void UpdateInventoryChecks() { - //For all the areas with compasses, if you have one, spoil the area + //For all the areas with maps, if you have one, spoil the area for (auto [scene, area] : DungeonRCAreasBySceneID) { if (CHECK_DUNGEON_ITEM(DUNGEON_MAP, scene)) { - areasSpoiled |= (1 << area); + SetAreaSpoiled(area); } } } @@ -1232,9 +1261,6 @@ void UpdateAreaFullyChecked(RandomizerCheckArea area) { void UpdateAreas(RandomizerCheckArea area) { areasFullyChecked[area] = areaChecksGotten[area] == checksByArea.find(area)->second.size(); - if (areaChecksGotten[area] != 0 || RandomizerCheckObjects::AreaIsOverworld(area)) { - areasSpoiled |= (1 << area); - } } void UpdateAllOrdering() { diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index a8928cca3..85a4f1d9e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -50,6 +50,8 @@ bool IsVisibleInCheckTracker(RandomizerCheckObject rcObj); void InitTrackerData(bool isDebug); RandomizerCheckArea GetCheckArea(); void UpdateCheck(uint32_t, RandomizerCheckTrackerData); +bool IsAreaSpoiled(RandomizerCheckArea rcArea); +void SetAreaSpoiled(RandomizerCheckArea rcArea); } // namespace CheckTracker diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index f63b37b62..44671b5c6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -9,6 +9,7 @@ #include #include #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "randomizer_check_tracker.h" #include extern "C" { @@ -290,15 +291,15 @@ bool IsValidSaveFile() { } bool HasSong(ItemTrackerItem item) { - return (1 << item.id) & gSaveContext.inventory.questItems; + return GameInteractor::IsSaveLoaded() ? ((1 << item.id) & gSaveContext.inventory.questItems) : false; } bool HasQuestItem(ItemTrackerItem item) { - return (item.data & gSaveContext.inventory.questItems) != 0; + return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.questItems) : false; } bool HasEquipment(ItemTrackerItem item) { - return (item.data & gSaveContext.inventory.equipment) != 0; + return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.equipment) : false; } ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { @@ -406,8 +407,12 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { #define IM_COL_GREEN IM_COL32(0, 255, 0, 255) #define IM_COL_GRAY IM_COL32(155, 155, 155, 255) #define IM_COL_PURPLE IM_COL32(180, 90, 200, 255) +#define IM_COL_LIGHT_YELLOW IM_COL32(255, 255, 130, 255) -void DrawItemCount(ItemTrackerItem item) { +void DrawItemCount(ItemTrackerItem item, bool hideMax) { + if (!GameInteractor::IsSaveLoaded()) { + return; + } int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); ItemTrackerNumbers currentAndMax = GetItemCurrentAndMax(item); ImVec2 p = ImGui::GetCursorScreenPos(); @@ -416,7 +421,7 @@ void DrawItemCount(ItemTrackerItem item) { if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { std::string currentString = ""; - std::string maxString = std::to_string(currentAndMax.maxCapacity); + std::string maxString = hideMax ? "???" : std::to_string(currentAndMax.maxCapacity); ImU32 currentColor = IM_COL_WHITE; ImU32 maxColor = IM_COL_GREEN; // "Collected / Max", "Current / Collected / Max", "Current / Max" @@ -548,7 +553,7 @@ void DrawQuest(ItemTrackerItem item) { ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); if (item.id == QUEST_SKULL_TOKEN) { - DrawItemCount(item); + DrawItemCount(item, false); } ImGui::EndGroup(); @@ -558,7 +563,7 @@ void DrawQuest(ItemTrackerItem item) { void DrawItem(ItemTrackerItem item) { - uint32_t actualItemId = INV_CONTENT(item.id); + uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE; int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); bool hasItem = actualItemId != ITEM_NONE; std::string itemName = ""; @@ -617,7 +622,7 @@ void DrawItem(ItemTrackerItem item) { ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - DrawItemCount(item); + DrawItemCount(item, false); ImGui::EndGroup(); if (itemName == "") { @@ -628,7 +633,7 @@ void DrawItem(ItemTrackerItem item) { } void DrawBottle(ItemTrackerItem item) { - uint32_t actualItemId = gSaveContext.inventory.items[SLOT(item.id) + item.data]; + uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? (gSaveContext.inventory.items[SLOT(item.id) + item.data]) : false; bool hasItem = actualItemId != ITEM_NONE; if (GameInteractor::IsSaveLoaded() && (hasItem && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) { @@ -647,8 +652,8 @@ void DrawDungeonItem(ItemTrackerItem item) { ImU32 dungeonColor = IM_COL_WHITE; uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential int iconSize = CVarGetInteger("gItemTrackerIconSize", 36); - bool hasItem = (bitMask & gSaveContext.inventory.dungeonItems[item.data]) != 0; - bool hasSmallKey = (gSaveContext.inventory.dungeonKeys[item.data]) >= 0; + bool hasItem = GameInteractor::IsSaveLoaded() ? (bitMask & gSaveContext.inventory.dungeonItems[item.data]) : false; + bool hasSmallKey = GameInteractor::IsSaveLoaded() ? ((gSaveContext.inventory.dungeonKeys[item.data]) >= 0) : false; ImGui::BeginGroup(); if (itemId == ITEM_KEY_SMALL) { ImGui::Image(LUS::Context::GetInstance()->GetWindow()->GetGui()->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded), @@ -659,16 +664,18 @@ void DrawDungeonItem(ItemTrackerItem item) { ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); } - if (ResourceMgr_IsSceneMasterQuest(item.data) && (CHECK_DUNGEON_ITEM(DUNGEON_MAP, item.data) || item.data == SCENE_GERUDO_TRAINING_GROUND || item.data == SCENE_INSIDE_GANONS_CASTLE)) { - dungeonColor = IM_COL_PURPLE; + if (CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast(item.data))) && GameInteractor::IsSaveLoaded()) { + dungeonColor = (ResourceMgr_IsSceneMasterQuest(item.data) ? IM_COL_PURPLE : IM_COL_LIGHT_YELLOW); } if (itemId == ITEM_KEY_SMALL) { - DrawItemCount(item); + DrawItemCount(item, !CheckTracker::IsAreaSpoiled(RandomizerCheckObjects::GetRCAreaBySceneID(static_cast(item.data)))); ImVec2 p = ImGui::GetCursorScreenPos(); + // offset puts the text at the correct level. for some reason, if the save is loaded, the margin is 3 pixels higher only for small keys, so we use 16 then. Otherwise, 13 is where everything else is + int offset = GameInteractor::IsSaveLoaded() ? 16 : 13; std::string dungeonName = itemTrackerDungeonShortNames[item.data]; - ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + 16))); + ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(dungeonName.c_str()).x / 2), p.y - (iconSize + offset))); ImGui::PushStyleColor(ImGuiCol_Text, dungeonColor); ImGui::Text("%s", dungeonName.c_str()); ImGui::PopStyleColor(); @@ -725,13 +732,15 @@ void DrawNotes(bool resizeable = false) { } }; ImVec2 size = resizeable ? ImVec2(-FLT_MIN, ImGui::GetContentRegionAvail().y) : ImVec2(((iconSize + iconSpacing) * 6) - 8, 200); - if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) { - notesNeedSave = true; - notesIdleFrames = 0; - } - if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) { - notesNeedSave = false; - SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true); + if (GameInteractor::IsSaveLoaded()) { + if (ItemTrackerNotes::TrackerNotesInputTextMultiline("##ItemTrackerNotes", &itemTrackerNotes, size, ImGuiInputTextFlags_AllowTabInput)) { + notesNeedSave = true; + notesIdleFrames = 0; + } + if ((ImGui::IsItemDeactivatedAfterEdit() || (notesNeedSave && notesIdleFrames > notesMaxIdleFrames)) && IsValidSaveFile()) { + notesNeedSave = false; + SaveManager::Instance->SaveSection(gSaveContext.fileNum, itemTrackerSectionId, true); + } } ImGui::EndGroup(); } From 32288be744a959f5cb12d7787e3aaff7ea948238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Amaro=20Mart=C3=ADnez?= Date: Fri, 19 Apr 2024 08:41:55 -0500 Subject: [PATCH 05/10] Save in-game language setting (#4026) --- soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c index 5c5cb3e6d..1682de47d 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_nameset_PAL.c @@ -692,6 +692,7 @@ void FileChoose_UpdateOptionsMenu(GameState* thisx) { sLastOptionButtonIndex = -1; osSyncPrintf("SAVE"); Save_SaveGlobal(); + CVarSave(); osSyncPrintf(VT_FGCOL(YELLOW)); osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting); osSyncPrintf("Na_SetSoundOutputMode = %d\n", gSaveContext.audioSetting); From bfe13906e9c1e21e06f7afa1313b0ee4de825d32 Mon Sep 17 00:00:00 2001 From: inspectredc <78732756+inspectredc@users.noreply.github.com> Date: Fri, 19 Apr 2024 14:42:12 +0100 Subject: [PATCH 06/10] Make equip swap work on pause any cursor (#4052) --- soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index 665c95b81..4e82cb8e7 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -237,8 +237,8 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { s16 oldCursorPoint; s16 moveCursorResult; bool dpad = (CVarGetInteger("gDpadPause", 0) && !CHECK_BTN_ALL(input->cur.button, BTN_CUP)); - bool pauseAnyCursor = (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || - (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON); + bool pauseAnyCursor = pauseCtx->cursorSpecialPos == 0 && ((CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_RANDO_ONLY && IS_RANDO) || + (CVarGetInteger("gPauseAnyCursor", 0) == PAUSE_ANY_CURSOR_ALWAYS_ON)); // only allow mask select when: // the shop is open: From 02f7310c167b27befe05e4d41e7070eb8a959570 Mon Sep 17 00:00:00 2001 From: Malkierian Date: Fri, 19 Apr 2024 06:42:26 -0700 Subject: [PATCH 07/10] Add keyring to check for placing Gerudo Fortess Keys in Any Dungeon or Overworld. (#4055) --- soh/soh/Enhancements/randomizer/3drando/fill.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index f9d3a9592..fa20a083d 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -846,10 +846,10 @@ static void RandomizeDungeonItems() { } if (GerudoKeys.Is(GERUDOKEYS_ANY_DUNGEON)) { - auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; }); + auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; }); AddElementsToPool(anyDungeonItems, gerudoKeys); } else if (GerudoKeys.Is(GERUDOKEYS_OVERWORLD)) { - auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY; }); + auto gerudoKeys = FilterAndEraseFromPool(ItemPool, [](const auto i) { return i == GERUDO_FORTRESS_SMALL_KEY || i == GERUDO_FORTRESS_KEY_RING; }); AddElementsToPool(overworldItems, gerudoKeys); } From 32bf8cc53ce6a90ade7b6ce47cc3d7db3b46a6b9 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 19 Apr 2024 09:42:41 -0400 Subject: [PATCH 08/10] fix wii u ci (#4056) --- .github/workflows/generate-builds.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml index 38cc4c9ad..c4523b917 100644 --- a/.github/workflows/generate-builds.yml +++ b/.github/workflows/generate-builds.yml @@ -235,7 +235,6 @@ jobs: - name: Install dependencies if: ${{ !vars.LINUX_RUNNER }} run: | - sudo apt-get update sudo apt-get install -y ninja-build - uses: actions/checkout@v3 with: From 2216b681111b951744980f219529bb6d9bb69db0 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Fri, 19 Apr 2024 11:06:52 -0400 Subject: [PATCH 09/10] fix: add include missed in merge conflict resolution --- soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 7d58d9476..08efbf99b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -9,6 +9,7 @@ #include #include #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "randomizer_check_tracker.h" #include extern "C" { From 43e8eec6bd417ce119f505419670a4476b520035 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Fri, 19 Apr 2024 12:28:38 -0500 Subject: [PATCH 10/10] Replace some printfs with spdlogs (#4058) --- .../Enhancements/randomizer/3drando/fill.cpp | 24 ++++++++----------- .../Enhancements/randomizer/3drando/hints.cpp | 4 ++-- .../randomizer/3drando/item_pool.cpp | 2 +- .../Enhancements/randomizer/3drando/menu.cpp | 6 ++--- .../randomizer/3drando/playthrough.cpp | 16 ++++++------- .../randomizer/3drando/spoiler_log.cpp | 2 +- 6 files changed, 24 insertions(+), 30 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 9394ef22d..f87871944 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -635,7 +635,7 @@ static void AssumedFill(const std::vector& items, const std::vect bool setLocationsAsHintable = false) { auto ctx = Rando::Context::GetInstance(); if (items.size() > allowedLocations.size()) { - printf("\x1b[2;2HERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); + SPDLOG_ERROR("ERROR: MORE ITEMS THAN LOCATIONS IN GIVEN LISTS"); SPDLOG_DEBUG("Items:\n"); // NOLINTNEXTLINE(clang-diagnostic-unused-variable) for (const RandomizerGet item : items) { @@ -984,9 +984,9 @@ void VanillaFill() { } //If necessary, handle ER stuff if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { - printf("\x1b[7;10HShuffling Entrances..."); + SPDLOG_INFO("Shuffling Entrances..."); ctx->GetEntranceShuffler()->ShuffleAllEntrances(); - printf("\x1b[7;32HDone"); + SPDLOG_INFO("Shuffling Entrances Done"); } // Populate the playthrough for entrances so they are placed in the spoiler log GeneratePlaythrough(); @@ -997,11 +997,6 @@ void VanillaFill() { } void ClearProgress() { - printf("\x1b[7;32H "); // Done - printf("\x1b[8;10H "); // Placing Items...Done - printf("\x1b[9;10H "); // Calculating Playthrough...Done - printf("\x1b[10;10H "); // Creating Hints...Done - printf("\x1b[11;10H "); // Writing Spoiler Log...Done } int Fill() { @@ -1024,13 +1019,13 @@ int Fill() { //can validate the world using deku/hylian shields AddElementsToPool(ItemPool, GetMinVanillaShopItems(32)); //assume worst case shopsanity 4 if (ctx->GetOption(RSK_SHUFFLE_ENTRANCES)) { - printf("\x1b[7;10HShuffling Entrances"); + SPDLOG_INFO("Shuffling Entrances..."); if (ctx->GetEntranceShuffler()->ShuffleAllEntrances() == ENTRANCE_SHUFFLE_FAILURE) { retries++; ClearProgress(); continue; } - printf("\x1b[7;32HDone"); + SPDLOG_INFO("Shuffling Entrances Done"); } SetAreas(); //erase temporary shop items @@ -1142,19 +1137,20 @@ int Fill() { GeneratePlaythrough(); //Successful placement, produced beatable result if(ctx->playthroughBeatable && !placementFailure) { - printf("Done"); - printf("\x1b[9;10HCalculating Playthrough..."); + SPDLOG_INFO("Calculating Playthrough..."); PareDownPlaythrough(); CalculateWotH(); CalculateBarren(); - printf("Done"); + SPDLOG_INFO("Calculating Playthrough Done"); ctx->CreateItemOverrides(); ctx->GetEntranceShuffler()->CreateEntranceOverrides(); + SPDLOG_INFO("Creating Other Hint Texts..."); //funny ganon line Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText(); CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText)); SetGanonText(ganonText); + SPDLOG_INFO("Creating Other Hint Texts Done"); CreateAllHints(); CreateWarpSongTexts(); @@ -1162,7 +1158,7 @@ int Fill() { } //Unsuccessful placement if(retries < 4) { - SPDLOG_DEBUG("\nGOT STUCK. RETRYING...\n"); + SPDLOG_DEBUG("Failed to generate a beatable seed. Retrying..."); Areas::ResetAllLocations(); logic->Reset(); ClearProgress(); diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index c55655de0..ce29c95d0 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -1114,8 +1114,8 @@ void CreateAllHints(){ CreateFrogsHint(); } if (ctx->GetOption(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE)) { - printf("\x1b[10;10HCreating Hints..."); + SPDLOG_INFO("Creating Hints..."); CreateStoneHints(); - printf("Done"); + SPDLOG_INFO("Creating Hints Done"); } } diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index a54f522aa..f1119123c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -468,7 +468,7 @@ void PlaceJunkInExcludedLocation(const RandomizerCheck il) { return; } } - printf("ERROR: No Junk to Place!!!\n"); + SPDLOG_ERROR("ERROR: No Junk to Place!!!"); } static void PlaceVanillaDekuScrubItems() { diff --git a/soh/soh/Enhancements/randomizer/3drando/menu.cpp b/soh/soh/Enhancements/randomizer/3drando/menu.cpp index 752984032..76cf6f1bc 100644 --- a/soh/soh/Enhancements/randomizer/3drando/menu.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/menu.cpp @@ -50,12 +50,10 @@ bool GenerateRandomizer(std::set excludedLocations, std::setGetSettings()->GetSeed(), excludedLocations, enabledTricks); if (ret < 0) { if (ret == -1) { // Failed to generate after 5 tries - printf("\n\nFailed to generate after 5 tries.\nPress B to go back to the menu.\nA different seed might be " - "successful."); - SPDLOG_DEBUG("\nRANDOMIZATION FAILED COMPLETELY. PLZ FIX\n");//RANDOTODO print seed for reproduction purposes + SPDLOG_ERROR("Failed to generate after 5 tries."); return false; } else { - printf("\n\nError %d with fill.\nPress Select to exit or B to go back to the menu.\n", ret); + SPDLOG_ERROR("Error {} with fill.", ret); return false; } } diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 7aef15aa5..d29b6e8a6 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -69,18 +69,18 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations, if (true) { //TODO: Handle different types of file output (i.e. Spoiler Log, Plando Template, Patch Files, Race Files, etc.) // write logs - printf("\x1b[11;10HWriting Spoiler Log..."); + SPDLOG_INFO("Writing Spoiler Log..."); if (SpoilerLog_Write()) { - printf("Done"); + SPDLOG_INFO("Writing Spoiler Log Done"); } else { - printf("Failed"); + SPDLOG_ERROR("Writing Spoiler Log Failed"); } #ifdef ENABLE_DEBUG - printf("\x1b[11;10HWriting Placement Log..."); + SPDLOG_INFO("Writing Placement Log..."); if (PlacementLog_Write()) { - printf("Done\n"); + SPDLOG_INFO("Writing Placement Log Done"); } else { - printf("Failed\n"); + SPDLOG_ERROR("Writing Placement Log Failed"); } #endif } @@ -93,7 +93,7 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations, // used for generating a lot of seeds at once int Playthrough_Repeat(std::set excludedLocations, std::set enabledTricks, int count /*= 1*/) { - printf("\x1b[0;0HGENERATING %d SEEDS", count); + SPDLOG_INFO("GENERATING {} SEEDS", count); auto ctx = Rando::Context::GetInstance(); uint32_t repeatedSeed = 0; for (int i = 0; i < count; i++) { @@ -103,7 +103,7 @@ int Playthrough_Repeat(std::set excludedLocations, std::setGetSettings()->GetSeed(), excludedLocations, enabledTricks); - printf("\x1b[15;15HSeeds Generated: %d\n", i + 1); + SPDLOG_INFO("Seeds Generated: {}", i + 1); } return 1; diff --git a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp index ba63e4641..3fdf56b60 100644 --- a/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/spoiler_log.cpp @@ -260,7 +260,7 @@ void WriteIngameSpoilerLog() { } } if (spoilerOutOfSpace || playthroughItemNotFound) { - printf("Error! "); + SPDLOG_ERROR("In-game spoiler log is out of space, playthrough data will not be written"); } } }