diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 954c36c142..45b717c14c 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -5,6 +5,16 @@ struct Player; +typedef struct { + /* 0x00 */ u8 itemId; + /* 0x01 */ u8 field; // various bit-packed data + /* 0x02 */ s8 gi; // defines the draw id and chest opening animation + /* 0x03 */ u8 textId; + /* 0x04 */ u16 objectId; +} GetItemEntry; // size = 0x06 + +extern GetItemEntry sGetItemTable[160]; + typedef enum { /* 0 */ PLAYER_SWORD_NONE, /* 1 */ PLAYER_SWORD_KOKIRI, @@ -612,6 +622,7 @@ typedef struct Player { /* 0x0A86 */ s8 unk_A86; /* 0x0A87 */ u8 unk_A87; /* 0x0A88 */ Vec3f unk_A88; // previous body part 0 position + /* 0x0A89 */ bool pendingIceTrap; } Player; // size = 0xA94 #endif diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index c68898b26a..c2b534111c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2488,6 +2488,7 @@ namespace Settings { ShuffleRewards.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS]); ShuffleSongs.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_SONGS]); + Tokensanity.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_TOKENS]); ShuffleKokiriSword.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD]); ShuffleOcarinas.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OCARINA]); @@ -2539,6 +2540,8 @@ namespace Settings { SkipTowerEscape.SetSelectedIndex(cvarSettings[RSK_SKIP_TOWER_ESCAPE]); + NightGSExpectSuns.SetSelectedIndex(cvarSettings[RSK_SKULLS_SUNS_SONG]); + // RANDOTODO implement chest shuffle with keysanity // ShuffleChestMinigame.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_CHEST_MINIGAME]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index d15ccb7d45..ea8ffd924d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2440,6 +2440,14 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_DEKU_TREE_COMPASS_ROOM_SIDE_CHEST; case 22788: return RC_DEKU_TREE_BASEMENT_CHEST; + case 8200: + return RC_DEKU_TREE_GS_COMPASS_ROOM; + case 8196: + return RC_DEKU_TREE_GS_BASEMENT_VINES; + case 8194: + return RC_DEKU_TREE_GS_BASEMENT_GATE; + case 8193: + return RC_DEKU_TREE_GS_BASEMENT_BACK_ROOM; } break; case 1: @@ -2456,6 +2464,16 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_DODONGOS_CAVERN_END_OF_BRIDGE_CHEST; case 4372: return RC_DODONGOS_CAVERN_GOSSIP_STONE; + case 8464: + return RC_DODONGOS_CAVERN_GS_SIDE_ROOM_NEAR_LOWER_LIZALFOS; + case 8450: + return RC_DODONGOS_CAVERN_GS_SCARECROW; + case 8452: + return RC_DODONGOS_CAVERN_GS_ALCOVE_ABOVE_STAIRS; + case 8449: + return RC_DODONGOS_CAVERN_GS_VINES_ABOVE_STAIRS; + case 8456: + return RC_DODONGOS_CAVERN_GS_BACK_ROOM; } break; case 2: @@ -2466,6 +2484,14 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_JABU_JABUS_BELLY_MAP_CHEST; case -18428: return RC_JABU_JABUS_BELLY_COMPASS_CHEST; + case 8712: + return RC_JABU_JABUS_BELLY_GS_WATER_SWITCH_ROOM; + case 8705: + return RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_LOWER; + case 8706: + return RC_JABU_JABUS_BELLY_GS_LOBBY_BASEMENT_UPPER; + case 8708: + return RC_JABU_JABUS_BELLY_GS_NEAR_BOSS; } break; case 3: @@ -2496,6 +2522,16 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_FOREST_TEMPLE_FALLING_CEILING_ROOM_CHEST; case 22827: return RC_FOREST_TEMPLE_BASEMENT_CHEST; + case 8962: + return RC_FOREST_TEMPLE_GS_FIRST_ROOM; + case 8968: + return RC_FOREST_TEMPLE_GS_LOBBY; + case 8961: + return RC_FOREST_TEMPLE_GS_RAISED_ISLAND_COURTYARD; + case 8964: + return RC_FOREST_TEMPLE_GS_LEVEL_ISLAND_COURTYARD; + case 8976: + return RC_FOREST_TEMPLE_GS_BASEMENT; } break; case 4: @@ -2528,6 +2564,16 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_FIRE_TEMPLE_MEGATON_HAMMER_CHEST; case 22601: return RC_FIRE_TEMPLE_HIGHEST_GORON_CHEST; + case 9218: + return RC_FIRE_TEMPLE_GS_BOSS_KEY_LOOP; + case 9217: + return RC_FIRE_TEMPLE_GS_SONG_OF_TIME_ROOM; + case 9220: + return RC_FIRE_TEMPLE_GS_BOULDER_MAZE; + case 9232: + return RC_FIRE_TEMPLE_GS_SCARECROW_CLIMB; + case 9224: + return RC_FIRE_TEMPLE_GS_SCARECROW_TOP; } break; case 5: @@ -2552,6 +2598,16 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_WATER_TEMPLE_RIVER_CHEST; case 22602: return RC_WATER_TEMPLE_DRAGON_CHEST; + case 9473: + return RC_WATER_TEMPLE_GS_BEHIND_GATE; + case 9480: + return RC_WATER_TEMPLE_GS_NEAR_BOSS_KEY_CHEST; + case 9476: + return RC_WATER_TEMPLE_GS_CENTRAL_PILLAR; + case 9474: + return RC_WATER_TEMPLE_GS_FALLING_PLATFORM_ROOM; + case 9488: + return RC_WATER_TEMPLE_GS_RIVER; } break; case 6: @@ -2590,6 +2646,16 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_SPIRIT_TEMPLE_BOSS_KEY_CHEST; case -29454: return RC_SPIRIT_TEMPLE_TOPMOST_CHEST; + case 9744: + return RC_SPIRIT_TEMPLE_GS_METAL_FENCE; + case 9736: + return RC_SPIRIT_TEMPLE_GS_SUN_ON_FLOOR_ROOM; + case 9729: + return RC_SPIRIT_TEMPLE_GS_HALL_AFTER_SUN_BLOCK_ROOM; + case 9732: + return RC_SPIRIT_TEMPLE_GS_LOBBY; + case 9730: + return RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM; } break; case 7: @@ -2628,6 +2694,16 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_SHADOW_TEMPLE_BOSS_KEY_CHEST; case 30797: return RC_SHADOW_TEMPLE_INVISIBLE_FLOORMASTER_CHEST; + case 9992: + return RC_SHADOW_TEMPLE_GS_LIKE_LIKE_ROOM; + case 9986: + return RC_SHADOW_TEMPLE_GS_FALLING_SPIKES_ROOM; + case 9985: + return RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT; + case 10000: + return RC_SHADOW_TEMPLE_GS_NEAR_SHIP; + case 9988: + return RC_SHADOW_TEMPLE_GS_TRIPLE_GIANT_POT; } break; case 8: @@ -2660,6 +2736,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_BOTTOM_OF_THE_WELL_LENS_OF_TRUTH_CHEST; case 27348: return RC_BOTTOM_OF_THE_WELL_INVISIBLE_CHEST; + case 10244: + return RC_BOTTOM_OF_THE_WELL_GS_WEST_INNER_ROOM; + case 10242: + return RC_BOTTOM_OF_THE_WELL_GS_EAST_INNER_ROOM; + case 10241: + return RC_BOTTOM_OF_THE_WELL_GS_LIKE_LIKE_CAGE; } break; case 9: @@ -2672,6 +2754,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_ICE_CAVERN_IRON_BOOTS_CHEST; case 262: return RC_ICE_CAVERN_FREESTANDING_POH; + case 10498: + return RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM; + case 10500: + return RC_ICE_CAVERN_GS_HEART_PIECE_ROOM; + case 10497: + return RC_ICE_CAVERN_GS_PUSH_BLOCK_ROOM; } break; case 10: @@ -2887,6 +2975,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_KAK_IMPAS_HOUSE_FREESTANDING_POH; } break; + case 56: + switch (actorParams) { + case -28152: + return RC_LH_GS_LAB_CRATE; + } + break; case 59: // using fountainType as actorParams switch (actorParams) { @@ -2961,6 +3055,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_HF_COW_GROTTO_GOSSIP_STONE; case 14355: return RC_HC_STORMS_GROTTO_GOSSIP_STONE; + case 10753: + return RC_HF_GS_COW_GROTTO; + case 10754: + return RC_HF_GS_NEAR_KAK_GROTTO; + case 11778: + return RC_HC_GS_STORMS_GROTTO; default: return RC_UNKNOWN_CHECK; } @@ -2999,6 +3099,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_LLR_FREESTANDING_POH; } break; + case 77: + switch (actorParams) { + case -29176: + return RC_MARKET_GS_GUARD_HOUSE; + } + break; case 82: switch (actorId) { case 316: @@ -3008,6 +3114,20 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_KAK_ANJU_AS_CHILD; } } + switch (actorParams) { + case -28640: + return RC_KAK_GS_TREE; + case 20482: + return RC_KAK_GS_GUARDS_HOUSE; + case 20484: + return RC_KAK_GS_WATCHTOWER; + case 20496: + return RC_KAK_GS_SKULLTULA_HOUSE; + case 20488: + return RC_KAK_GS_HOUSE_UNDER_CONSTRUCTION; + case 20544: + return RC_KAK_GS_ABOVE_IMPAS_HOUSE; + } break; case 83: switch (actorParams) { @@ -3017,6 +3137,10 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_GRAVEYARD_DAMPE_GRAVEDIGGING_TOUR; case 14346: return RC_GY_GOSSIP_STONE; + case 28673: + return RC_GRAVEYARD_GS_BEAN_PATCH; + case 20608: + return RC_GRAVEYARD_GS_WALL; } break; case 84: @@ -3029,6 +3153,14 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_ZR_NEAR_GROTTOS_GOSSIP_STONE; case 14860: return RC_ZR_NEAR_DOMAIN_GOSSIP_STONE; + case -28414: + return RC_ZR_GS_TREE; + case 20737: + return RC_ZR_GS_LADDER; + case 20752: + return RC_ZR_GS_NEAR_RAISED_GROTTOS; + case 20744: + return RC_ZR_GS_ABOVE_BRIDGE; } break; case 85: @@ -3041,6 +3173,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_KF_DEKU_TREE_RIGHT_GOSSIP_STONE; case 14623: return RC_KF_DEKU_TREE_LEFT_GOSSIP_STONE; + case 19458: + return RC_KF_GS_KNOW_IT_ALL_HOUSE; + case 27649: + return RC_KF_GS_BEAN_PATCH; + case 19460: + return RC_KF_GS_HOUSE_OF_TWINS; } break; case 86: @@ -3051,6 +3189,8 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_SFM_MAZE_UPPER_GOSSIP_STONE; case 14876: return RC_SFM_SARIA_GOSSIP_STONE; + case 19720: + return RC_SFM_GS; } break; case 87: @@ -3071,6 +3211,14 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_LH_SOUTHWEST_GOSSIP_STONE; case 14863: return RC_LH_SOUTHEAST_GOSSIP_STONE; + case 29185: + return RC_LH_GS_BEAN_PATCH; + case 20996: + return RC_LH_GS_LAB_WALL; + case 20994: + return RC_LH_GS_SMALL_ISLAND; + case 21008: + return RC_LH_GS_TREE; } break; case 88: @@ -3079,6 +3227,8 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_ZD_CHEST; case 14345: return RC_ZD_GOSSIP_STONE; + case 20800: + return RC_ZD_GS_FROZEN_WATERFALL; } break; case 89: @@ -3093,6 +3243,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act case 14849: case 14337: return RC_FAIRY_GOSSIP_STONE; + case 20740: + return RC_ZF_GS_ABOVE_THE_LOG; + case -28288: + return RC_ZF_GS_TREE; + case 20768: + return RC_ZF_GS_HIDDEN_CAVE; } break; case 90: @@ -3105,6 +3261,14 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_GV_CRATE_FREESTANDING_POH; case 14353: return RC_GV_GOSSIP_STONE; + case 21250: + return RC_GV_GS_SMALL_BRIDGE; + case 29441: + return RC_GV_GS_BEAN_PATCH; + case 21256: + return RC_GV_GS_BEHIND_TENT; + case 21252: + return RC_GV_GS_PILLAR; } break; case 91: @@ -3113,6 +3277,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_LW_DEKU_SCRUB_NEAR_BRIDGE; case 14365: return RC_LW_GOSSIP_STONE; + case 27905: + return RC_LW_GS_BEAN_PATCH_NEAR_BRIDGE; + case 27906: + return RC_LW_GS_BEAN_PATCH_NEAR_THEATER; + case 19716: + return RC_LW_GS_ABOVE_THEATER; } break; case 92: @@ -3125,6 +3295,12 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_COLOSSUS_FREESTANDING_POH; case 14362: return RC_COLOSSUS_GOSSIP_STONE; + case 29953: + return RC_COLOSSUS_GS_BEAN_PATCH; + case 21768: + return RC_COLOSSUS_GS_TREE; + case 21764: + return RC_COLOSSUS_GS_HILL; } break; case 93: @@ -3132,12 +3308,18 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act case 262: case 1984: return RC_GF_CHEST; + case 21506: + return RC_GF_GS_TOP_FLOOR; + case 21505: + return RC_GF_GS_ARCHERY_RANGE; } break; case 94: switch (actorParams) { case -30048: return RC_WASTELAND_CHEST; + case 13570: + return RC_WASTELAND_GS; } break; case 95: @@ -3146,6 +3328,8 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_HC_MALON_GOSSIP_STONE; case 14347: return RC_HC_ROCK_WALL_GOSSIP_STONE; + case -29180: + return RC_HC_GS_TREE; } break; case 96: @@ -3156,6 +3340,14 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_DMT_CHEST; case 14340: return RC_DMT_GOSSIP_STONE; + case 12036: + return RC_DMT_GS_NEAR_KAK; + case 28418: + return RC_DMT_GS_BEAN_PATCH; + case 20232: + return RC_DMT_GS_ABOVE_DODONGOS_CAVERN; + case 20240: + return RC_DMT_GS_FALLING_ROCKS_PATH; } break; case 97: @@ -3166,6 +3358,10 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_DMC_WALL_FREESTANDING_POH; case 14341: return RC_DMC_GOSSIP_STONE; + case -28800: + return RC_DMC_GS_CRATE; + case 28417: + return RC_DMC_GS_BEAN_PATCH; } break; case 98: @@ -3182,6 +3378,28 @@ RandomizerCheck Randomizer::GetCheckFromActor(s16 sceneNum, s16 actorId, s16 act return RC_GC_MAZE_GOSSIP_STONE; case 14873: return RC_GC_MEDIGORON_GOSSIP_STONE; + case 12064: + return RC_GC_GS_CENTER_PLATFORM; + case -28864: + return RC_GC_GS_BOULDER_MAZE; + } + break; + case 99: + switch (actorParams) { + case 11012: + return RC_LLR_GS_HOUSE_WINDOW; + case -29944: + return RC_LLR_GS_TREE; + case 11010: + return RC_LLR_GS_RAIN_SHED; + case 11009: + return RC_LLR_GS_BACK_WALL; + } + break; + case 100: + switch (actorParams) { + case 11777: + return RC_OGC_GS; } break; } @@ -3219,7 +3437,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 0); cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0); cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0); - + cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0); cvarSettings[RSK_SKIP_CHILD_ZELDA] = CVar_GetS32("gRandomizeSkipChildZelda", 0); // if we skip child zelda, we start with zelda's letter, and malon starts @@ -3256,6 +3474,8 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SKIP_EPONA_RACE] = CVar_GetS32("gRandomizeSkipEponaRace", 0); cvarSettings[RSK_SKIP_TOWER_ESCAPE] = CVar_GetS32("gRandomizeSkipTowerEscape", 0); + cvarSettings[RSK_SKULLS_SUNS_SONG] = CVar_GetS32("gRandomizeGsExpectSunsSong", 0); + RandoMain::GenerateRando(cvarSettings); CVar_SetS32("gRandoGenerating", 0); @@ -3301,7 +3521,8 @@ void DrawRandoEditor(bool& open) { // Shuffle Settings const char* randoShuffleDungeonRewards[4] = { "End of dungeons", "Any dungeon", "Overworld", "Anywhere" }; const char* randoLinksPocket[4] = { "Dungeon Reward", "Advancement", "Anything", "Nothing" }; - const char* randoShuffleSongs[3] = { "Song locations", "Dungeon rewards", "Anywhere" }; + const char* randoShuffleSongs[3] = { "Song Locations", "Dungeon Rewards", "Anywhere" }; + const char* randoShuffleTokens[4] = { "Off", "Dungeons", "Overworld", "All Tokens" }; const char* randoShopsanity[7] = { "Off", "0", "1", "2", "3", "4", "Random" }; const char* randoTokensanity[4] = { "Off", "Dungeons", "Overworld", "All Tokens" }; const char* randoShuffleScrubs[4] = { "Off", "Affordable", "Expensive", "Random Prices" }; @@ -3490,7 +3711,7 @@ void DrawRandoEditor(bool& open) { "Timer", "Zelda Gasp (Adult)" }; - ImGui::SetNextWindowSize(ImVec2(720, 530), ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(ImVec2(750, 530), ImGuiCond_FirstUseEver); if (!ImGui::Begin("Randomizer Editor", &open, ImGuiWindowFlags_NoFocusOnAppearing)) { ImGui::End(); return; @@ -3702,6 +3923,23 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCombobox("gRandomizeShuffleSongs", randoShuffleSongs, 3, 0); ImGui::Separator(); + // Shuffle Tokens + ImGui::Text(Settings::Tokensanity.GetName().c_str()); + InsertHelpHoverText( + "Shuffles Golden Skulltula Tokens into the item pool. This means\n" + "Golden Skulltulas can contain other items as well.\n" + "\n" + "Off - GS tokens will not be shuffled.\n" + "\n" + "Dungeons - Only shuffle GS tokens that are within dungeons.\n" + "\n" + "Overworld - Only shuffle GS tokens that are outside of dungeons.\n" + "\n" + "All Tokens - Shuffle all 100 GS tokens." + ); + SohImGui::EnhancementCombobox("gRandomizeShuffleTokens", randoShuffleTokens, 4, 0); + ImGui::Separator(); + if(CVar_GetS32("gRandomizeStartingKokiriSword", 0) == 0) { // Shuffle Kokiri Sword SohImGui::EnhancementCheckbox(Settings::ShuffleKokiriSword.GetName().c_str(), "gRandomizeShuffleKokiriSword"); @@ -3965,8 +4203,8 @@ void DrawRandoEditor(bool& open) { if (ImGui::BeginTable("tableRandoDetailedLogic", 3, ImGuiTableFlags_BordersH | ImGuiTableFlags_BordersV)) { ImGui::TableSetupColumn("Exclude Locations", ImGuiTableColumnFlags_WidthStretch, 200.0f); - // Add empty columns to keep them 1/3rd of the width - ImGui::TableSetupColumn(" ", ImGuiTableColumnFlags_WidthStretch, 200.0f); + ImGui::TableSetupColumn("Misc Options", ImGuiTableColumnFlags_WidthStretch, 200.0f); + // Add empty column to keep them 1/3rd of the width ImGui::TableSetupColumn(" ", ImGuiTableColumnFlags_WidthStretch, 200.0f); ImGui::TableHeadersRow(); ImGui::TableNextRow(); @@ -3987,8 +4225,17 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCheckbox("50 Skulltula Reward", "gRandomizeExcludeKak50SkullReward"); ImGui::Separator(); - // Add empty columns to keep them 1/3rd of the width + // COLUMN 2 - MISC OPTIONS ImGui::TableNextColumn(); + ImGui::Separator(); + SohImGui::EnhancementCheckbox("Nighttime GS expect Sun's Song", "gRandomizeGsExpectSunsSong"); + InsertHelpHoverText( + "All Golden Skulltulas that require nighttime to appear will only be\n" + "expected to be collected after getting Sun's Song." + ); + ImGui::Separator(); + + // Add empty column to keep them 1/3rd of the width ImGui::TableNextColumn(); ImGui::EndTable(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 5519668284..95b82127e7 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -973,6 +973,7 @@ typedef enum { RSK_STARTING_MAPS_COMPASSES, //RANDOTODO more options for this, rn it's just start with or own dungeon RSK_SHUFFLE_DUNGEON_REWARDS, RSK_SHUFFLE_SONGS, + RSK_SHUFFLE_TOKENS, RSK_SHUFFLE_WEIRD_EGG, RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD, RSK_ITEM_POOL, @@ -996,5 +997,6 @@ typedef enum { RSK_CUCCO_COUNT, RSK_BIG_POE_COUNT, RSK_SKIP_EPONA_RACE, - RSK_SKIP_TOWER_ESCAPE + RSK_SKIP_TOWER_ESCAPE, + RSK_SKULLS_SUNS_SONG } RandomizerSettingKey; diff --git a/soh/src/code/z_actor.c b/soh/src/code/z_actor.c index 70771880c3..cdeb974e86 100644 --- a/soh/src/code/z_actor.c +++ b/soh/src/code/z_actor.c @@ -1981,6 +1981,10 @@ s32 GiveItemWithoutActor(GlobalContext* globalCtx, s32 getItemId) { player->getItemId = getItemId; player->interactRangeActor = &player->actor; player->getItemDirection = player->actor.shape.rot.y; + // Player state 26 = Player is frozen + if (player->stateFlags1 & (PLAYER_STATE1_26)) { + player->pendingIceTrap = false; + } return true; } } diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 79326ee81b..eb6e9c10df 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1735,6 +1735,20 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { } else { msgCtx->msgLength = font->msgLength = Randomizer_CopyGanonHintText(font->msgBuf, sizeof(font->msgBuf)); } + } else if (textId == 0xF8 && GET_PLAYER(globalCtx)->getItemId == GI_ICE_TRAP) { + switch (gSaveContext.language) { + case LANGUAGE_FRA: + strcpy(font->msgBuf, "\x08\x06\x50\x05\x43IDIOT\x0E\x20\x02"); + break; + case LANGUAGE_GER: + strcpy(font->msgBuf, "\x08\x06\x15 Du bist ein\x05\x43 DUMMKOPF\x05\x40!\x0E\x20\x02"); + break; + case LANGUAGE_ENG: + default: + strcpy(font->msgBuf, "\x08\x06\x30You are a\x05\x43 FOWL\x05\x40!\x0E\x20\x02"); + break; + } + msgCtx->msgLength = font->msgLength = strlen(font->msgBuf); } else { msgCtx->msgLength = font->msgLength; char* src = (uintptr_t)font->msgOffset; diff --git a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c index 7bd83a997f..aa67f1a20f 100644 --- a/soh/src/overlays/actors/ovl_En_Si/z_en_si.c +++ b/soh/src/overlays/actors/ovl_En_Si/z_en_si.c @@ -18,6 +18,10 @@ void func_80AFB768(EnSi* this, GlobalContext* globalCtx); void func_80AFB89C(EnSi* this, GlobalContext* globalCtx); void func_80AFB950(EnSi* this, GlobalContext* globalCtx); +s32 textId = 0xB4; +s32 giveItemId = ITEM_SKULL_TOKEN; +s32 getItemId; + static ColliderCylinderInit sCylinderInit = { { COLTYPE_NONE, @@ -93,11 +97,24 @@ void func_80AFB768(EnSi* this, GlobalContext* globalCtx) { if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { this->collider.base.ocFlags2 &= ~OC2_HIT_PLAYER; - Item_Give(globalCtx, ITEM_SKULL_TOKEN); - if (CVar_GetS32("gSkulltulaFreeze", 0) != 1) { + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetRandomizedItemId(GI_SKULL_TOKEN, this->actor.id, this->actor.params, globalCtx->sceneNum); + if (getItemId == GI_ICE_TRAP) { + player->getItemId = GI_ICE_TRAP; + player->pendingIceTrap = true; + textId = 0xF8; + } else { + textId = sGetItemTable[getItemId - 1].textId; + giveItemId = sGetItemTable[getItemId - 1].itemId; + Item_Give(globalCtx, giveItemId); + } + } else { + Item_Give(globalCtx, giveItemId); + } + if ((CVar_GetS32("gSkulltulaFreeze", 0) != 1 || giveItemId != ITEM_SKULL_TOKEN) && getItemId != GI_ICE_TRAP) { player->actor.freezeTimer = 20; } - Message_StartTextbox(globalCtx, 0xB4, NULL); + Message_StartTextbox(globalCtx, textId, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); this->actionFunc = func_80AFB950; } else { @@ -117,8 +134,21 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) { this->actor.shape.rot.y += 0x400; if (!CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_13)) { - Item_Give(globalCtx, ITEM_SKULL_TOKEN); - Message_StartTextbox(globalCtx, 0xB4, NULL); + if (gSaveContext.n64ddFlag) { + getItemId = Randomizer_GetRandomizedItemId(GI_SKULL_TOKEN, this->actor.id, this->actor.params, globalCtx->sceneNum); + if (getItemId == GI_ICE_TRAP) { + player->getItemId = GI_ICE_TRAP; + player->pendingIceTrap = true; + textId = 0xF8; + } else { + textId = sGetItemTable[getItemId - 1].textId; + giveItemId = sGetItemTable[getItemId - 1].itemId; + Item_Give(globalCtx, giveItemId); + } + } else { + Item_Give(globalCtx, giveItemId); + } + Message_StartTextbox(globalCtx, textId, NULL); Audio_PlayFanfare(NA_BGM_SMALL_ITEM_GET); this->actionFunc = func_80AFB950; } @@ -127,7 +157,8 @@ void func_80AFB89C(EnSi* this, GlobalContext* globalCtx) { void func_80AFB950(EnSi* this, GlobalContext* globalCtx) { Player* player = GET_PLAYER(globalCtx); - if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING && CVar_GetS32("gSkulltulaFreeze", 0) != 1) { + if (Message_GetState(&globalCtx->msgCtx) != TEXT_STATE_CLOSING && + ((CVar_GetS32("gSkulltulaFreeze", 0) != 1 || giveItemId != ITEM_SKULL_TOKEN) && getItemId != GI_ICE_TRAP)) { player->actor.freezeTimer = 10; } else { SET_GS_FLAGS((this->actor.params & 0x1F00) >> 8, this->actor.params & 0xFF); @@ -150,6 +181,19 @@ void EnSi_Draw(Actor* thisx, GlobalContext* globalCtx) { if (this->actionFunc != func_80AFB950) { func_8002ED80(&this->actor, globalCtx, 0); func_8002EBCC(&this->actor, globalCtx, 0); - GetItem_Draw(globalCtx, GID_SKULL_TOKEN_2); + if (!gSaveContext.n64ddFlag) { + GetItem_Draw(globalCtx, GID_SKULL_TOKEN_2); + } else { + getItemId = Randomizer_GetRandomizedItemId(GI_SKULL_TOKEN, this->actor.id, this->actor.params, globalCtx->sceneNum); + if (getItemId >= GI_MINUET_OF_FOREST && getItemId <= GI_DOUBLE_DEFENSE) { + EnItem00_CustomItemsParticles(&this->actor, globalCtx, getItemId); + } + if (getItemId != ITEM_SKULL_TOKEN) { + f32 mtxScale = 1.5f; + Matrix_Scale(mtxScale, mtxScale, mtxScale, MTXMODE_APPLY); + } + GetItem_Draw(globalCtx, Randomizer_GetItemModelFromId(getItemId)); + } + } } diff --git a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c index 51a5128559..864fa22707 100644 --- a/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c +++ b/soh/src/overlays/actors/ovl_En_Sw/z_en_sw.c @@ -613,9 +613,9 @@ void func_80B0D878(EnSw* this, GlobalContext* globalCtx) { x = (this->unk_364.x * 10.0f); y = (this->unk_364.y * 10.0f); z = (this->unk_364.z * 10.0f); - temp_v0 = - Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_SI, this->actor.world.pos.x + x, - this->actor.world.pos.y + y, this->actor.world.pos.z + z, 0, 0, 0, this->actor.params); + temp_v0 = Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_SI, + this->actor.world.pos.x + x, this->actor.world.pos.y + y, + this->actor.world.pos.z + z, 0, 0, 0, this->actor.params); if (temp_v0 != NULL) { temp_v0->parent = NULL; } diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index 1f1d09a8db..d1ddf2f2ef 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -21,14 +21,6 @@ #include "objects/object_link_child/object_link_child.h" #include "textures/icon_item_24_static/icon_item_24_static.h" -typedef struct { - /* 0x00 */ u8 itemId; - /* 0x01 */ u8 field; // various bit-packed data - /* 0x02 */ s8 gi; // defines the draw id and chest opening animation - /* 0x03 */ u8 textId; - /* 0x04 */ u16 objectId; -} GetItemEntry; // size = 0x06 - #define GET_ITEM(itemId, objectId, drawId, textId, field, chestAnim) \ { itemId, field, (chestAnim != CHEST_ANIM_SHORT ? 1 : -1) * (drawId + 1), textId, objectId } @@ -496,7 +488,7 @@ static u16 D_8085361C[] = { NA_SE_VO_LI_FALL_L, }; -static GetItemEntry sGetItemTable[] = { +GetItemEntry sGetItemTable[] = { GET_ITEM(ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT), GET_ITEM(ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT), GET_ITEM(ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT), @@ -10985,6 +10977,10 @@ void Player_UpdateCommon(Player* this, GlobalContext* globalCtx, Input* input) { Collider_ResetQuadAC(globalCtx, &this->shieldQuad.base); Collider_ResetQuadAT(globalCtx, &this->shieldQuad.base); + + if (this->pendingIceTrap) { + GiveItemWithoutActor(globalCtx, GI_ICE_TRAP); + } } static Vec3f D_80854838 = { 0.0f, 0.0f, -30.0f };