From 328ff0e8c4bfd6d1ba378fcd73b5498f6ffa5cec Mon Sep 17 00:00:00 2001 From: Dakota Brown Date: Sun, 6 Nov 2022 14:07:58 -0700 Subject: [PATCH 1/7] Added Chests of Agony (#1885) --- soh/soh/GameMenuBar.cpp | 22 ++++++++++++++----- soh/soh/UIWidgets.cpp | 5 ++++- soh/soh/UIWidgets.hpp | 2 +- soh/src/overlays/actors/ovl_En_Box/z_en_box.c | 8 ++++--- 4 files changed, 27 insertions(+), 10 deletions(-) diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index 0a9e4d1ce..1220c9aed 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -147,6 +147,8 @@ namespace GameMenuBar { CVar_SetS32("gFastChests", 0); // Chest size & texture matches contents CVar_SetS32("gChestSizeAndTextureMatchesContents", 0); + // Chest size & texture matches contents only with agony + CVar_SetS32("gChestSizeDependsStoneOfAgony", 0); // Fast Drops CVar_SetS32("gFastDrops", 0); // Better Owl @@ -776,7 +778,6 @@ namespace GameMenuBar { UIWidgets::Tooltip("Kick open every chest"); UIWidgets::PaddedText("Chest size & texture matches contents", true, false); const char* chestSizeAndTextureMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only"}; - UIWidgets::EnhancementCombobox("gChestSizeAndTextureMatchesContents", chestSizeAndTextureMatchesContentsOptions, 4, 0); UIWidgets::Tooltip( "Chest sizes and textures are changed to help identify the item inside.\n" " - Major items: Large gold chests\n" @@ -786,6 +787,15 @@ namespace GameMenuBar { " - Boss keys: Vanilla size and texture\n" " - Skulltula Tokens: Small skulltula chest\n" ); + if (UIWidgets::EnhancementCombobox("gChestSizeAndTextureMatchesContents", chestSizeAndTextureMatchesContentsOptions, 4, 0)) { + if (CVar_GetS32("gChestSizeAndTextureMatchesContents", 0) == 0) { + CVar_SetS32("gChestSizeDependsStoneOfAgony", 0); + } + } + if (CVar_GetS32("gChestSizeAndTextureMatchesContents", 0) > 0) { + UIWidgets::PaddedEnhancementCheckbox("Chests of Agony", "gChestSizeDependsStoneOfAgony", true, false); + UIWidgets::Tooltip("Only change the size/texture of chests if you have the Stone of Agony."); + } UIWidgets::PaddedEnhancementCheckbox("Skip Pickup Messages", "gFastDrops", true, false); UIWidgets::Tooltip("Skip pickup messages for new consumable items and bottle swipes"); UIWidgets::PaddedEnhancementCheckbox("Ask to Equip New Items", "gAskToEquip", true, false); @@ -1289,11 +1299,13 @@ namespace GameMenuBar { } UIWidgets::EnhancementCheckbox("Disable LOD", "gDisableLOD"); UIWidgets::Tooltip("Turns off the Level of Detail setting, making models use their higher-poly variants at any distance"); - UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false); + if (UIWidgets::PaddedEnhancementCheckbox("Disable Draw Distance", "gDisableDrawDistance", true, false)) { + if (CVar_GetS32("gDisableDrawDistance", 0) == 0) { + CVar_SetS32("gDisableKokiriDrawDistance", 0); + } + } UIWidgets::Tooltip("Turns off the objects draw distance, making objects being visible from a longer range"); - if (CVar_GetS32("gDisableDrawDistance", 0) == 0) { - CVar_SetS32("gDisableKokiriDrawDistance", 0); - } else if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { + if (CVar_GetS32("gDisableDrawDistance", 0) == 1) { UIWidgets::PaddedEnhancementCheckbox("Kokiri Draw Distance", "gDisableKokiriDrawDistance", true, false); UIWidgets::Tooltip("The Kokiri are mystical beings that fade into view when approached\nEnabling this will remove their draw distance"); } diff --git a/soh/soh/UIWidgets.cpp b/soh/soh/UIWidgets.cpp index 93f67e5b8..c394b0a2b 100644 --- a/soh/soh/UIWidgets.cpp +++ b/soh/soh/UIWidgets.cpp @@ -227,7 +227,8 @@ namespace UIWidgets { } } - void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue) { + bool EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue) { + bool changed = false; if (FirstTimeValue <= 0) { FirstTimeValue = 0; } @@ -240,12 +241,14 @@ namespace UIWidgets { if (ImGui::Selectable(ComboArray[i], i == selected)) { CVar_SetS32(name, i); selected = i; + changed = true; SohImGui::RequestCvarSaveOnNextTick(); } } } ImGui::EndCombo(); } + return changed; } void PaddedText(const char* text, bool padTop, bool padBottom) { diff --git a/soh/soh/UIWidgets.hpp b/soh/soh/UIWidgets.hpp index fa25c727e..015761aa2 100644 --- a/soh/soh/UIWidgets.hpp +++ b/soh/soh/UIWidgets.hpp @@ -36,7 +36,7 @@ namespace UIWidgets { bool EnhancementCheckbox(const char* text, const char* cvarName, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross); bool PaddedEnhancementCheckbox(const char* text, const char* cvarName, bool padTop = true, bool padBottom = true, bool disabled = false, const char* disabledTooltipText = "", CheckboxGraphics disabledGraphic = CheckboxGraphics::Cross); void EnhancementCombo(const std::string& name, const char* cvarName, const std::vector& items, int defaultValue = 0); - void EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); + bool EnhancementCombobox(const char* name, const char* ComboArray[], size_t arraySize, uint8_t FirstTimeValue); void PaddedText(const char* text, bool padTop = true, bool padBottom = true); void EnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false); void PaddedEnhancementSliderInt(const char* text, const char* id, const char* cvarName, int min, int max, const char* format, int defaultValue = 0, bool PlusMinusButton = false, bool padTop = true, bool padBottom = true); diff --git a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c index b81313878..734f3af7e 100644 --- a/soh/src/overlays/actors/ovl_En_Box/z_en_box.c +++ b/soh/src/overlays/actors/ovl_En_Box/z_en_box.c @@ -619,9 +619,11 @@ void EnBox_Update(Actor* thisx, PlayState* play) { void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { EnBox_CreateExtraChestTextures(); int cvar = CVar_GetS32("gChestSizeAndTextureMatchesContents", 0); + int agonyCVar = CVar_GetS32("gChestSizeDependsStoneOfAgony", 0); + int stoneCheck = CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY); GetItemCategory getItemCategory; - if (play->sceneNum != SCENE_TAKARAYA && cvar > 0) { + if (play->sceneNum != SCENE_TAKARAYA && cvar > 0 && ((agonyCVar > 0 && stoneCheck) | agonyCVar == 0)) { getItemCategory = this->getItemEntry.getItemCategory; // If they don't have bombchu's yet consider the bombchu item major if (this->getItemEntry.gid == GID_BOMBCHU && INV_CONTENT(ITEM_BOMBCHU) != ITEM_BOMBCHU) { @@ -637,7 +639,7 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { } } - if (play->sceneNum != SCENE_TAKARAYA && (cvar == 1 || cvar == 3)) { + if (play->sceneNum != SCENE_TAKARAYA && (cvar == 1 || cvar == 3) && ((agonyCVar > 0 && stoneCheck) | agonyCVar == 0)) { switch (getItemCategory) { case ITEM_CATEGORY_JUNK: case ITEM_CATEGORY_SMALL_KEY: @@ -665,7 +667,7 @@ void EnBox_UpdateSizeAndTexture(EnBox* this, PlayState* play) { } } - if (play->sceneNum != SCENE_TAKARAYA && (cvar == 1 || cvar == 2)) { + if (play->sceneNum != SCENE_TAKARAYA && (cvar == 1 || cvar == 2) && ((agonyCVar > 0 && stoneCheck) | agonyCVar == 0)) { switch (getItemCategory) { case ITEM_CATEGORY_MAJOR: this->boxBodyDL = gGoldTreasureChestChestFrontDL; From 8d57ef4bede8b3ad5dd1d170e439cb8291e33e5d Mon Sep 17 00:00:00 2001 From: RaelCappra Date: Mon, 7 Nov 2022 05:02:42 -0300 Subject: [PATCH 2/7] Restore QPA glitched damage (#1789) --- soh/src/overlays/actors/ovl_player_actor/z_player.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) 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 c68113f75..0eabd2244 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -3597,7 +3597,12 @@ void func_80837948(PlayState* play, Player* this, s32 arg2) { } if ((arg2 >= 16) && (arg2 < 20)) { - flags = D_80854488[temp][1]; + if (CVar_GetS32("gRestoreQPA", 1) && temp == -1) { + flags = 0x16171617; + } + else { + flags = D_80854488[temp][1]; + } } else { flags = D_80854488[temp][0]; } From e17040751761ab3e3a60ecefa32d25ac88e96499 Mon Sep 17 00:00:00 2001 From: lilDavid <1337lilDavid@gmail.com> Date: Mon, 7 Nov 2022 02:05:56 -0600 Subject: [PATCH 3/7] Enhancements for equipping magic arrows (#1022) Skip Magic Arrow Equip Animation, Equip Multiple Arrows at Once --- soh/soh/GameMenuBar.cpp | 13 +++++ .../actors/ovl_player_actor/z_player.c | 12 +++-- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 50 ++++++++++++++----- 3 files changed, 60 insertions(+), 15 deletions(-) diff --git a/soh/soh/GameMenuBar.cpp b/soh/soh/GameMenuBar.cpp index 1220c9aed..1089f147c 100644 --- a/soh/soh/GameMenuBar.cpp +++ b/soh/soh/GameMenuBar.cpp @@ -165,6 +165,11 @@ namespace GameMenuBar { CVar_SetS32("gMaskSelect", 0); // Remember Save Location CVar_SetS32("gRememberSaveLocation", 0); + // Skip Magic Arrow Equip Animation + CVar_SetS32("gSkipArrowAnimation", 0); + + // Equip arrows on multiple slots + CVar_SetS32("gSeparateArrows", 0); // Damage Multiplier (0 to 8) CVar_SetS32("gDamageMul", 0); @@ -428,6 +433,11 @@ namespace GameMenuBar { CVar_SetS32("gGoronPot", 1); // Always Win Dampe Digging CVar_SetS32("gDampeWin", 1); + // Skip Magic Arrow Equip Animation + CVar_SetS32("gSkipArrowAnimation", 1); + + // Equip arrows on multiple slots + CVar_SetS32("gSeparateArrows", 1); // Disable Navi Call Audio CVar_SetS32("gDisableNaviCallAudio", 1); @@ -814,6 +824,7 @@ namespace GameMenuBar { UIWidgets::PaddedEnhancementCheckbox("Remember Save Location", "gRememberSaveLocation", true, false); UIWidgets::Tooltip("When loading a save, places Link at the last entrance he went through.\n" "This doesn't work if the save was made in a grotto."); + UIWidgets::PaddedEnhancementCheckbox("Skip Magic Arrow Equip Animation", "gSkipArrowAnimation", true, false); UIWidgets::PaddedEnhancementCheckbox("Skip save confirmation", "gSkipSaveConfirmation", true, false); UIWidgets::Tooltip("Skip the \"Game saved.\" confirmation screen"); ImGui::EndMenu(); @@ -837,6 +848,8 @@ namespace GameMenuBar { UIWidgets::Tooltip("After completing the mask trading sub-quest, press A and any direction on the mask slot to change masks"); UIWidgets::PaddedEnhancementCheckbox("Nuts explode bombs", "gNutsExplodeBombs", true, false); UIWidgets::Tooltip("Makes nuts explode bombs, similar to how they interact with bombchus. This does not affect bombflowers."); + UIWidgets::PaddedEnhancementCheckbox("Equip Multiple Arrows at Once", "gSeparateArrows", true, false); + UIWidgets::Tooltip("Allow the bow and magic arrows to be equipped at the same time on different slots"); ImGui::EndMenu(); } 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 0eabd2244..7fe844aa3 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -127,8 +127,8 @@ s32 func_80834A2C(Player* this, PlayState* play); s32 func_80834B5C(Player* this, PlayState* play); s32 func_80834C74(Player* this, PlayState* play); s32 func_8083501C(Player* this, PlayState* play); -s32 func_808351D4(Player* this, PlayState* play); -s32 func_808353D8(Player* this, PlayState* play); +s32 func_808351D4(Player* this, PlayState* play); // Arrow nocked +s32 func_808353D8(Player* this, PlayState* play); // Aiming in first person s32 func_80835588(Player* this, PlayState* play); s32 func_808356E8(Player* this, PlayState* play); s32 func_80835800(Player* this, PlayState* play); @@ -2167,6 +2167,7 @@ void func_80834298(Player* this, PlayState* play) { } } +// Determine projectile type for bow or slingshot s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) { if (LINK_IS_ADULT) { *itemPtr = ITEM_BOW; @@ -2189,6 +2190,7 @@ s32 func_80834380(PlayState* play, Player* this, s32* itemPtr, s32* typePtr) { } } +// The player has pressed the bow or hookshot button s32 func_8083442C(Player* this, PlayState* play) { s32 item; s32 arrowType; @@ -2502,6 +2504,7 @@ s32 func_8083501C(Player* this, PlayState* play) { return 1; } +// Fire the projectile s32 func_808350A4(PlayState* play, Player* this) { s32 item; s32 arrowType; @@ -3012,7 +3015,10 @@ void func_80835F44(PlayState* play, Player* this, s32 item) { if ((this->heldItemActionParam >= 0) && (Player_ActionToMagicSpell(this, actionParam) < 0) && (item != this->heldItemId) && (D_80854164[gPlayerModelTypes[this->modelGroup][PLAYER_MODELGROUPENTRY_ANIM]][nextAnimType] != - PLAYER_D_808540F4_0)) { + PLAYER_D_808540F4_0) && + (!CVar_GetS32("gSeparateArrows", 0) || + actionParam < PLAYER_AP_BOW || actionParam > PLAYER_AP_BOW_0E || + this->heldItemActionParam < PLAYER_AP_BOW || this->heldItemActionParam > PLAYER_AP_BOW_0E)) { this->heldItemId = item; this->stateFlags1 |= PLAYER_STATE1_8; } else { 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 4dd11dcd1..80c816877 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 @@ -577,18 +577,22 @@ void KaleidoScope_SetupItemEquip(PlayState* play, u16 item, u16 slot, s16 animX, sEquipMoveTimer = 10; if ((pauseCtx->equipTargetItem == ITEM_ARROW_FIRE) || (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) || (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT)) { - u16 index = 0; - if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) { - index = 1; + if (CVar_GetS32("gSkipArrowAnimation", 0)) { + Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else { + u16 index = 0; + if (pauseCtx->equipTargetItem == ITEM_ARROW_ICE) { + index = 1; + } + if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { + index = 2; + } + Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + pauseCtx->equipTargetItem = 0xBF + index; + sEquipState = 0; + pauseCtx->equipAnimAlpha = 0; + sEquipMoveTimer = 6; } - if (pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { - index = 2; - } - Audio_PlaySoundGeneral(NA_SE_SY_SET_FIRE_ARROW + index, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); - pauseCtx->equipTargetItem = 0xBF + index; - sEquipState = 0; - pauseCtx->equipAnimAlpha = 0; - sEquipMoveTimer = 6; } else { Audio_PlaySoundGeneral(NA_SE_SY_DECIDE, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); } @@ -784,7 +788,9 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { if (D_8082A488 == 0) { pauseCtx->equipTargetItem -= 0xBF - ITEM_BOW_ARROW_FIRE; - pauseCtx->equipTargetSlot = SLOT_BOW; + if (!CVar_GetS32("gSeparateArrows", 0)) { + pauseCtx->equipTargetSlot = SLOT_BOW; + } sEquipMoveTimer = 6; WREG(90) = 320; WREG(87) = WREG(91); @@ -853,6 +859,26 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { osSyncPrintf("\n================================\n"); + // Skipping the arrow animation: need to change the item's type and + // slot when it hits the button since it didn't get set earlier + if (pauseCtx->equipTargetItem == ITEM_ARROW_FIRE || pauseCtx->equipTargetItem == ITEM_ARROW_ICE || + pauseCtx->equipTargetItem == ITEM_ARROW_LIGHT) { + switch (pauseCtx->equipTargetItem) { + case ITEM_ARROW_FIRE: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_FIRE; + break; + case ITEM_ARROW_ICE: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_ICE; + break; + case ITEM_ARROW_LIGHT: + pauseCtx->equipTargetItem = ITEM_BOW_ARROW_LIGHT; + break; + } + if (!CVar_GetS32("gSeparateArrows", 0)) { + pauseCtx->equipTargetSlot = SLOT_BOW; + } + } + // If the item is on another button already, swap the two uint16_t targetButtonIndex = pauseCtx->equipTargetCBtn + 1; for (uint16_t otherSlotIndex = 0; otherSlotIndex < ARRAY_COUNT(gSaveContext.equips.cButtonSlots); From 92b1730237e29a0e722404c6bd86e5675dc929c7 Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 7 Nov 2022 13:14:24 -0600 Subject: [PATCH 4/7] [#1931] Fix issue with ZF Gossip stones (#1933) --- soh/soh/Enhancements/randomizer/randomizer.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index fac20164d..8fad01f21 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2209,9 +2209,11 @@ RandomizerCheckObject Randomizer::GetCheckObjectFromActor(s16 actorId, s16 scene case 15362: case 14594: specialRc = RC_JABU_GOSSIP_STONE; + break; case 14849: case 14337: specialRc = RC_FAIRY_GOSSIP_STONE; + break; } break; case SCENE_DDAN: From 2c6c1d2e46c0ae3323bdbbba4701d1dc370d3caf Mon Sep 17 00:00:00 2001 From: David Chavez Date: Mon, 7 Nov 2022 20:34:03 +0100 Subject: [PATCH 5/7] [CI] Add Github build pipeline (#1688) --- .github/workflows/apt-deps.txt | 1 + .github/workflows/generate-builds.yml | 246 ++++++++++++++++++++++++++ .github/workflows/gtar | 2 + .github/workflows/macports-deps.txt | 1 + README.md | 7 + 5 files changed, 257 insertions(+) create mode 100644 .github/workflows/apt-deps.txt create mode 100644 .github/workflows/generate-builds.yml create mode 100644 .github/workflows/gtar create mode 100644 .github/workflows/macports-deps.txt diff --git a/.github/workflows/apt-deps.txt b/.github/workflows/apt-deps.txt new file mode 100644 index 000000000..2a12d368c --- /dev/null +++ b/.github/workflows/apt-deps.txt @@ -0,0 +1 @@ +libsdl2-dev libsdl2-net-dev libpng-dev libglew-dev ninja-build diff --git a/.github/workflows/generate-builds.yml b/.github/workflows/generate-builds.yml new file mode 100644 index 000000000..e20fd3c09 --- /dev/null +++ b/.github/workflows/generate-builds.yml @@ -0,0 +1,246 @@ +name: generate-builds +on: + push: + pull_request: +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true +jobs: + extract-assets: + runs-on: [ self-hosted, asset-builder ] + steps: + - uses: actions/checkout@v2 + - name: Extract assets + run: | + cp ../../../ZELOOTD.z64 OTRExporter/baserom_non_mq.z64 + cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release + cmake --build build-cmake --target ExtractAssets --config Release + zip -r assets.zip soh/assets + - uses: actions/upload-artifact@v3 + with: + name: assets + path: assets.zip + retention-days: 1 + build-macos: + needs: extract-assets + runs-on: macos-12 + steps: + - uses: actions/checkout@v2 + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ runner.os }}-ccache + - name: Install gtar wrapper + run: | + sudo mv /usr/local/bin/gtar /usr/local/bin/gtar.orig + sudo cp .github/workflows//gtar /usr/local/bin/gtar + sudo chmod +x /usr/local/bin/gtar + - name: Cache MacPorts + id: cache-macports + uses: actions/cache@v2 + with: + path: /opt/local/ + key: ${{ runner.os }}-macports-${{ hashFiles('.github/workflows/macports-deps.txt') }} + restore-keys: | + ${{ runner.os }}-macports- + - name: Install MacPorts (if necessary) + run: | + if [ -d /opt/local/ ]; then + echo "MacPorts already installed" + else + wget https://github.com/macports/macports-base/releases/download/v2.7.2/MacPorts-2.7.2-12-Monterey.pkg + sudo installer -pkg ./MacPorts-2.7.2-12-Monterey.pkg -target / + fi + echo "/opt/local/bin:/opt/local/sbin" >> $GITHUB_PATH + - name: Install dependencies + run: | + brew uninstall --ignore-dependencies libpng + sudo port install $(cat .github/workflows/macports-deps.txt) + brew install ninja + - name: Restore assets + uses: actions/download-artifact@v3 + with: + name: assets + - name: Build SoH + run: | + unzip -o assets.zip + + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_OSX_ARCHITECTURES="x86_64;arm64" + cmake --build build-cmake --config Release --parallel 10 + (cd build-cmake && cpack) + + mv _packages/*.dmg SoH.dmg + mv README.md readme.txt + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: soh-mac + path: | + SoH.dmg + readme.txt + build-linux: + needs: extract-assets + runs-on: ubuntu-20.04 + steps: + - uses: actions/checkout@v2 + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y $(cat .github/workflows/apt-deps.txt) + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ runner.os }}-ccache + - name: Install latest SDL + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + wget https://www.libsdl.org/release/SDL2-2.24.1.tar.gz + tar -xzf SDL2-2.24.1.tar.gz + cd SDL2-2.24.1 + ./configure + make -j 10 + sudo make install + - name: Install latest SDL_net + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + wget https://www.libsdl.org/projects/SDL_net/release/SDL2_net-2.2.0.tar.gz + tar -xzf SDL2_net-2.2.0.tar.gz + cd SDL2_net-2.2.0 + ./configure + make -j 10 + sudo make install + - name: Restore assets + uses: actions/download-artifact@v3 + with: + name: assets + - name: Build SoH + run: | + unzip -o assets.zip + + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + cmake --no-warn-unused-cli -H. -Bbuild-cmake -GNinja -DCMAKE_BUILD_TYPE:STRING=Release + cmake --build build-cmake --target OTRGui -j3 + cmake --build build-cmake --config Release -j3 + (cd build-cmake && cpack -G External) + + mv README.md readme.txt + mv build-cmake/*.appimage soh.appimage + env: + CC: gcc-10 + CXX: g++-10 + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: soh-linux + path: | + soh.appimage + readme.txt + build-switch: + needs: extract-assets + runs-on: ubuntu-latest + container: + image: devkitpro/devkita64:latest + steps: + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y ninja-build + - uses: actions/checkout@v2 + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ runner.os }}-switch-ccache + - name: Restore assets + uses: actions/download-artifact@v3 + with: + name: assets + - name: Build SoH + run: | + unzip -o assets.zip + + cmake -H. -Bbuild-switch -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/Switch.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache + cmake --build build-switch --target soh_nro -j3 + + mv build-switch/soh/*.nro soh.nro + mv README.md readme.txt + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: soh-switch + path: | + soh.nro + readme.txt + build-wiiu: + needs: extract-assets + runs-on: ubuntu-latest + container: + image: devkitpro/devkitppc:latest + steps: + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y ninja-build + - uses: actions/checkout@v2 + - name: ccache + uses: hendrikmuhs/ccache-action@v1.2 + with: + key: ${{ runner.os }}-wiiu-ccache + - name: Restore assets + uses: actions/download-artifact@v3 + with: + name: assets + - name: Build SoH + run: | + unzip -o assets.zip + + cmake -H. -Bbuild-wiiu -GNinja -DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/WiiU.cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_C_COMPILER_LAUNCHER=ccache + cmake --build build-wiiu --target soh_wuhb --config Release -j3 + + mv build-wiiu/soh/*.rpx soh.rpx + mv build-wiiu/soh/*.wuhb soh.wuhb + mv README.md readme.txt + env: + DEVKITPRO: /opt/devkitpro + DEVKITPPC: /opt/devkitpro/devkitPPC + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: soh-wiiu + path: | + soh.rpx + soh.wuhb + readme.txt + build-windows: + needs: extract-assets + runs-on: windows-latest + steps: + - name: Install dependencies + run: | + choco install ninja + Remove-Item -Path "C:\ProgramData\Chocolatey\bin\ccache.exe" -Force + - uses: actions/checkout@v2 + - name: ccache + uses: dcvz/ccache-action@27b9f33213c0079872f064f6b6ba0233dfa16ba2 + with: + key: ${{ runner.os }}-ccache + - name: Restore assets + uses: actions/download-artifact@v3 + with: + name: assets + - uses: ilammy/msvc-dev-cmd@v1 + - name: Build SoH + run: | + 7z x assets.zip -aoa + + set $env:PATH="$env:USERPROFILE/.cargo/bin;$env:PATH" + cmake -S . -B build-windows -G Ninja -DCMAKE_MAKE_PROGRAM=ninja -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache + cmake --build build-windows --target OTRGui --config Release --parallel 10 + cmake --build build-windows --config Release --parallel 10 + cd build-windows + cpack -G ZIP + - name: Upload build + uses: actions/upload-artifact@v3 + with: + name: soh-windows + path: _packages/*.zip diff --git a/.github/workflows/gtar b/.github/workflows/gtar new file mode 100644 index 000000000..5814696d1 --- /dev/null +++ b/.github/workflows/gtar @@ -0,0 +1,2 @@ +#!/bin/sh +exec sudo /usr/local/bin/gtar.orig "$@" diff --git a/.github/workflows/macports-deps.txt b/.github/workflows/macports-deps.txt new file mode 100644 index 000000000..02c11cc68 --- /dev/null +++ b/.github/workflows/macports-deps.txt @@ -0,0 +1 @@ +libsdl2 +universal libpng +universal glew +universal diff --git a/README.md b/README.md index d30aa96b6..f591edc23 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,13 @@ Official Discord: https://discord.com/invite/BtBmd55HVH Refer to the [building instructions](BUILDING.md) to compile SoH. +## Getting CI to work on your fork + +The CI works via [Github Actions](https://github.com/features/actions) where we mostly make use of machines hosted by Github; except for the very first step of the CI process called "Extract assets". This steps extracts assets from the game file and generates an "assets" folder in `soh/`. + +To get this step working on your fork, you'll need to add a machine to your own repository as a self-hosted runner via "Settings > Actions > Runners" in your repository settings. If you're on macOS or Linux take a look at `macports-deps.txt` or `apt-deps.txt` to see the dependencies expected to be on your machine. For Windows, deps get installed as part of the CI process. To setup your runner as a service read the docs [here](https://docs.github.com/en/actions/hosting-your-own-runners/configuring-the-self-hosted-runner-application-as-a-service?platform=linux). + + ## Troubleshooting The Exporter - Confirm that you have an `/assets` folder filled with XMLs in the same directory as OTRGui.exe - Confirm that `zapd.exe` exists in the `/assets/extractor` folder From f050ba9ff76ae6cd670f0debc27f713aa404702e Mon Sep 17 00:00:00 2001 From: PurpleHato Date: Mon, 7 Nov 2022 22:41:33 +0100 Subject: [PATCH 6/7] TWEAK: Fix corrupted characters on French gossip hint (#1935) --- soh/soh/Enhancements/randomizer/3drando/hint_list.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 6d1f2063f..040835979 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -1532,7 +1532,7 @@ void HintTable_Init() { hintTable[JUNK02] = HintText::Junk({ // obscure text Text{ "They say you must read the names of \"Special Deal\" shop items carefully.", - /*french*/ "Selon moi, les « Offres spéciales » sont parfois trompeuses... Lisez attentivement!", + /*french*/ "Selon moi, les \"Offres spéciales\" sont parfois trompeuses... Lisez les attentivement!", /*spanish*/ "Según dicen, se debería prestar atención a los nombres de las ofertas especiales." }, }); @@ -1956,7 +1956,7 @@ void HintTable_Init() { hintTable[JUNK65] = HintText::Junk({ // obscure text Text{ "They say that the nightly builds may be unstable.", - /*french*/ "Selon moi, les « nightly builds » peuvent être instables.", + /*french*/ "Selon moi, les \"nightly builds\" peuvent être instables.", /*spanish*/ "Según dicen, las últimas nightlies pueden llegar a ser algo inestables." }, }); From 341bc43daf8b327c515c717e87d2a25fcce7266f Mon Sep 17 00:00:00 2001 From: Ralphie Morell Date: Tue, 8 Nov 2022 13:54:51 -0500 Subject: [PATCH 7/7] Rando: Shuffle Merchants (#1720) --- .../custom-message/CustomMessageTypes.h | 3 + .../Enhancements/debugger/debugSaveEditor.h | 3 + .../randomizer/3drando/settings.cpp | 1 + .../Enhancements/randomizer/randomizer.cpp | 82 +++++++++++++++++++ .../Enhancements/randomizer/randomizerTypes.h | 1 + .../Enhancements/randomizer/randomizer_inf.h | 3 + soh/soh/OTRGlobals.cpp | 5 ++ soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c | 28 ++++++- soh/src/overlays/actors/ovl_En_Js/z_en_js.c | 8 ++ 9 files changed, 133 insertions(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h index 991a44b19..8856d7e5a 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageTypes.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageTypes.h @@ -21,6 +21,9 @@ typedef enum { TEXT_PURPLE_RUPEE = 0xF1, TEXT_HUGE_RUPEE = 0xF2, TEXT_BEAN_SALESMAN = 0x405E, + TEXT_MEDIGORON = 0x304C, + TEXT_CARPET_SALESMAN_1 = 0x6077, + TEXT_CARPET_SALESMAN_2 = 0x6078, TEXT_SCRUB_RANDOM = 0x9000, TEXT_SCRUB_RANDOM_FREE = 0x9001, TEXT_SHOP_ITEM_RANDOM = 0x9100, diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h index 8f2d7b454..97b2a5062 100644 --- a/soh/soh/Enhancements/debugger/debugSaveEditor.h +++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h @@ -485,5 +485,8 @@ const std::vector flagTables = { { RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_6, "SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_6" }, { RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7, "SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7" }, { RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8, "SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8" }, + + { RAND_INF_MERCHANTS_MEDIGORON, "RAND_INF_MERCHANTS_MEDIGORON" }, + { RAND_INF_MERCHANTS_CARPET_SALESMAN, "RAND_INF_MERCHANTS_CARPET_SALESMAN" }, } }, }; \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index 4c199b929..78b2e03d5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2579,6 +2579,7 @@ namespace Settings { ShuffleAdultTradeQuest.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_ADULT_TRADE]); ShuffleMagicBeans.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_MAGIC_BEANS]); + ShuffleMerchants.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_MERCHANTS]); // the checkbox works because 0 is "Off" and 1 is "Fairy Ocarina" StartingOcarina.SetSelectedIndex(cvarSettings[RSK_STARTING_OCARINA]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8fad01f21..f9dfb1c77 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -203,6 +203,7 @@ std::unordered_map SpoilerfileSettingNameToEn { "Shuffle Settings:Tokensanity", RSK_SHUFFLE_TOKENS }, { "Shuffle Settings:Shuffle Adult Trade", RSK_SHUFFLE_ADULT_TRADE }, { "Shuffle Settings:Shuffle Magic Beans", RSK_SHUFFLE_MAGIC_BEANS }, + { "Shuffle Settings:Shuffle Merchants", RSK_SHUFFLE_MERCHANTS }, { "Start with Deku Shield", RSK_STARTING_DEKU_SHIELD }, { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, @@ -453,6 +454,61 @@ void Randomizer::LoadMerchantMessages(const char* spoilerFileName) { "%gobjet mystérieux%w pour 60 Rubis?\x1B&%gOui&Non%w", }); + + //Setup for merchant text boxes + //Medigoron + //RANDOTODO: Implement obscure/ambiguous hints + CustomMessageManager::Instance->CreateMessage( + Randomizer::merchantMessageTableID, TEXT_MEDIGORON, + { + TEXTBOX_TYPE_BLACK, + TEXTBOX_POS_BOTTOM, + "How about buying %r&{{item}}%w for %g200 rupees%w?\x1B&%gYes&No%w", + "Wie wäre es mit %r&{{item}}%w für %g200 Rubine?%w\x1B&%gJa!&Nein!%w", + "Veux-tu acheter %r&{{item}}%w pour %g200 rubis?%w\x1B&%gOui&Non&w" + }); + + //Carpet Salesman + //RANDOTODO: Implement obscure/ambiguous hints + std::vector cgBoxTwoText; + if (Randomizer::GetRandoSettingValue(RSK_SHUFFLE_MERCHANTS) == 2) { //If merchant hints are clear... + cgBoxTwoText = { + "!%w&It's real, I promise!&A lonely man such as myself&wouldn't %rlie%w to you, hmm?^", + "!%w&Ich kann versichern es ist ein&aufrichtiges Angebot!^Ein einsamer Mann wie ich würde dich&doch nicht %ranlügen%w, oder?^", + "!%w&C'est vrai! J'te jure!&Un gars comme moi ne te %rmentirai%w pas&tu ne crois pas?^" + }; + } else { + cgBoxTwoText = { + "!%w&I won't tell you what it is until I see&the money...^", + "!%w&Erst kommt das Geld, dann die Ware...^", + "!%w&Je ne te dirai pas ce que c'est avant&d'être payé rubis sur l'ongle...^" + }; + } + CustomMessageManager::Instance->CreateMessage( + Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_1, + { + TEXTBOX_TYPE_BLACK, + TEXTBOX_POS_BOTTOM, + "Welcome!^I am selling stuff, strange and rare, &from all over the world to everybody.&Today's special is...^%r{{item}}" + cgBoxTwoText[0] + + "How about %g200 Rupees?%w\x1B&&%gYes&No%w", + "Sei gegrüßt!^Ich verkaufe allerlei Kuriorisäten.&Stets sonderliche und seltene Ware&aus aller Welt für jedermann.&Das heutige Angebot bleibt...^%r{{item}}" + + cgBoxTwoText[1] + "Wie wäre es mit %g200 Rubinen?%w\x1B&&%gJa!&Nein!%w", + "Bienvenue!^Je vends des trucs étranges et rares,&de partout dans le monde et à tout le&monde! L'objet du jour est...^%r{{item}}" + + cgBoxTwoText[2] + "Alors, marché conclu pour %g200 rubis?%w\x1B&&%gOui&Non%w" + } + ); + + CustomMessageManager::Instance->CreateMessage( + Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_2, + { + TEXTBOX_TYPE_BLACK, + TEXTBOX_POS_TOP, + "Finally! Now I can go back to being &an %rarms dealer!%w", + "Endlich! Schon bald kann ich wieder &%rKrabbelminen-Händler%w sein!", + "Squalala! Je vais enfin pouvoir &%rprendre des vacances!%w" + } + ); + // Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are // prompted buy/don't buy CustomMessageManager::Instance->CreateMessage( @@ -654,6 +710,15 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = 1; } break; + case RSK_SHUFFLE_MERCHANTS: + if(it.value() == "Off") { + gSaveContext.randoSettings[index].value = 0; + } else if (it.value() == "On (No Hints)") { + gSaveContext.randoSettings[index].value = 1; + } else if (it.value() == "On (With Hints)") { + gSaveContext.randoSettings[index].value = 2; + } + break; // Uses Ammo Drops option for now. "Off" not yet implemented case RSK_ENABLE_BOMBCHU_DROPS: if (it.value() == "On") { @@ -2145,6 +2210,9 @@ std::map rcToRandomizerInf = { { RC_MARKET_BOMBCHU_SHOP_ITEM_6, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_6 }, { RC_MARKET_BOMBCHU_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7 }, { RC_MARKET_BOMBCHU_SHOP_ITEM_8, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8 }, + { RC_GC_MEDIGORON, RAND_INF_MERCHANTS_MEDIGORON }, + { RC_WASTELAND_BOMBCHU_SALESMAN, RAND_INF_MERCHANTS_CARPET_SALESMAN }, + }; RandomizerCheckObject Randomizer::GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams = 0x00) { @@ -2422,6 +2490,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SHUFFLE_COWS] = CVar_GetS32("gRandomizeShuffleCows", 0); cvarSettings[RSK_SHUFFLE_ADULT_TRADE] = CVar_GetS32("gRandomizeShuffleAdultTrade", 0); cvarSettings[RSK_SHUFFLE_MAGIC_BEANS] = CVar_GetS32("gRandomizeShuffleBeans", 0); + cvarSettings[RSK_SHUFFLE_MERCHANTS] = CVar_GetS32("gRandomizeShuffleMerchants", 0); cvarSettings[RSK_ENABLE_BOMBCHU_DROPS] = CVar_GetS32("gRandomizeEnableBombchuDrops", 0); cvarSettings[RSK_BOMBCHUS_IN_LOGIC] = CVar_GetS32("gRandomizeBombchusInLogic", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); @@ -3052,6 +3121,19 @@ void DrawRandoEditor(bool& open) { UIWidgets::PaddedSeparator(); + // Shuffle Merchants + ImGui::Text(Settings::ShuffleMerchants.GetName().c_str()); + UIWidgets::InsertHelpHoverText( + "Enabling this adds a Giant's Knife and a pack of Bombchus to the item pool " + "and changes both Medigoron and the Haunted Wasteland Carpet Salesman to sell " + "a random item once at the price of 200 rupees.\n\n" + "On (no hints) - Salesmen will be included but won't tell you what you'll get.\n" + "On (with hints) - Salesmen will be included and you'll know what you're buying." + ); + UIWidgets::EnhancementCombobox("gRandomizeShuffleMerchants", randoShuffleMerchants, 3, 0); + + UIWidgets::PaddedSeparator(); + // Shuffle Frog Song Rupees UIWidgets::EnhancementCheckbox(Settings::ShuffleFrogSongRupees.GetName().c_str(), "gRandomizeShuffleFrogSongRupees"); UIWidgets::InsertHelpHoverText( diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index c516a92d9..4ffa6313c 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -1029,6 +1029,7 @@ typedef enum { RSK_SKULLS_SUNS_SONG, RSK_SHUFFLE_ADULT_TRADE, RSK_SHUFFLE_MAGIC_BEANS, + RSK_SHUFFLE_MERCHANTS, RSK_BLUE_FIRE_ARROWS, RSK_SUNLIGHT_ARROWS, RSK_ENABLE_BOMBCHU_DROPS, diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h index 5cc3304b9..e764f372b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_inf.h +++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h @@ -140,6 +140,9 @@ typedef enum { RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_7, RAND_INF_SHOP_ITEMS_MARKET_BOMBCHU_SHOP_ITEM_8, + RAND_INF_MERCHANTS_CARPET_SALESMAN, + RAND_INF_MERCHANTS_MEDIGORON, + // If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16) RAND_INF_MAX, diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 25ebf9847..352a46f7d 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1983,6 +1983,11 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId); } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MAGIC_BEANS) && textId == TEXT_BEAN_SALESMAN) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN); + } else if (Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) && (textId == TEXT_MEDIGORON || + (textId == TEXT_CARPET_SALESMAN_1 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) || + (textId == TEXT_CARPET_SALESMAN_2 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)))) { + RandomizerInf randoInf = (RandomizerInf)(textId == TEXT_MEDIGORON ? RAND_INF_MERCHANTS_MEDIGORON : RAND_INF_MERCHANTS_CARPET_SALESMAN); + messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(randoInf, textId, Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) != 2); } else if (Randomizer_GetSettingValue(RSK_BOMBCHUS_IN_LOGIC) && (textId == TEXT_BUY_BOMBCHU_10_DESC || textId == TEXT_BUY_BOMBCHU_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId); diff --git a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c index b6b8b9acb..8a63a70f2 100644 --- a/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c +++ b/soh/src/overlays/actors/ovl_En_Gm/z_en_gm.c @@ -97,6 +97,8 @@ s32 func_80A3D7C8(void) { return 1; } else if (gBitFlags[3] & gSaveContext.inventory.equipment) { return 2; + } else if ((gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS)) && (gBitFlags[2] & gSaveContext.inventory.equipment)){ + return 1; } else { return 3; } @@ -209,6 +211,11 @@ void func_80A3DC44(EnGm* this, PlayState* play) { return; case 1: gSaveContext.infTable[11] |= 2; + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { + //Resets "Talked to Medigoron" flag in infTable to restore initial conversation state + gSaveContext.infTable[11] &= ~2; + } case 2: this->actionFunc = EnGm_ProcessChoiceIndex; default: @@ -243,8 +250,17 @@ void EnGm_ProcessChoiceIndex(EnGm* this, PlayState* play) { Message_ContinueTextbox(play, 0xC8); this->actionFunc = func_80A3DD7C; } else { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { + GiveItemEntryFromActor(&this->actor, play, + Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE), 415.0f, 10.0f); + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); + gSaveContext.infTable[11] |= 2; + this->actionFunc = func_80A3DF00; + } else { func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); this->actionFunc = func_80A3DF00; + } } break; case 1: // no @@ -260,7 +276,17 @@ void func_80A3DF00(EnGm* this, PlayState* play) { this->actor.parent = NULL; this->actionFunc = func_80A3DF60; } else { - func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON)) { + GiveItemEntryFromActor(&this->actor, play, + Randomizer_GetItemFromKnownCheck(RC_GC_MEDIGORON, GI_SWORD_KNIFE), 415.0f, 10.0f); + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_MEDIGORON); + gSaveContext.infTable[11] |= 2; + } + else { + func_8002F434(&this->actor, play, GI_SWORD_KNIFE, 415.0f, 10.0f); + } + } } diff --git a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c index fd0a277e0..66ae484d4 100644 --- a/soh/src/overlays/actors/ovl_En_Js/z_en_js.c +++ b/soh/src/overlays/actors/ovl_En_Js/z_en_js.c @@ -129,7 +129,15 @@ void func_80A89160(EnJs* this, PlayState* play) { this->actor.parent = NULL; En_Js_SetupAction(this, func_80A8910C); } else { + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_MERCHANTS) && + !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { + GiveItemEntryFromActor(&this->actor, play, + Randomizer_GetItemFromKnownCheck(RC_WASTELAND_BOMBCHU_SALESMAN, GI_BOMBCHUS_10), 90.0f, 10.0f); + Flags_SetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN); + } else { func_8002F434(&this->actor, play, GI_BOMBCHUS_10, 10000.0f, 50.0f); + } + } }