diff options
Diffstat (limited to 'soh/src/code')
| -rw-r--r-- | soh/src/code/code_80097A00.c | 2 | ||||
| -rw-r--r-- | soh/src/code/code_800EC960.c | 53 | ||||
| -rw-r--r-- | soh/src/code/z_actor.c | 16 | ||||
| -rw-r--r-- | soh/src/code/z_draw.c | 24 | ||||
| -rw-r--r-- | soh/src/code/z_en_item00.c | 36 | ||||
| -rw-r--r-- | soh/src/code/z_game_over.c | 22 | ||||
| -rw-r--r-- | soh/src/code/z_kankyo.c | 2 | ||||
| -rw-r--r-- | soh/src/code/z_message_PAL.c | 3 | ||||
| -rw-r--r-- | soh/src/code/z_parameter.c | 243 | ||||
| -rw-r--r-- | soh/src/code/z_play.c | 6 | ||||
| -rw-r--r-- | soh/src/code/z_player_lib.c | 10 | ||||
| -rw-r--r-- | soh/src/code/z_scene_table.c | 8 | ||||
| -rw-r--r-- | soh/src/code/z_sram.c | 510 |
13 files changed, 461 insertions, 474 deletions
diff --git a/soh/src/code/code_80097A00.c b/soh/src/code/code_80097A00.c index f07102b0f..727c199ac 100644 --- a/soh/src/code/code_80097A00.c +++ b/soh/src/code/code_80097A00.c @@ -27,7 +27,7 @@ u16 gUpgradeCapacities[][4] = { { 0, 20, 30, 40 }, // Bomb Bags { 0, 0, 0, 0 }, // Unused (Scale) { 0, 0, 0, 0 }, // Unused (Strength) - { 99, 200, 500, 500 }, // Wallets + { 99, 200, 500, 999 }, // Wallets { 0, 30, 40, 50 }, // Deku Seed Bullet Bags { 0, 10, 20, 30 }, // Deku Stick Upgrades { 0, 20, 30, 40 }, // Deku Nut Upgrades diff --git a/soh/src/code/code_800EC960.c b/soh/src/code/code_800EC960.c index f7d073a8d..f5f1b980e 100644 --- a/soh/src/code/code_800EC960.c +++ b/soh/src/code/code_800EC960.c @@ -1246,6 +1246,7 @@ void Audio_StepFreqLerp(FreqLerp* lerp); void func_800F56A8(void); void Audio_PlayNatureAmbienceSequence(u8 natureAmbienceId); s32 Audio_SetGanonDistVol(u8 targetVol); +void Audio_PlayFanfare_Rando(GetItemEntry getItem); // Right stick as virtual C buttons #define RSTICK_UP 0x100000 @@ -3954,6 +3955,58 @@ void Audio_ResetSfxChannelState(void) { sAudioCodeReverb = 0; } +// Function to play "get-item" fanfares according to the type of item obtained (used in rando) +// Longer fanfares for medallions/stones/songs are behind the Cvar +void Audio_PlayFanfare_Rando(GetItemEntry getItem) { + s32 temp1; + s16 getItemId = getItem.getItemId; + s16 itemId = getItem.itemId; + + if (getItem.modIndex == MOD_NONE) { + if (((itemId >= ITEM_RUPEE_GREEN) && (itemId <= ITEM_RUPEE_GOLD)) || (itemId == ITEM_HEART)) { + Audio_PlaySoundGeneral(NA_SE_SY_GET_BOXITEM, &D_801333D4, 4, &D_801333E0, &D_801333E0, &D_801333E8); + } else { + if (itemId == ITEM_HEART_CONTAINER || + ((itemId == ITEM_HEART_PIECE_2) && ((gSaveContext.inventory.questItems & 0xF0000000) == 0x40000000))) { + temp1 = NA_BGM_HEART_GET | 0x900; + } else { + temp1 = (itemId == ITEM_HEART_PIECE_2) ? NA_BGM_SMALL_ITEM_GET : NA_BGM_ITEM_GET | 0x900; + } + // If we get a skulltula token or the "WINNER" heart, play "get small item" + // Also make sure "WINNER" heart is not the 4th heart piece. + if (itemId == ITEM_SKULL_TOKEN || (getItemId == GI_HEART_PIECE_WIN && itemId == ITEM_HEART_PIECE_2 && + (gSaveContext.inventory.questItems & 0xF0000000) != 0x40000000)) { + temp1 = NA_BGM_SMALL_ITEM_GET | 0x900; + } + // If the setting is toggled on and we get special quest items (longer fanfares): + if (CVar_GetS32("gRandoQuestItemFanfares", 0) != 0) { + // If we get a medallion, play the "get a medallion" fanfare + if ((itemId >= ITEM_MEDALLION_FOREST) && (itemId <= ITEM_MEDALLION_LIGHT)) { + temp1 = NA_BGM_MEDALLION_GET | 0x900; + } + // If it's a Spiritual Stone, play the "get a spiritual stone" fanfare + if ((itemId >= ITEM_KOKIRI_EMERALD) && (itemId <= ITEM_ZORA_SAPPHIRE)) { + temp1 = NA_BGM_SPIRITUAL_STONE | 0x900; + } + // If the item we're getting is a song, play the "learned a song" fanfare + if ((itemId >= ITEM_SONG_MINUET) && (itemId <= ITEM_SONG_STORMS)) { + temp1 = NA_BGM_OCA_FAIRY_GET | 0x900; + } + } + Audio_PlayFanfare(temp1); + } + } else if (getItem.modIndex == MOD_RANDOMIZER) { + if ((itemId >= RG_BOTTLE_WITH_RED_POTION && itemId <= RG_BOTTLE_WITH_BIG_POE) || + (itemId >= RG_DEKU_TREE_MAP && itemId <= RG_GANONS_CASTLE_SMALL_KEY)) { + temp1 = NA_BGM_ITEM_GET | 0x900; + } else { + // Just in case nothing else matches. + temp1 = NA_BGM_ITEM_GET | 0x900; + } + Audio_PlayFanfare(temp1); + } +} + void func_800F3F3C(u8 arg0) { if (gSoundBankMuted[0] != 1) { Audio_StartSeq(SEQ_PLAYER_BGM_SUB, 0, NA_BGM_VARIOUS_SFX); diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index f4fda54a1..1c87ed859 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -4701,6 +4701,20 @@ void Flags_SetInfTable(s32 flag) { gSaveContext.infTable[flag >> 4] |= (1 << (flag & 0xF)); } +/** + * Tests if "randomizerInf" flag is set. + */ +s32 Flags_GetRandomizerInf(RandomizerInf flag) { + return gSaveContext.randomizerInf[flag >> 4] & (1 << (flag & 0xF)); +} + +/** + * Sets "randomizerInf" flag. + */ +void Flags_SetRandomizerInf(RandomizerInf flag) { + gSaveContext.randomizerInf[flag >> 4] |= (1 << (flag & 0xF)); +} + u32 func_80035BFC(GlobalContext* globalCtx, s16 arg1) { u16 retTextId = 0; @@ -6108,7 +6122,7 @@ GetItemEntry GetChestGameRandoGetItem(s8 room, s16 ogDrawId, GlobalContext* glob s16 GetChestGameRandoGiDrawId(s8 room, s16 ogDrawId, GlobalContext* globalCtx) { GetItemEntry randoGetItem = GetChestGameRandoGetItem(room, ogDrawId, globalCtx); - if (randoGetItem.itemId != RG_NONE) { + if (randoGetItem.itemId != ITEM_NONE) { return randoGetItem.gid; } diff --git a/soh/src/code/z_draw.c b/soh/src/code/z_draw.c index 203f3c3c9..7d98c8e2c 100644 --- a/soh/src/code/z_draw.c +++ b/soh/src/code/z_draw.c @@ -395,6 +395,20 @@ void GetItem_Draw(GlobalContext* globalCtx, s16 drawId) { sDrawItemTable[drawId].drawFunc(globalCtx, drawId); } +/** + * Draw "Get Item" Model from a `GetItemEntry` + * Uses the Custom Draw Function if it exists, or just calls `GetItem_Draw` + */ +void GetItemEntry_Draw(GlobalContext* globalCtx, GetItemEntry getItemEntry) { + // RANDOTODO: Make this more flexible for easier toggling of individual item recolors in the future. + if (getItemEntry.drawFunc != NULL && + (CVar_GetS32("gRandoMatchKeyColors", 0) || getItemEntry.getItemId == RG_DOUBLE_DEFENSE)) { + getItemEntry.drawFunc(globalCtx, &getItemEntry); + } else { + GetItem_Draw(globalCtx, getItemEntry.gid); + } +} + // All remaining functions in this file are draw functions referenced in the table and called by the function above /* 0x0178 */ u8 primXluColor[3]; @@ -813,12 +827,12 @@ void GetItem_DrawGenericMusicNote(GlobalContext* globalCtx, s16 drawId) { OPEN_DISPS(globalCtx->state.gfxCtx); - gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, __FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); - gsDPSetGrayscaleColor(POLY_OPA_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255); - gsSPGrayscale(POLY_OPA_DISP++, true); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, __FILE__, __LINE__), G_MTX_MODELVIEW | G_MTX_LOAD); + gsDPSetGrayscaleColor(POLY_XLU_DISP++, colors[color_slot][0], colors[color_slot][1], colors[color_slot][2], 255); + gsSPGrayscale(POLY_XLU_DISP++, true); func_80093D18(globalCtx->state.gfxCtx); - gSPDisplayList(POLY_OPA_DISP++, sDrawItemTable[drawId].dlists[0]); - gsSPGrayscale(POLY_OPA_DISP++, false); + gSPDisplayList(POLY_XLU_DISP++, sDrawItemTable[drawId].dlists[0]); + gsSPGrayscale(POLY_XLU_DISP++, false); CLOSE_DISPS(globalCtx->state.gfxCtx); } diff --git a/soh/src/code/z_en_item00.c b/soh/src/code/z_en_item00.c index 899984b89..d4ddd18e9 100644 --- a/soh/src/code/z_en_item00.c +++ b/soh/src/code/z_en_item00.c @@ -519,7 +519,8 @@ void EnItem00_Init(Actor* thisx, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { func_8002F554(&this->actor, globalCtx, getItemId); } else { - getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId); + getItem.getItemFrom = ITEM_FROM_FREESTANDING; GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } } @@ -686,7 +687,8 @@ void func_8001E5C8(EnItem00* this, GlobalContext* globalCtx) { func_8002F434(&this->actor, globalCtx, this->getItemId, 50.0f, 80.0f); } else { GetItemEntry getItemEntry = - Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, this->getItemId); + getItemEntry.getItemFrom = ITEM_FROM_FREESTANDING; GiveItemEntryFromActor(&this->actor, globalCtx, getItemEntry, 50.0f, 80.0f); } this->unk_15A++; @@ -911,8 +913,9 @@ void EnItem00_Update(Actor* thisx, GlobalContext* globalCtx) { if (!gSaveContext.n64ddFlag) { func_8002F554(&this->actor, globalCtx, getItemId); } else { - getItem = Randomizer_GetRandomizedItem(getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + getItem = Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, getItemId); getItemId = getItem.getItemId; + getItem.getItemFrom = ITEM_FROM_FREESTANDING; GiveItemEntryFromActorWithFixedRange(&this->actor, globalCtx, getItem); } } @@ -1290,10 +1293,11 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI switch (giEntry.itemId) { case RG_MAGIC_SINGLE: case RG_MAGIC_DOUBLE: + case RG_MAGIC_BEAN_PACK: color_slot = 0; break; case RG_DOUBLE_DEFENSE: - color_slot = 1; + color_slot = 8; break; default: return; @@ -1305,14 +1309,14 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI s16* colors[9][3] = { { 34, 255, 76 }, // Minuet and Magic Upgrades Colors - { 177, 35, 35 }, // Bolero and Double Defense Colors + { 177, 35, 35 }, // Bolero Colors { 115, 251, 253 }, // Serenade Color { 177, 122, 35 }, // Requiem Color { 177, 28, 212 }, // Nocturne Color { 255, 255, 92 }, // Prelude Color { 31, 152, 49 }, // Stick Upgrade Color { 222, 182, 20 }, // Nut Upgrade Color - { 255, 255, 255 } // White Color placeholder + { 255, 255, 255 } // Double Defense Color }; s16* colorsEnv[9][3] = { @@ -1338,8 +1342,15 @@ void EnItem00_CustomItemsParticles(Actor* Parent, GlobalContext* globalCtx, GetI velocity.y = -0.05f; accel.y = -0.025f; pos.x = Rand_CenteredFloat(32.0f) + Parent->world.pos.x; - pos.y = (Rand_ZeroOne() * 6.0f) + Parent->world.pos.y + 25; + // Shop items are rendered at a different height than the rest, so a different y offset is required + if (Parent->id == ACTOR_EN_GIRLA) { + pos.y = (Rand_ZeroOne() * 6.0f) + Parent->world.pos.y + 5; + } else { + pos.y = (Rand_ZeroOne() * 6.0f) + Parent->world.pos.y + 25; + } pos.z = Rand_CenteredFloat(32.0f) + Parent->world.pos.z; + + EffectSsKiraKira_SpawnDispersed(globalCtx, &pos, &velocity, &accel, &primColor, &envColor, 1000, 50); } @@ -1379,9 +1390,9 @@ void EnItem00_DrawCollectible(EnItem00* this, GlobalContext* globalCtx) { f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItemEntry randoGetItemEntry = - Randomizer_GetRandomizedItem(this->getItemId, this->actor.id, this->ogParams, globalCtx->sceneNum); + Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, this->getItemId); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry); - GetItem_Draw(globalCtx, randoGetItemEntry.gid); + GetItemEntry_Draw(globalCtx, randoGetItemEntry); } else { s32 texIndex = this->actor.params - 3; @@ -1441,9 +1452,9 @@ void EnItem00_DrawHeartPiece(EnItem00* this, GlobalContext* globalCtx) { f32 mtxScale = 16.0f; Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); GetItemEntry randoGetItemEntry = - Randomizer_GetRandomizedItem(GI_HEART_PIECE, this->actor.id, this->ogParams, globalCtx->sceneNum); + Randomizer_GetItemFromActor(this->actor.id, globalCtx->sceneNum, this->ogParams, GI_HEART_PIECE); EnItem00_CustomItemsParticles(&this->actor, globalCtx, randoGetItemEntry); - GetItem_Draw(globalCtx, randoGetItemEntry.gid); + GetItemEntry_Draw(globalCtx, randoGetItemEntry); } else { s32 pad; @@ -1506,7 +1517,8 @@ s16 func_8001F404(s16 dropId) { } } - if (CVar_GetS32("gBombchuDrops", 0) && + if ((CVar_GetS32("gBombchuDrops", 0) || + (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_ENABLE_BOMBCHU_DROPS) == 1)) && (dropId == ITEM00_BOMBS_A || dropId == ITEM00_BOMBS_B || dropId == ITEM00_BOMBS_SPECIAL)) { dropId = EnItem00_ConvertBombDropToBombchu(dropId); } diff --git a/soh/src/code/z_game_over.c b/soh/src/code/z_game_over.c index 86ba7c6e1..bb4be8711 100644 --- a/soh/src/code/z_game_over.c +++ b/soh/src/code/z_game_over.c @@ -33,19 +33,21 @@ void GameOver_Update(GlobalContext* globalCtx) { gSaveContext.eventInf[1] &= ~1; // search inventory for spoiling items and revert if necessary - for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { - if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) { - INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; - - // search c buttons for the found spoiling item and revert if necessary - for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { - if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { - gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; - Interface_LoadItemIcon1(globalCtx, j); + if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) { + for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { + if (INV_CONTENT(ITEM_POCKET_EGG) == gSpoilingItems[i]) { + INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; + + // search c buttons for the found spoiling item and revert if necessary + for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { + if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { + gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + Interface_LoadItemIcon1(globalCtx, j); + } } } } - } + } // restore "temporary B" to the B Button if not a sword item if (gSaveContext.equips.buttonItems[0] != ITEM_SWORD_KOKIRI && diff --git a/soh/src/code/z_kankyo.c b/soh/src/code/z_kankyo.c index 34503619e..540e58a76 100644 --- a/soh/src/code/z_kankyo.c +++ b/soh/src/code/z_kankyo.c @@ -2095,7 +2095,7 @@ void func_80075B44(GlobalContext* globalCtx) { gSaveContext.dogIsLost = true; func_80078884(NA_SE_EV_CHICKEN_CRY_M); if ((Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) || - Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) && + Inventory_HatchPocketCucco(globalCtx)) && globalCtx->csCtx.state == 0 && !Player_InCsMode(globalCtx)) { Message_StartTextbox(globalCtx, 0x3066, NULL); } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 693187fb7..4ed8a3f62 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1696,7 +1696,7 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { // Increments text id based on piece of heart count, assumes the piece of heart text is all // in order and that you don't have more than the intended amount of heart pieces. textId += (gSaveContext.inventory.questItems & 0xF0000000 & 0xF0000000) >> 0x1C; - } else if (msgCtx->textId == 0xC && CHECK_OWNED_EQUIP(EQUIP_SWORD, 2)) { + } else if (!gSaveContext.n64ddFlag && (msgCtx->textId == 0xC && CHECK_OWNED_EQUIP(EQUIP_SWORD, 2))) { textId = 0xB; // Traded Giant's Knife for Biggoron Sword } else if (msgCtx->textId == 0xB4 && (gSaveContext.eventChkInf[9] & 0x40)) { textId = 0xB5; // Destroyed Gold Skulltula @@ -1718,6 +1718,7 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { gSaveContext.eventInf[0] = gSaveContext.eventInf[1] = gSaveContext.eventInf[2] = gSaveContext.eventInf[3] = 0; } + // RANDOTODO: Use this for ice trap messages if (CustomMessage_RetrieveIfExists(globalCtx)) { osSyncPrintf("Found custom message"); } else if (sTextIsCredits) { diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index d5b8113c3..83a1b19e8 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -3,6 +3,7 @@ #include "textures/parameter_static/parameter_static.h" #include "textures/do_action_static/do_action_static.h" #include "textures/icon_item_static/icon_item_static.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #ifdef _MSC_VER #include <stdlib.h> @@ -1574,6 +1575,17 @@ void func_80084BF4(GlobalContext* globalCtx, u16 flag) { } } +/** + * @brief Adds the given item to Link's inventory. + * + * NOTE: This function has been edited to be safe to use with a NULL globalCtx. + * If you need to add to this function, be sure you check if the globalCtx is not + * NULL before doing any operations requiring it. + * + * @param globalCtx + * @param item + * @return u8 + */ u8 Item_Give(GlobalContext* globalCtx, u8 item) { static s16 sAmmoRefillCounts[] = { 5, 10, 20, 30, 5, 10, 30, 0, 5, 20, 1, 5, 20, 50, 200, 10 }; s16 i; @@ -1646,15 +1658,21 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { } else if ((item >= ITEM_SWORD_KOKIRI) && (item <= ITEM_SWORD_BGS)) { gSaveContext.inventory.equipment |= gBitFlags[item - ITEM_SWORD_KOKIRI] << gEquipShifts[EQUIP_SWORD]; + // Both Giant's Knife and Biggoron Sword have the same Item ID, so this part handles both of them if (item == ITEM_SWORD_BGS) { gSaveContext.swordHealth = 8; - if (ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xF - ||(gSaveContext.n64ddFlag && ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xE)) { // In rando, when buying Giant's Knife, also check - gSaveContext.inventory.equipment ^= 8 << gEquipShifts[EQUIP_SWORD]; // for 0xE in case we don't have Kokiri Sword + // In rando, when buying Giant's Knife, also check + // for 0xE in case we don't have Kokiri Sword + if (ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xF || (gSaveContext.n64ddFlag && ALL_EQUIP_VALUE(EQUIP_SWORD) == 0xE)) { + + gSaveContext.inventory.equipment ^= 8 << gEquipShifts[EQUIP_SWORD]; + if (gSaveContext.equips.buttonItems[0] == ITEM_SWORD_KNIFE) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_BGS; - Interface_LoadItemIcon1(globalCtx, 0); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, 0); + } } } @@ -1662,7 +1680,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { gSaveContext.equips.buttonItems[0] = ITEM_SWORD_MASTER; gSaveContext.equips.equipment &= 0xFFF0; gSaveContext.equips.equipment |= 0x0002; - Interface_LoadItemIcon1(globalCtx, 0); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, 0); + } } PerformAutosave(globalCtx, item); @@ -1681,7 +1701,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return ITEM_NONE; } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { // Boss Key, Compass, and Dungeon Map exceptions for rando. - if (gSaveContext.n64ddFlag) { + // Rando should never be able to get here for Link's Pocket unless something goes wrong, + // but we check for a globalCtx here so the game won't crash if we do somehow get here. + if (gSaveContext.n64ddFlag && globalCtx != NULL) { if (globalCtx->sceneNum == 13) { // ganon's castle -> ganon's tower gSaveContext.inventory.dungeonItems[10] |= 1; } else if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple. @@ -1695,8 +1717,10 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { PerformAutosave(globalCtx, item); return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { - // Small key exceptions for rando. - if (gSaveContext.n64ddFlag) { + // Small key exceptions for rando with keysanity off. + // Rando should never be able to get here for Link's Pocket unless something goes wrong, + // but we check for a globalCtx here so the game won't crash if we do somehow get here. + if (gSaveContext.n64ddFlag && globalCtx != NULL) { if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle if (gSaveContext.inventory.dungeonKeys[13] < 0) { gSaveContext.inventory.dungeonKeys[13] = 1; @@ -1721,7 +1745,6 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { } } } - if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1; PerformAutosave(globalCtx, item); @@ -1859,7 +1882,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.equips.buttonItems); i++) { if (gSaveContext.equips.buttonItems[i] == ITEM_HOOKSHOT) { gSaveContext.equips.buttonItems[i] = ITEM_LONGSHOT; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } // update the adult/child equips when rando'd (accounting for equp swapped hookshot as child) @@ -1867,7 +1892,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) { if (gSaveContext.adultEquips.buttonItems[i] == ITEM_HOOKSHOT) { gSaveContext.adultEquips.buttonItems[i] = ITEM_LONGSHOT; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -1875,7 +1902,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) { if (gSaveContext.childEquips.buttonItems[i] == ITEM_HOOKSHOT) { gSaveContext.childEquips.buttonItems[i] = ITEM_LONGSHOT; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -2034,7 +2063,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) { if (gSaveContext.adultEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) { gSaveContext.adultEquips.buttonItems[i] = ITEM_OCARINA_TIME; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -2042,7 +2073,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (i = 1; i < ARRAY_COUNT(gSaveContext.childEquips.buttonItems); i++) { if (gSaveContext.childEquips.buttonItems[i] == ITEM_OCARINA_FAIRY) { gSaveContext.childEquips.buttonItems[i] = ITEM_OCARINA_TIME; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } } } @@ -2070,15 +2103,21 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return ITEM_NONE; } else if (item == ITEM_HEART) { osSyncPrintf("回復ハート回復ハート回復ハート\n"); // "Recovery Heart" - Health_ChangeBy(globalCtx, 0x10); + if (globalCtx != NULL) { + Health_ChangeBy(globalCtx, 0x10); + } PerformAutosave(globalCtx, item); return item; } else if (item == ITEM_MAGIC_SMALL) { if (gSaveContext.unk_13F0 != 10) { - Magic_Fill(globalCtx); + if (globalCtx != NULL) { + Magic_Fill(globalCtx); + } } - func_80087708(globalCtx, 12, 5); + if (globalCtx != NULL) { + func_80087708(globalCtx, 12, 5); + } if (!(gSaveContext.infTable[25] & 0x100)) { gSaveContext.infTable[25] |= 0x100; @@ -2090,10 +2129,13 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { return item; } else if (item == ITEM_MAGIC_LARGE) { if (gSaveContext.unk_13F0 != 10) { - Magic_Fill(globalCtx); + if (globalCtx != NULL) { + Magic_Fill(globalCtx); + } + } + if (globalCtx != NULL) { + func_80087708(globalCtx, 24, 5); } - - func_80087708(globalCtx, 24, 5); if (!(gSaveContext.infTable[25] & 0x100)) { gSaveContext.infTable[25] |= 0x100; @@ -2136,7 +2178,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { for (int buttonIndex = 1; buttonIndex < ARRAY_COUNT(gSaveContext.equips.buttonItems); buttonIndex++) { if ((temp + i) == gSaveContext.equips.cButtonSlots[buttonIndex - 1]) { gSaveContext.equips.buttonItems[buttonIndex] = item; - Interface_LoadItemIcon2(globalCtx, buttonIndex); + if (globalCtx != NULL) { + Interface_LoadItemIcon2(globalCtx, buttonIndex); + } gSaveContext.buttonStatus[BUTTON_STATUS_INDEX(buttonIndex)] = BTN_ENABLED; break; } @@ -2161,6 +2205,10 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { gSaveContext.itemGetInf[1] |= 0x8000; } + if (item >= ITEM_POCKET_EGG) { + gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(item); + } + temp = INV_CONTENT(item); INV_CONTENT(item) = item; @@ -2169,7 +2217,9 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { if (temp == gSaveContext.equips.buttonItems[i]) { if (item != ITEM_SOLD_OUT) { gSaveContext.equips.buttonItems[i] = item; - Interface_LoadItemIcon1(globalCtx, i); + if (globalCtx != NULL) { + Interface_LoadItemIcon1(globalCtx, i); + } } else { gSaveContext.equips.buttonItems[i] = ITEM_NONE; } @@ -2214,6 +2264,14 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) { return RG_NONE; } + if (item == RG_MAGIC_BEAN_PACK) { + if (INV_CONTENT(ITEM_BEAN) == ITEM_NONE) { + INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; + AMMO(ITEM_BEAN) = 10; + } + return RG_NONE; + } + if (item == RG_DOUBLE_DEFENSE) { gSaveContext.doubleDefense = true; gSaveContext.inventory.defenseHearts = 20; @@ -2259,6 +2317,106 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) { return ITEM_NONE; } } + } else if ((item >= RG_FOREST_TEMPLE_SMALL_KEY && item <= RG_GANONS_CASTLE_SMALL_KEY) || + (item >= RG_FOREST_TEMPLE_BOSS_KEY && item <= RG_GANONS_CASTLE_BOSS_KEY) || + (item >= RG_DEKU_TREE_MAP && item <= RG_ICE_CAVERN_MAP) || + (item >= RG_DEKU_TREE_COMPASS && item <= RG_ICE_CAVERN_COMPASS)) { + int mapIndex = gSaveContext.mapIndex; + switch (item) { + case RG_DEKU_TREE_MAP: + case RG_DEKU_TREE_COMPASS: + mapIndex = SCENE_YDAN; + break; + case RG_DODONGOS_CAVERN_MAP: + case RG_DODONGOS_CAVERN_COMPASS: + mapIndex = SCENE_DDAN; + break; + case RG_JABU_JABUS_BELLY_MAP: + case RG_JABU_JABUS_BELLY_COMPASS: + mapIndex = SCENE_BDAN; + break; + case RG_FOREST_TEMPLE_MAP: + case RG_FOREST_TEMPLE_COMPASS: + case RG_FOREST_TEMPLE_SMALL_KEY: + case RG_FOREST_TEMPLE_BOSS_KEY: + mapIndex = SCENE_BMORI1; + break; + case RG_FIRE_TEMPLE_MAP: + case RG_FIRE_TEMPLE_COMPASS: + case RG_FIRE_TEMPLE_SMALL_KEY: + case RG_FIRE_TEMPLE_BOSS_KEY: + mapIndex = SCENE_HIDAN; + break; + case RG_WATER_TEMPLE_MAP: + case RG_WATER_TEMPLE_COMPASS: + case RG_WATER_TEMPLE_SMALL_KEY: + case RG_WATER_TEMPLE_BOSS_KEY: + mapIndex = SCENE_MIZUSIN; + break; + case RG_SPIRIT_TEMPLE_MAP: + case RG_SPIRIT_TEMPLE_COMPASS: + case RG_SPIRIT_TEMPLE_SMALL_KEY: + case RG_SPIRIT_TEMPLE_BOSS_KEY: + mapIndex = SCENE_JYASINZOU; + break; + case RG_SHADOW_TEMPLE_MAP: + case RG_SHADOW_TEMPLE_COMPASS: + case RG_SHADOW_TEMPLE_SMALL_KEY: + case RG_SHADOW_TEMPLE_BOSS_KEY: + mapIndex = SCENE_HAKADAN; + break; + case RG_BOTTOM_OF_THE_WELL_MAP: + case RG_BOTTOM_OF_THE_WELL_COMPASS: + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + mapIndex = SCENE_HAKADANCH; + break; + case RG_ICE_CAVERN_MAP: + case RG_ICE_CAVERN_COMPASS: + mapIndex = SCENE_ICE_DOUKUTO; + break; + case RG_GANONS_CASTLE_BOSS_KEY: + mapIndex = SCENE_GANON; + break; + case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + mapIndex = SCENE_MEN; + break; + case RG_GERUDO_FORTRESS_SMALL_KEY: + mapIndex = SCENE_GERUDOWAY; + break; + case RG_GANONS_CASTLE_SMALL_KEY: + mapIndex = SCENE_GANONTIKA; + break; + } + + if ((item >= RG_FOREST_TEMPLE_SMALL_KEY) && (item <= RG_GANONS_CASTLE_SMALL_KEY)) { + if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { + gSaveContext.inventory.dungeonKeys[mapIndex] = 1; + return RG_NONE; + } else { + gSaveContext.inventory.dungeonKeys[mapIndex]++; + return RG_NONE; + } + } else { + int bitmask; + if ((item >= RG_DEKU_TREE_MAP) && (item <= RG_ICE_CAVERN_MAP)) { + bitmask = gBitFlags[2]; + } else if ((item >= RG_DEKU_TREE_COMPASS) && (item <= RG_ICE_CAVERN_COMPASS)) { + bitmask = gBitFlags[1]; + } else { + bitmask = gBitFlags[0]; + } + + gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask; + return RG_NONE; + } + } + + if (item == RG_TYCOON_WALLET) { + Inventory_ChangeUpgrade(UPG_WALLET, 3); + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_FULL_WALLETS)) { + Rupees_ChangeBy(999); + } + return RG_NONE; } temp = gSaveContext.inventory.items[slot]; @@ -2268,7 +2426,6 @@ u16 Randomizer_Item_Give(GlobalContext* globalCtx, GetItemEntry giEntry) { return temp; } - u8 Item_CheckObtainability(u8 item) { s16 i; s16 slot = SLOT(item); @@ -2321,6 +2478,13 @@ u8 Item_CheckObtainability(u8 item) { } else { return ITEM_NONE; } + } else if ( gSaveContext.n64ddFlag && + ((item >= RG_GERUDO_FORTRESS_SMALL_KEY) && (item <= RG_GANONS_CASTLE_SMALL_KEY) || + (item >= RG_FOREST_TEMPLE_BOSS_KEY) && (item <= RG_GANONS_CASTLE_BOSS_KEY) || + (item >= RG_DEKU_TREE_MAP) && (item <= RG_ICE_CAVERN_MAP) || + (item >= RG_DEKU_TREE_COMPASS) && (item <= RG_ICE_CAVERN_COMPASS)) + ) { + return ITEM_NONE; } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { @@ -2507,6 +2671,17 @@ s32 Inventory_HasEmptyBottle(void) { } } +bool Inventory_HasEmptyBottleSlot(void) { + u8* items = gSaveContext.inventory.items; + + return ( + items[SLOT_BOTTLE_1] == ITEM_NONE || + items[SLOT_BOTTLE_2] == ITEM_NONE || + items[SLOT_BOTTLE_3] == ITEM_NONE || + items[SLOT_BOTTLE_4] == ITEM_NONE + ); +} + s32 Inventory_HasSpecificBottle(u8 bottleItem) { u8* items = gSaveContext.inventory.items; @@ -2568,6 +2743,21 @@ s32 Inventory_ConsumeFairy(GlobalContext* globalCtx) { return 0; } +bool Inventory_HatchPocketCucco(GlobalContext* globalCtx) { + if (!gSaveContext.n64ddFlag) { + return Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); + } + + if (!PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_POCKET_EGG)) { + return 0; + } + + gSaveContext.adultTradeItems &= ~ADULT_TRADE_FLAG(ITEM_POCKET_EGG); + gSaveContext.adultTradeItems |= ADULT_TRADE_FLAG(ITEM_POCKET_CUCCO); + Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO); + return 1; +} + void func_80086D5C(s32* buf, u16 size) { u16 i; @@ -4509,14 +4699,15 @@ void Interface_Draw(GlobalContext* globalCtx) { static s16 D_80125B1C[][3] = { { 0, 150, 0 }, { 100, 255, 0 }, { 255, 255, 255 }, { 0, 0, 0 }, { 255, 255, 255 }, }; - static s16 rupeeDigitsFirst[] = { 1, 0, 0 }; - static s16 rupeeDigitsCount[] = { 2, 3, 3 }; + static s16 rupeeDigitsFirst[] = { 1, 0, 0, 0 }; + static s16 rupeeDigitsCount[] = { 2, 3, 3, 3 }; // courtesy of https://github.com/TestRunnerSRL/OoT-Randomizer/blob/Dev/ASM/c/hud_colors.c - static s16 rupeeWalletColors[3][3] = { + static s16 rupeeWalletColors[4][3] = { { 0xC8, 0xFF, 0x64 }, // Base Wallet (Green) { 0x82, 0x82, 0xFF }, // Adult's Wallet (Blue) { 0xFF, 0x64, 0x64 }, // Giant's Wallet (Red) + { 0xFF, 0x5A, 0xFF }, // Tycoon's Wallet (Purple). Only used in rando shopsanity. }; Color_RGB8 rColor_ori = { 200, 255, 100 }; Color_RGB8 rColor; diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index ff5e879ce..b10ee5bf9 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -200,7 +200,7 @@ void GivePlayerRandoRewardSongOfTime(GlobalContext* globalCtx, RandomizerCheck c Player* player = GET_PLAYER(globalCtx); if (gSaveContext.entranceIndex == 0x050F && player != NULL && !Player_InBlockingCsMode(globalCtx, player) && - !Flags_GetTreasure(globalCtx, 0x1F) && gSaveContext.nextTransition == 0xFF) { + !Flags_GetTreasure(globalCtx, 0x1F) && gSaveContext.nextTransition == 0xFF && !gSaveContext.pendingIceTrapCount) { GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(check, RG_SONG_OF_TIME); GiveItemEntryWithoutActor(globalCtx, getItemEntry); player->pendingFlag.flagID = 0x1F; @@ -245,7 +245,7 @@ void GivePlayerRandoRewardZeldaLightArrowsGift(GlobalContext* globalCtx, Randomi !Flags_GetTreasure(globalCtx, 0x1E) && player != NULL && !Player_InBlockingCsMode(globalCtx, player) && globalCtx->sceneLoadFlag == 0) { GetItemEntry getItem = Randomizer_GetItemFromKnownCheck(check, GI_ARROW_LIGHT); - if (player->pendingFlag.flagType == FLAG_NONE && GiveItemEntryWithoutActor(globalCtx, getItem)) { + if (GiveItemEntryWithoutActor(globalCtx, getItem)) { player->pendingFlag.flagID = 0x1E; player->pendingFlag.flagType = FLAG_SCENE_TREASURE; } @@ -401,7 +401,7 @@ void Gameplay_Init(GameState* thisx) { gSaveContext.bgsDayCount++; gSaveContext.dogIsLost = true; if (Inventory_ReplaceItem(globalCtx, ITEM_WEIRD_EGG, ITEM_CHICKEN) || - Inventory_ReplaceItem(globalCtx, ITEM_POCKET_EGG, ITEM_POCKET_CUCCO)) { + Inventory_HatchPocketCucco(globalCtx)) { Message_StartTextbox(globalCtx, 0x3066, NULL); } gSaveContext.nextDayTime = 0xFFFE; diff --git a/soh/src/code/z_player_lib.c b/soh/src/code/z_player_lib.c index 315af9e9e..522e7d851 100644 --- a/soh/src/code/z_player_lib.c +++ b/soh/src/code/z_player_lib.c @@ -1170,7 +1170,15 @@ void Player_DrawGetItemImpl(GlobalContext* globalCtx, Player* this, Vec3f* refPo Matrix_RotateZYX(0, globalCtx->gameplayFrames * 1000, 0, MTXMODE_APPLY); Matrix_Scale(0.2f, 0.2f, 0.2f, MTXMODE_APPLY); - GetItem_Draw(globalCtx, drawIdPlusOne - 1); + if (!(this->getItemEntry.modIndex == MOD_RANDOMIZER && this->getItemEntry.getItemId == RG_ICE_TRAP)) { + // RANDOTODO: Make this more flexible for easier toggling of individual item recolors in the future. + if (this->getItemEntry.drawFunc != NULL && + (CVar_GetS32("gRandoMatchKeyColors", 0) || this->getItemEntry.getItemId == RG_DOUBLE_DEFENSE)) { + this->getItemEntry.drawFunc(globalCtx, &this->getItemEntry); + } else { + GetItem_Draw(globalCtx, drawIdPlusOne - 1); + } + } CLOSE_DISPS(globalCtx->state.gfxCtx); } diff --git a/soh/src/code/z_scene_table.c b/soh/src/code/z_scene_table.c index 4987cba2f..9bf710af1 100644 --- a/soh/src/code/z_scene_table.c +++ b/soh/src/code/z_scene_table.c @@ -23,6 +23,8 @@ #include "overlays/actors/ovl_Bg_Dodoago/z_bg_dodoago.h" +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" + #define ENTRANCE(scene, spawn, continueBgm, displayTitleCard, fadeIn, fadeOut) \ { \ scene, spawn, \ @@ -2136,7 +2138,11 @@ void func_8009EE44(GlobalContext* globalCtx) { gDPPipeSync(POLY_OPA_DISP++); gDPSetEnvColor(POLY_OPA_DISP++, 128, 128, 128, 128); - if ((globalCtx->roomCtx.unk_74[0] == 0) && (INV_CONTENT(ITEM_COJIRO) == ITEM_COJIRO)) { + bool playerHasCojiro = INV_CONTENT(ITEM_COJIRO) == ITEM_COJIRO; + if (gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { + playerHasCojiro = PLAYER_HAS_SHUFFLED_ADULT_TRADE_ITEM(ITEM_COJIRO); + } + if ((globalCtx->roomCtx.unk_74[0] == 0) && playerHasCojiro) { if (globalCtx->roomCtx.unk_74[1] == 50) { func_8002F7DC(&GET_PLAYER(globalCtx)->actor, NA_SE_EV_CHICKEN_CRY_M); globalCtx->roomCtx.unk_74[0] = 1; diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index c71bb4def..16cbcdd33 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -3,9 +3,11 @@ #include <string.h> #include <soh/Enhancements/randomizer/randomizerTypes.h> +#include <soh/Enhancements/randomizer/randomizer_inf.h> +#include "soh/Enhancements/randomizer/adult_trade_shuffle.h" #define NUM_DUNGEONS 8 -#define NUM_TRIALS 6 +#define NUM_COWS 10 /** * Initialize new save. @@ -51,31 +53,6 @@ void GiveLinkRupees(int numOfRupees) { } } -void GiveLinkRupeesByGetItemId(GetItemID giid) { - if (giid == GI_RUPEE_GREEN) { - GiveLinkRupees(1); - } else if (giid == GI_RUPEE_BLUE) { - GiveLinkRupees(5); - } else if (giid == GI_RUPEE_RED) { - GiveLinkRupees(20); - } else if (giid == GI_RUPEE_PURPLE) { - GiveLinkRupees(50); - } else if (giid == GI_RUPEE_GOLD) { - GiveLinkRupees(100); - } -} - -void GiveLinkBombchus(GetItemID giid) { - INV_CONTENT(ITEM_BOMBCHU) = ITEM_BOMBCHU; - if (giid == GI_BOMBCHUS_5) { - AMMO(ITEM_BOMBCHU) += 5; - } else if (giid == GI_BOMBCHUS_10) { - AMMO(ITEM_BOMBCHU) += 10; - } else if (giid == GI_BOMBCHUS_20) { - AMMO(ITEM_BOMBCHU) += 20; - } -} - void GiveLinkDekuSticks(int howManySticks) { int maxStickCount; if (CUR_UPG_VALUE(UPG_STICKS) == 0) { @@ -97,16 +74,6 @@ void GiveLinkDekuSticks(int howManySticks) { } } -void GiveLinkDekuSticksByGetItemId(GetItemID giid) { - if (giid == GI_STICKS_1) { - GiveLinkDekuSticks(1); - } else if (giid == GI_STICKS_5) { - GiveLinkDekuSticks(5); - } else if (giid == GI_STICKS_10) { - GiveLinkDekuSticks(10); - } -} - void GiveLinkDekuNuts(int howManyNuts) { int maxNutCount; if (CUR_UPG_VALUE(UPG_NUTS) == 0) { @@ -128,300 +95,25 @@ void GiveLinkDekuNuts(int howManyNuts) { } } -void GiveLinkDekuNutsByGetItemId(GetItemID giid) { - if (giid == GI_NUTS_5) { - GiveLinkDekuNuts(5); - } else if (giid == GI_NUTS_10) { - GiveLinkDekuNuts(10); - } -} - -void GiveLinkBeans() { - INV_CONTENT(ITEM_BEAN) = ITEM_BEAN; - AMMO(ITEM_BEAN)++; -} - -void GiveLinkKokiriSword() { - uint32_t bitMask = 1 << 0; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkGiantsKnife() { - gSaveContext.bgsFlag = 0; - gSaveContext.swordHealth = 8; - uint32_t bitMask = 1 << 2; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkBiggoronSword() { - gSaveContext.bgsFlag = 1; - gSaveContext.swordHealth = 8; - uint32_t bitMask = 1 << 2; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkDekuShield() { - uint32_t bitMask = 1 << 4; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkHylianShield() { - uint32_t bitMask = 1 << 5; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkMirrorShield() { - uint32_t bitMask = 1 << 6; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkGoronTunic() { - uint32_t bitMask = 1 << 9; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkZoraTunic() { - uint32_t bitMask = 1 << 10; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkIronBoots() { - uint32_t bitMask = 1 << 13; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkHoverBoots() { - uint32_t bitMask = 1 << 14; - gSaveContext.inventory.equipment |= bitMask; -} - -void GiveLinkStoneOfAgony() { - uint32_t bitMask = 1 << QUEST_STONE_OF_AGONY; - gSaveContext.inventory.questItems |= bitMask; -} - -void GiveLinkGerudoCard() { - uint32_t bitMask = 1 << QUEST_GERUDO_CARD; - gSaveContext.inventory.questItems |= bitMask; -} - -void GiveLinkPieceOfHeart() { - int32_t pohCount = (gSaveContext.inventory.questItems & 0xF0000000) >> 28; - pohCount++; - gSaveContext.inventory.questItems |= (pohCount << 28); -} - -void GiveLinkHeartContainer() { - gSaveContext.healthCapacity += 16; - gSaveContext.health += 16; -} - -void GiveLinkBulletBagUpgrade(GetItemID giid) { - if (giid == GI_SLINGSHOT) { - INV_CONTENT(ITEM_SLINGSHOT) = ITEM_SLINGSHOT; - AMMO(ITEM_SLINGSHOT) = 30; - Inventory_ChangeUpgrade(UPG_BULLET_BAG, 1); - } else if (giid == GI_BULLET_BAG_40) { - Inventory_ChangeUpgrade(UPG_BULLET_BAG, 2); - AMMO(ITEM_SLINGSHOT) = 40; - } else if (giid == GI_BULLET_BAG_50) { - Inventory_ChangeUpgrade(UPG_BULLET_BAG, 3); - AMMO(ITEM_SLINGSHOT) = 50; - } -} - -void GiveLinkQuiverUpgrade(GetItemID giid) { - if (giid == GI_BOW) { - INV_CONTENT(ITEM_BOW) = ITEM_BOW; - Inventory_ChangeUpgrade(UPG_QUIVER, 1); - AMMO(ITEM_BOW) = 30; - } else if (giid == GI_QUIVER_40) { - Inventory_ChangeUpgrade(UPG_QUIVER, 2); - AMMO(ITEM_BOW) = 40; - } else if (giid == GI_QUIVER_50) { - Inventory_ChangeUpgrade(UPG_QUIVER, 3); - AMMO(ITEM_BOW) = 50; - } -} - -void GiveLinkBombBagUpgrade(GetItemID giid) { - if (giid == GI_BOMB_BAG_20) { - INV_CONTENT(ITEM_BOMB) = ITEM_BOMB; - Inventory_ChangeUpgrade(UPG_BOMB_BAG, 1); - AMMO(ITEM_BOMB) = 20; - } else if (giid == GI_BOMB_BAG_30) { - Inventory_ChangeUpgrade(UPG_BOMB_BAG, 2); - AMMO(ITEM_BOMB) = 30; - } else if (giid == GI_BOMB_BAG_40) { - Inventory_ChangeUpgrade(UPG_BOMB_BAG, 3); - AMMO(ITEM_BOMB) = 40; - } -} - -void GiveLinkStrengthUpgrade(GetItemID giid) { - if (giid == GI_BRACELET) { - Inventory_ChangeUpgrade(UPG_STRENGTH, 1); - } else if (giid == GI_GAUNTLETS_SILVER) { - Inventory_ChangeUpgrade(UPG_STRENGTH, 2); - } else if (giid == GI_GAUNTLETS_GOLD) { - Inventory_ChangeUpgrade(UPG_STRENGTH, 3); - } -} - -void GiveLinkScaleUpgrade(GetItemID giid) { - if (giid == GI_SCALE_SILVER) { - Inventory_ChangeUpgrade(UPG_SCALE, 1); - } else if (giid == GI_SCALE_GOLD) { - Inventory_ChangeUpgrade(UPG_SCALE, 2); - } -} - -void GiveLinkWalletUpgrade(GetItemID giid) { - if (giid == GI_WALLET_ADULT) { - Inventory_ChangeUpgrade(UPG_WALLET, 1); - } else if (giid == GI_WALLET_GIANT) { - Inventory_ChangeUpgrade(UPG_WALLET, 2); - } -} - -void GiveLinkDekuStickUpgrade(GetItemID giid) { - if (giid == GI_STICK_UPGRADE_20) { - INV_CONTENT(ITEM_STICK) = ITEM_STICK; - Inventory_ChangeUpgrade(UPG_STICKS, 2); - AMMO(ITEM_STICK) = 20; - } else if (giid == GI_STICK_UPGRADE_30) { - Inventory_ChangeUpgrade(UPG_STICKS, 3); - AMMO(ITEM_STICK) = 30; - } -} - -void GiveLinkDekuNutUpgrade(GetItemID giid) { - if (giid == GI_NUT_UPGRADE_30) { - INV_CONTENT(ITEM_NUT) = ITEM_NUT; - Inventory_ChangeUpgrade(UPG_NUTS, 2); - AMMO(ITEM_NUT) = 30; - } else if (giid == GI_NUT_UPGRADE_40) { - Inventory_ChangeUpgrade(UPG_NUTS, 3); - AMMO(ITEM_NUT) = 40; - } -} - -void GiveLinkMagic(GetItemID giid) { - if (giid == RG_MAGIC_SINGLE) { - gSaveContext.magicLevel = 1; - gSaveContext.magicAcquired = true; - gSaveContext.doubleMagic = false; - } else if (giid == RG_MAGIC_DOUBLE) { - gSaveContext.magicLevel = 2; - gSaveContext.magicAcquired = true; - gSaveContext.doubleMagic = true; - } -} - -void GiveLinkDoubleDefense() { - gSaveContext.doubleDefense = 1; - gSaveContext.inventory.defenseHearts = 20; -} - -void GiveLinkSong(GetItemID getItemId) { - uint32_t bitMask; - - switch (getItemId) { - case RG_ZELDAS_LULLABY: - bitMask = 1 << QUEST_SONG_LULLABY; - break; - case RG_SUNS_SONG: - bitMask = 1 << QUEST_SONG_SUN; - break; - case RG_EPONAS_SONG: - bitMask = 1 << QUEST_SONG_EPONA; - break; - case RG_SONG_OF_STORMS: - bitMask = 1 << QUEST_SONG_STORMS; - break; - case RG_SONG_OF_TIME: - bitMask = 1 << QUEST_SONG_TIME; - break; - case RG_SARIAS_SONG: - bitMask = 1 << QUEST_SONG_SARIA; - break; - case RG_MINUET_OF_FOREST: - bitMask = 1 << QUEST_SONG_MINUET; - break; - case RG_BOLERO_OF_FIRE: - bitMask = 1 << QUEST_SONG_BOLERO; - break; - case RG_SERENADE_OF_WATER: - bitMask = 1 << QUEST_SONG_SERENADE; - break; - case RG_NOCTURNE_OF_SHADOW: - bitMask = 1 << QUEST_SONG_NOCTURNE; - break; - case RG_REQUIEM_OF_SPIRIT: - bitMask = 1 << QUEST_SONG_REQUIEM; - break; - case RG_PRELUDE_OF_LIGHT: - bitMask = 1 << QUEST_SONG_PRELUDE; - break; - } - - gSaveContext.inventory.questItems |= bitMask; -} - -void GiveLinkDungeonReward(uint16_t getItemId) { - s16 item; - - u8 medallion = 0; - - switch (getItemId) { - case RG_FOREST_MEDALLION: - item = ITEM_MEDALLION_FOREST; - medallion = 1; - break; - case RG_FIRE_MEDALLION: - item = ITEM_MEDALLION_FIRE; - medallion = 1; - break; - case RG_WATER_MEDALLION: - item = ITEM_MEDALLION_WATER; - medallion = 1; - break; - case RG_SHADOW_MEDALLION: - item = ITEM_MEDALLION_SHADOW; - medallion = 1; - break; - case RG_SPIRIT_MEDALLION: - item = ITEM_MEDALLION_SPIRIT; - medallion = 1; - break; - case RG_LIGHT_MEDALLION: - item = ITEM_MEDALLION_LIGHT; - medallion = 1; - break; - case RG_KOKIRI_EMERALD: - item = ITEM_KOKIRI_EMERALD; - break; - case RG_GORON_RUBY: - item = ITEM_GORON_RUBY; - break; - case RG_ZORA_SAPPHIRE: - item = ITEM_ZORA_SAPPHIRE; - break; - } +void GiveLinksPocketItem() { + if (Randomizer_GetSettingValue(RSK_LINKS_POCKET) < 3) { + GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE); - if (medallion == 1) { - gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST]; - } else { - gSaveContext.inventory.questItems |= gBitFlags[item - ITEM_KOKIRI_EMERALD + QUEST_KOKIRI_EMERALD]; + if (getItemEntry.modIndex == MOD_NONE) { + if (getItemEntry.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; + } + Item_Give(NULL, getItemEntry.itemId); + } else if (getItemEntry.modIndex == MOD_RANDOMIZER) { + if (getItemEntry.getItemId == RG_ICE_TRAP) { + gSaveContext.pendingIceTrapCount++; + } else { + Randomizer_Item_Give(NULL, getItemEntry); + } + } } } -void GiveLinksPocketMedallion() { - GetItemEntry getItemEntry = Randomizer_GetItemFromKnownCheck(RC_LINKS_POCKET, RG_NONE); - - GiveLinkDungeonReward(getItemEntry.getItemId); -} - /** * Copy save currently on the buffer to Save Context and complete various tasks to open the save. * This includes: @@ -563,13 +255,15 @@ void Sram_OpenSave() { gSaveContext.equips.equipment |= 2; } - for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { - if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) { - INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; + if (!(gSaveContext.n64ddFlag && Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE))) { + for (i = 0; i < ARRAY_COUNT(gSpoilingItems); i++) { + if (INV_CONTENT(ITEM_TRADE_ADULT) == gSpoilingItems[i]) { + INV_CONTENT(gSpoilingItemReverts[i]) = gSpoilingItemReverts[i]; - for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { - if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { - gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + for (j = 1; j < ARRAY_COUNT(gSaveContext.equips.buttonItems); j++) { + if (gSaveContext.equips.buttonItems[j] == gSpoilingItems[i]) { + gSaveContext.equips.buttonItems[j] = gSpoilingItemReverts[i]; + } } } } @@ -610,14 +304,18 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { fileChooseCtx->n64ddFlag = 1; gSaveContext.n64ddFlag = 1; - // Sets all the dungeons to incomplete when generating a rando save. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/82 - for (u8 i = 0; i < NUM_DUNGEONS; i++) { - gSaveContext.dungeonsDone[i] = 0; + // Sets all rando flags to false + for (s32 i = 0; i < ARRAY_COUNT(gSaveContext.randomizerInf); i++) { + gSaveContext.randomizerInf[i] = 0; } - // Sets all Ganon's Trials to incomplete when generating a rando save. Fixes https://github.com/briaguya-ai/rando-issue-tracker/issues/131 - for (u8 i = 0; i < NUM_TRIALS; i++) { - gSaveContext.trialsDone[i] = 0; + // Set all trials to cleared if trial count is random or anything other than 6 + if (Randomizer_GetSettingValue(RSK_RANDOM_TRIALS) || (Randomizer_GetSettingValue(RSK_TRIAL_COUNT) != 6)) { + for (u16 i = RAND_INF_TRIALS_DONE_LIGHT_TRIAL; i <= RAND_INF_TRIALS_DONE_SHADOW_TRIAL; i++) { + if (!Randomizer_IsTrialRequired(i)) { + Flags_SetRandomizerInf(i); + } + } } // Set Cutscene flags to skip them @@ -626,8 +324,9 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { gSaveContext.eventChkInf[4] |= 0x20; // master sword pulled gSaveContext.eventChkInf[4] |= 0x8000; // entered master sword chamber gSaveContext.infTable[0] |= 1; - // RANDTODO: Don't skip this scene if Don't Skip Glitch Useful Cutscenes is enabled. - gSaveContext.infTable[17] |= 0x400; // Darunia in Fire Temple + if (!Randomizer_GetSettingValue(RSK_ENABLE_GLITCH_CUTSCENES)) { + gSaveContext.infTable[17] |= 0x400; // Darunia in Fire Temple + } gSaveContext.cutsceneIndex = 0; Flags_SetEventChkInf(5); @@ -645,8 +344,16 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { gSaveContext.eventChkInf[3] |= 0x800; gSaveContext.eventChkInf[12] |= 1; + // shuffle adult trade quest + if (Randomizer_GetSettingValue(RSK_SHUFFLE_ADULT_TRADE)) { + gSaveContext.adultTradeItems = 0; + } + + // Starts pending ice traps out at 0 before potentially incrementing them down the line. + gSaveContext.pendingIceTrapCount = 0; + // Give Link's pocket item - GiveLinksPocketMedallion(); + GiveLinksPocketItem(); int openForest = Randomizer_GetSettingValue(RSK_FOREST); switch (openForest) { @@ -675,18 +382,19 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { break; } - if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) GiveLinkKokiriSword(); - if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) GiveLinkDekuShield(); + if(Randomizer_GetSettingValue(RSK_STARTING_KOKIRI_SWORD)) Item_Give(NULL, ITEM_SWORD_KOKIRI); + if(Randomizer_GetSettingValue(RSK_STARTING_DEKU_SHIELD)) Item_Give(NULL, ITEM_SHIELD_DEKU); if(Randomizer_GetSettingValue(RSK_STARTING_OCARINA)) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; } - if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES)) { + // "Start with" == 0 for Maps and Compasses + if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == 0) { uint32_t mapBitMask = 1 << 1; uint32_t compassBitMask = 1 << 2; uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask; - for(int scene = 0; scene <= 9; scene++) { + for(int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) { gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask; } } @@ -701,71 +409,16 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { s32 giid = getItem.getItemId; if (getItem.modIndex == MOD_NONE) { - if (getItem.itemId >= ITEM_MEDALLION_FOREST && getItem.itemId <= ITEM_ZORA_SAPPHIRE) { - GiveLinkDungeonReward(getItem.getItemId); - } else if (getItem.itemId >= ITEM_SONG_MINUET && getItem.itemId <= ITEM_SONG_STORMS) { - GiveLinkSong(getItem.getItemId); - } else if (giid == GI_RUPEE_GREEN || giid == GI_RUPEE_BLUE || giid == GI_RUPEE_RED || - giid == GI_RUPEE_PURPLE || giid == GI_RUPEE_GOLD) { - GiveLinkRupeesByGetItemId(giid); - } else if (giid == GI_BOMBCHUS_10 || giid == GI_BOMBCHUS_5 || giid == GI_BOMBCHUS_20) { - GiveLinkBombchus(giid); - } else if (giid == GI_STICKS_1 || giid == GI_STICKS_5 || giid == GI_STICKS_10) { - GiveLinkDekuSticksByGetItemId(giid); - } else if (giid == GI_NUTS_5 || giid == GI_NUTS_10) { - GiveLinkDekuNutsByGetItemId(giid); - } else if (giid == GI_BEAN) { - GiveLinkBeans(); - } else if (giid == GI_SWORD_KOKIRI) { - GiveLinkKokiriSword(); - } else if (giid == GI_SWORD_BGS) { - GiveLinkBiggoronSword(); - } else if (giid == GI_SWORD_KNIFE) { - GiveLinkGiantsKnife(); - } else if (giid == GI_SHIELD_DEKU) { - GiveLinkDekuShield(); - } else if (giid == GI_SHIELD_HYLIAN) { - GiveLinkHylianShield(); - } else if (giid == GI_SHIELD_MIRROR) { - GiveLinkMirrorShield(); - } else if (giid == GI_TUNIC_GORON) { - GiveLinkGoronTunic(); - } else if (giid == GI_TUNIC_ZORA) { - GiveLinkZoraTunic(); - } else if (giid == GI_BOOTS_IRON) { - GiveLinkIronBoots(); - } else if (giid == GI_BOOTS_HOVER) { - GiveLinkHoverBoots(); - } else if (giid == GI_SLINGSHOT || giid == GI_BULLET_BAG_40 || giid == GI_BULLET_BAG_50) { - GiveLinkBulletBagUpgrade(giid); - } else if (giid == GI_BOW || giid == GI_QUIVER_40 || giid == GI_QUIVER_50) { - GiveLinkQuiverUpgrade(giid); - } else if (giid == GI_BOMB_BAG_20 || giid == GI_BOMB_BAG_30 || giid == GI_BOMB_BAG_40) { - GiveLinkBombBagUpgrade(giid); - } else if (giid == GI_BRACELET || giid == GI_GAUNTLETS_SILVER || giid == GI_GAUNTLETS_GOLD) { - GiveLinkStrengthUpgrade(giid); - } else if (giid == GI_SCALE_SILVER || giid == GI_SCALE_GOLD) { - GiveLinkScaleUpgrade(giid); - } else if (giid == GI_WALLET_ADULT || giid == GI_WALLET_GIANT) { - GiveLinkWalletUpgrade(giid); - } else if (giid == GI_STONE_OF_AGONY) { - GiveLinkStoneOfAgony(); - } else if (giid == GI_GERUDO_CARD) { - GiveLinkGerudoCard(); - } else if (giid == GI_HEART_PIECE) { - GiveLinkPieceOfHeart(); - } else if (giid == GI_HEART_CONTAINER) { - GiveLinkHeartContainer(); - } else if (giid == GI_STICK_UPGRADE_20 || giid == GI_STICK_UPGRADE_30) { - GiveLinkDekuStickUpgrade(giid); - } else if (giid == GI_NUT_UPGRADE_30 || giid == GI_NUT_UPGRADE_40) { - GiveLinkDekuNutUpgrade(giid); - } else { - s32 iid = getItem.itemId; - if (iid != -1) INV_CONTENT(iid) = iid; + if (getItem.getItemId == GI_SWORD_BGS) { + gSaveContext.bgsFlag = true; } + Item_Give(NULL, getItem.itemId); } else if (getItem.modIndex == MOD_RANDOMIZER) { - Randomizer_Item_Give(NULL, getItem); + if (getItem.getItemId == RG_ICE_TRAP) { + gSaveContext.pendingIceTrapCount++; + } else { + Randomizer_Item_Give(NULL, getItem); + } } // malon/talon back at ranch @@ -789,9 +442,31 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { GiveLinkRupees(9001); } - // For Ganon's boss key "Start With" is 0 - if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 0) { - gSaveContext.inventory.dungeonItems[10] |= 1; + // "Start with" == 0 for Keysanity + if(Randomizer_GetSettingValue(RSK_KEYSANITY) == 0) { + // TODO: If master quest there are different key counts + gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = 5; // Forest + gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = 8; // Fire + gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = 6; // Water + gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 5; // Spirit + gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = 5; // Shadow + gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = 3; // BotW + gSaveContext.inventory.dungeonKeys[SCENE_MEN] = 9; // GTG + gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = 2; // Ganon + } + + // "Start with" == 0 for Boss Kesanity + if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == 0) { + gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest + gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire + gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water + gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit + gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow + } + + // "Start with" == 2 for Ganon's Boss Key + if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 2) { + gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1; } HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT)); @@ -850,9 +525,20 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { gSaveContext.sceneFlags[12].collect |= (1 << 0x0C); if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD)) { - GiveLinkGerudoCard(); + Item_Give(NULL, ITEM_GERUDO_CARD); } } + + // complete mask quest + if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) { + gSaveContext.infTable[7] |= 0x80; // Soldier Wears Keaton Mask + gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask + gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask + gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask + gSaveContext.itemGetInf[3] |= 0x800; // bunny hood related + gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth + gSaveContext.eventChkInf[8] |= 0x8000; // sold all masks + } } Save_SaveFile(); |
