Add support for shuffling maps and compasses

This commit is contained in:
Garrett Cox 2022-08-08 14:07:02 -05:00
parent cb97c2a205
commit 8f55dd0624
9 changed files with 359 additions and 109 deletions

View File

@ -268,6 +268,26 @@ typedef enum {
/* 0xB1 */ ITEM_SPIRIT_TEMPLE_BOSS_KEY,
/* 0xB2 */ ITEM_SHADOW_TEMPLE_BOSS_KEY,
/* 0xB3 */ ITEM_GANONS_CASTLE_BOSS_KEY,
/* 0xB4 */ ITEM_DEKU_TREE_MAP,
/* 0xB5 */ ITEM_DODONGOS_CAVERN_MAP,
/* 0xB6 */ ITEM_JABU_JABUS_BELLY_MAP,
/* 0xB7 */ ITEM_FOREST_TEMPLE_MAP,
/* 0xB8 */ ITEM_FIRE_TEMPLE_MAP,
/* 0xB9 */ ITEM_WATER_TEMPLE_MAP,
/* 0xBA */ ITEM_SPIRIT_TEMPLE_MAP,
/* 0xBB */ ITEM_SHADOW_TEMPLE_MAP,
/* 0xBC */ ITEM_BOTTOM_OF_THE_WELL_MAP,
/* 0xBD */ ITEM_ICE_CAVERN_MAP,
/* 0xBE */ ITEM_DEKU_TREE_COMPASS,
/* 0xBF */ ITEM_DODONGOS_CAVERN_COMPASS,
/* 0xC0 */ ITEM_JABU_JABUS_BELLY_COMPASS,
/* 0xC1 */ ITEM_FOREST_TEMPLE_COMPASS,
/* 0xC2 */ ITEM_FIRE_TEMPLE_COMPASS,
/* 0xC3 */ ITEM_WATER_TEMPLE_COMPASS,
/* 0xC4 */ ITEM_SPIRIT_TEMPLE_COMPASS,
/* 0xC5 */ ITEM_SHADOW_TEMPLE_COMPASS,
/* 0xC6 */ ITEM_BOTTOM_OF_THE_WELL_COMPASS,
/* 0xC7 */ ITEM_ICE_CAVERN_COMPASS,
/* 0xFC */ ITEM_LAST_USED = 0xFC,
/* 0xFE */ ITEM_NONE_FE = 0xFE,
/* 0xFF */ ITEM_NONE = 0xFF
@ -461,6 +481,28 @@ typedef enum {
/* 0xAC */ GI_SHADOW_TEMPLE_BOSS_KEY,
/* 0xAD */ GI_GANONS_CASTLE_BOSS_KEY,
/* 0xAE */ GI_DEKU_TREE_MAP,
/* 0xAF */ GI_DODONGOS_CAVERN_MAP,
/* 0xB0 */ GI_JABU_JABUS_BELLY_MAP,
/* 0xB1 */ GI_FOREST_TEMPLE_MAP,
/* 0xB2 */ GI_FIRE_TEMPLE_MAP,
/* 0xB3 */ GI_WATER_TEMPLE_MAP,
/* 0xB4 */ GI_SPIRIT_TEMPLE_MAP,
/* 0xB5 */ GI_SHADOW_TEMPLE_MAP,
/* 0xB6 */ GI_BOTTOM_OF_THE_WELL_MAP,
/* 0xB7 */ GI_ICE_CAVERN_MAP,
/* 0xB8 */ GI_DEKU_TREE_COMPASS,
/* 0xB9 */ GI_DODONGOS_CAVERN_COMPASS,
/* 0xBA */ GI_JABU_JABUS_BELLY_COMPASS,
/* 0xBB */ GI_FOREST_TEMPLE_COMPASS,
/* 0xBC */ GI_FIRE_TEMPLE_COMPASS,
/* 0xBD */ GI_WATER_TEMPLE_COMPASS,
/* 0xBE */ GI_SPIRIT_TEMPLE_COMPASS,
/* 0xBF */ GI_SHADOW_TEMPLE_COMPASS,
/* 0xC0 */ GI_BOTTOM_OF_THE_WELL_COMPASS,
/* 0xC1 */ GI_ICE_CAVERN_COMPASS,
/* 0xAE */ GI_MAX
} GetItemID;

View File

@ -13,7 +13,7 @@ typedef struct {
/* 0x04 */ u16 objectId;
} GetItemEntry; // size = 0x06
extern GetItemEntry sGetItemTable[175];
extern GetItemEntry sGetItemTable[195];
typedef enum {
/* 0 */ PLAYER_SWORD_NONE,

View File

@ -2544,14 +2544,7 @@ namespace Settings {
StartingDekuShield.SetSelectedIndex(cvarSettings[RSK_STARTING_DEKU_SHIELD]);
StartingKokiriSword.SetSelectedIndex(cvarSettings[RSK_STARTING_KOKIRI_SWORD]);
if(cvarSettings[RSK_STARTING_MAPS_COMPASSES]) {
// "Start With" is index 0
MapsAndCompasses.SetSelectedIndex(0);
} else {
// We don't support maps/compasses outside of their own dungeon yet
// "Own Dungeon" is index 2
MapsAndCompasses.SetSelectedIndex(2);
}
MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]);
StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]);
StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]);

View File

@ -985,6 +985,18 @@ std::unordered_map<s16, s16> itemIdToModel = { { GI_NONE, GID_MAXIMUM },
{ GI_REQUIEM_OF_SPIRIT, GID_SONG_REQUIEM },
{ GI_NOCTURNE_OF_SHADOW, GID_SONG_NOCTURNE },
{ GI_PRELUDE_OF_LIGHT, GID_SONG_PRELUDE },
{ GI_DOUBLE_DEFENSE, GID_HEART_CONTAINER },
{ GI_STONE_KOKIRI, GID_KOKIRI_EMERALD },
{ GI_STONE_GORON, GID_GORON_RUBY },
{ GI_STONE_ZORA, GID_ZORA_SAPPHIRE },
{ GI_MEDALLION_FOREST, GID_MEDALLION_FOREST },
{ GI_MEDALLION_FIRE, GID_MEDALLION_FIRE },
{ GI_MEDALLION_WATER, GID_MEDALLION_WATER },
{ GI_MEDALLION_SPIRIT, GID_MEDALLION_SPIRIT },
{ GI_MEDALLION_SHADOW, GID_MEDALLION_SHADOW },
{ GI_MEDALLION_LIGHT, GID_MEDALLION_LIGHT },
{ GI_SINGLE_MAGIC, GID_MAGIC_SMALL },
{ GI_DOUBLE_MAGIC, GID_MAGIC_LARGE },
{ GI_GERUDO_FORTRESS_SMALL_KEY, GID_KEY_SMALL },
{ GI_FOREST_TEMPLE_SMALL_KEY, GID_KEY_SMALL },
{ GI_FIRE_TEMPLE_SMALL_KEY, GID_KEY_SMALL },
@ -1000,18 +1012,26 @@ std::unordered_map<s16, s16> itemIdToModel = { { GI_NONE, GID_MAXIMUM },
{ GI_SPIRIT_TEMPLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_SHADOW_TEMPLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_GANONS_CASTLE_BOSS_KEY, GID_KEY_BOSS },
{ GI_DOUBLE_DEFENSE, GID_HEART_CONTAINER },
{ GI_STONE_KOKIRI, GID_KOKIRI_EMERALD },
{ GI_STONE_GORON, GID_GORON_RUBY },
{ GI_STONE_ZORA, GID_ZORA_SAPPHIRE },
{ GI_MEDALLION_FOREST, GID_MEDALLION_FOREST },
{ GI_MEDALLION_FIRE, GID_MEDALLION_FIRE },
{ GI_MEDALLION_WATER, GID_MEDALLION_WATER },
{ GI_MEDALLION_SPIRIT, GID_MEDALLION_SPIRIT },
{ GI_MEDALLION_SHADOW, GID_MEDALLION_SHADOW },
{ GI_MEDALLION_LIGHT, GID_MEDALLION_LIGHT },
{ GI_SINGLE_MAGIC, GID_MAGIC_SMALL },
{ GI_DOUBLE_MAGIC, GID_MAGIC_LARGE },
{ GI_DEKU_TREE_MAP, GID_DUNGEON_MAP },
{ GI_DODONGOS_CAVERN_MAP, GID_DUNGEON_MAP },
{ GI_JABU_JABUS_BELLY_MAP, GID_DUNGEON_MAP },
{ GI_FOREST_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_FIRE_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_WATER_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_SPIRIT_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_SHADOW_TEMPLE_MAP, GID_DUNGEON_MAP },
{ GI_BOTTOM_OF_THE_WELL_MAP, GID_DUNGEON_MAP },
{ GI_ICE_CAVERN_MAP, GID_DUNGEON_MAP },
{ GI_DEKU_TREE_COMPASS, GID_COMPASS },
{ GI_DODONGOS_CAVERN_COMPASS, GID_COMPASS },
{ GI_JABU_JABUS_BELLY_COMPASS, GID_COMPASS },
{ GI_FOREST_TEMPLE_COMPASS, GID_COMPASS },
{ GI_FIRE_TEMPLE_COMPASS, GID_COMPASS },
{ GI_WATER_TEMPLE_COMPASS, GID_COMPASS },
{ GI_SPIRIT_TEMPLE_COMPASS, GID_COMPASS },
{ GI_SHADOW_TEMPLE_COMPASS, GID_COMPASS },
{ GI_BOTTOM_OF_THE_WELL_COMPASS, GID_COMPASS },
{ GI_ICE_CAVERN_COMPASS, GID_COMPASS },
{ GI_ICE_TRAP, GID_RUPEE_GOLD },
{ GI_ICE_TRAP, GID_MAXIMUM },
{ GI_TEXT_0, GID_MAXIMUM } };
@ -1634,10 +1654,18 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
}
break;
case RSK_STARTING_MAPS_COMPASSES:
if(it.value() == "Own Dungeon") {
gSaveContext.randoSettings[index].value = 0;
} else if (it.value() == "Start With") {
gSaveContext.randoSettings[index].value = 1;
if(it.value() == "Start With") {
gSaveContext.randoSettings[index].value = 0;
} else if(it.value() == "Vanilla") {
gSaveContext.randoSettings[index].value = 1;
} else if(it.value() == "Own Dungeon") {
gSaveContext.randoSettings[index].value = 2;
} else if(it.value() == "Any Dungeon") {
gSaveContext.randoSettings[index].value = 3;
} else if(it.value() == "Overworld") {
gSaveContext.randoSettings[index].value = 4;
} else if(it.value() == "Anywhere") {
gSaveContext.randoSettings[index].value = 5;
}
break;
case RSK_STARTING_DEKU_SHIELD:
@ -2300,30 +2328,47 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId)
case RG_PRELUDE_OF_LIGHT:
return GI_PRELUDE_OF_LIGHT;
// todo implement dungeon-specific maps/compasses
case RG_DEKU_TREE_MAP:
return GI_DEKU_TREE_MAP;
case RG_DODONGOS_CAVERN_MAP:
return GI_DODONGOS_CAVERN_MAP;
case RG_JABU_JABUS_BELLY_MAP:
return GI_JABU_JABUS_BELLY_MAP;
case RG_FOREST_TEMPLE_MAP:
return GI_FOREST_TEMPLE_MAP;
case RG_FIRE_TEMPLE_MAP:
return GI_FIRE_TEMPLE_MAP;
case RG_WATER_TEMPLE_MAP:
return GI_WATER_TEMPLE_MAP;
case RG_SPIRIT_TEMPLE_MAP:
return GI_SPIRIT_TEMPLE_MAP;
case RG_SHADOW_TEMPLE_MAP:
return GI_SHADOW_TEMPLE_MAP;
case RG_BOTTOM_OF_THE_WELL_MAP:
return GI_BOTTOM_OF_THE_WELL_MAP;
case RG_ICE_CAVERN_MAP:
return GI_MAP;
return GI_ICE_CAVERN_MAP;
case RG_DEKU_TREE_COMPASS:
return GI_DEKU_TREE_COMPASS;
case RG_DODONGOS_CAVERN_COMPASS:
return GI_DODONGOS_CAVERN_COMPASS;
case RG_JABU_JABUS_BELLY_COMPASS:
return GI_JABU_JABUS_BELLY_COMPASS;
case RG_FOREST_TEMPLE_COMPASS:
return GI_FOREST_TEMPLE_COMPASS;
case RG_FIRE_TEMPLE_COMPASS:
return GI_FIRE_TEMPLE_COMPASS;
case RG_WATER_TEMPLE_COMPASS:
return GI_WATER_TEMPLE_COMPASS;
case RG_SPIRIT_TEMPLE_COMPASS:
return GI_SPIRIT_TEMPLE_COMPASS;
case RG_SHADOW_TEMPLE_COMPASS:
return GI_SHADOW_TEMPLE_COMPASS;
case RG_BOTTOM_OF_THE_WELL_COMPASS:
return GI_BOTTOM_OF_THE_WELL_COMPASS;
case RG_ICE_CAVERN_COMPASS:
return GI_COMPASS;
return GI_ICE_CAVERN_COMPASS;
case RG_FOREST_TEMPLE_BOSS_KEY:
return GI_FOREST_TEMPLE_BOSS_KEY;
@ -3518,7 +3563,7 @@ void GenerateRandomizerImgui() {
cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVar_GetS32("gRandomizeShuffleKokiriSword", 0) ||
CVar_GetS32("gRandomizeStartingKokiriSword", 0);
cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVar_GetS32("gRandomizeStartingDekuShield", 0);
cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 0);
cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 1);
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);
@ -3627,8 +3672,7 @@ void DrawRandoEditor(bool& open) {
const char* randoShuffleAdultTrade[2] = { "Off", "On" };
// Shuffle Dungeon Items Settings
const char* randoShuffleMapsAndCompasses[6] = { "Own Dungeon", "Any Dungeon", "Overworld",
"Anywhere", "Start With", "Vanilla" };
const char* randoShuffleMapsAndCompasses[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" };
const char* randoShuffleSmallKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" };
const char* randoShuffleGerudoFortressKeys[4] = { "Vanilla", "Any Dungeon", "Overworld", "Anywhere" };
const char* randoShuffleBossKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" };
@ -4198,7 +4242,17 @@ void DrawRandoEditor(bool& open) {
PaddedSeparator();
// Start with Maps & Compasses
SohImGui::EnhancementCheckbox(Settings::MapsAndCompasses.GetName().c_str(), "gRandomizeStartingMapsCompasses");
ImGui::Text(Settings::MapsAndCompasses.GetName().c_str());
InsertHelpHoverText(
"Own dungeon - Boss Keys can only appear in their respective dungeon.\n"
"\n"
"Any dungeon - Boss Keys can only appear inside of any dungon.\n"
"\n"
"Overworld - Boss Keys can only appear outside of dungeons.\n"
"\n"
"Anywhere - Boss Keys can appear anywhere in the world."
);
SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 1);
ImGui::PopItemWidth();
ImGui::EndTable();

View File

@ -971,7 +971,7 @@ typedef enum {
RSK_STARTING_DEKU_SHIELD,
RSK_STARTING_KOKIRI_SWORD,
RSK_SHUFFLE_KOKIRI_SWORD,
RSK_STARTING_MAPS_COMPASSES, //RANDOTODO more options for this, rn it's just start with or own dungeon
RSK_STARTING_MAPS_COMPASSES,
RSK_SHUFFLE_DUNGEON_REWARDS,
RSK_SHUFFLE_SONGS,
RSK_SHUFFLE_TOKENS,

View File

@ -1801,6 +1801,86 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) {
break;
}
msgCtx->msgLength = font->msgLength = strlen(font->msgBuf);
} else if (gSaveContext.n64ddFlag && textId == 0x66 && GET_PLAYER(globalCtx)->getItemId >= GI_DEKU_TREE_MAP && GET_PLAYER(globalCtx)->getItemId <= GI_ICE_CAVERN_MAP) {
char* keyMsg;
switch (gSaveContext.language) {
case LANGUAGE_ENG: default:
switch (GET_PLAYER(globalCtx)->getItemId) {
case GI_DEKU_TREE_MAP:
keyMsg = "\x08You got the \x05\x42\Deku Tree Map\x05\x40!\x09\x02";
break;
case GI_DODONGOS_CAVERN_MAP:
keyMsg = "\x08You got the \x05\x41\Dodongo's Cavern Map\x05\x40!\x09\x02";
break;
case GI_JABU_JABUS_BELLY_MAP:
keyMsg = "\x08You got the \x05\x43\Jabu Jabu's Belly Map\x05\x40!\x09\x02";
break;
case GI_FOREST_TEMPLE_MAP:
keyMsg = "\x08You got the \x05\x42\Forest Temple Map\x05\x40!\x09\x02";
break;
case GI_FIRE_TEMPLE_MAP:
keyMsg = "\x08You got the \x05\x41\Fire Temple Map\x05\x40!\x09\x02";
break;
case GI_WATER_TEMPLE_MAP:
keyMsg = "\x08You got the \x05\x43\Water Temple Map\x05\x40!\x09\x02";
break;
case GI_SPIRIT_TEMPLE_MAP:
keyMsg = "\x08You got the \x05\x46\Spirit Temple Map\x05\x40!\x09\x02";
break;
case GI_SHADOW_TEMPLE_MAP:
keyMsg = "\x08You got the \x05\x45\Shadow Temple Map\x05\x40!\x09\x02";
break;
case GI_BOTTOM_OF_THE_WELL_MAP:
keyMsg = "\x08You got the \x05\x45\Bottom of the Well Map\x05\x40!\x09\x02";
break;
case GI_ICE_CAVERN_MAP:
keyMsg = "\x08You got the \x05\x43\Ice Cavern Map\x05\x40!\x09\x02";
break;
}
strcpy(font->msgBuf, keyMsg);
break;
}
msgCtx->msgLength = font->msgLength = strlen(font->msgBuf);
} else if (gSaveContext.n64ddFlag && textId == 0x67 && GET_PLAYER(globalCtx)->getItemId >= GI_DEKU_TREE_COMPASS && GET_PLAYER(globalCtx)->getItemId <= GI_ICE_CAVERN_COMPASS) {
char* keyMsg;
switch (gSaveContext.language) {
case LANGUAGE_ENG: default:
switch (GET_PLAYER(globalCtx)->getItemId) {
case GI_DEKU_TREE_COMPASS:
keyMsg = "\x08You got the \x05\x42\Deku Tree Compass\x05\x40!\x09\x02";
break;
case GI_DODONGOS_CAVERN_COMPASS:
keyMsg = "\x08You got the \x05\x41\Dodongo's Cavern Compass\x05\x40!\x09\x02";
break;
case GI_JABU_JABUS_BELLY_COMPASS:
keyMsg = "\x08You got the \x05\x43\Jabu Jabu's Belly Compass\x05\x40!\x09\x02";
break;
case GI_FOREST_TEMPLE_COMPASS:
keyMsg = "\x08You got the \x05\x42\Forest Temple Compass\x05\x40!\x09\x02";
break;
case GI_FIRE_TEMPLE_COMPASS:
keyMsg = "\x08You got the \x05\x41\Fire Temple Compass\x05\x40!\x09\x02";
break;
case GI_WATER_TEMPLE_COMPASS:
keyMsg = "\x08You got the \x05\x43\Water Temple Compass\x05\x40!\x09\x02";
break;
case GI_SPIRIT_TEMPLE_COMPASS:
keyMsg = "\x08You got the \x05\x46\Spirit Temple Compass\x05\x40!\x09\x02";
break;
case GI_SHADOW_TEMPLE_COMPASS:
keyMsg = "\x08You got the \x05\x45\Shadow Temple Compass\x05\x40!\x09\x02";
break;
case GI_BOTTOM_OF_THE_WELL_COMPASS:
keyMsg = "\x08You got the \x05\x45\Bottom of the Well Compass\x05\x40!\x09\x02";
break;
case GI_ICE_CAVERN_COMPASS:
keyMsg = "\x08You got the \x05\x43\Ice Cavern Compass\x05\x40!\x09\x02";
break;
}
strcpy(font->msgBuf, keyMsg);
break;
}
msgCtx->msgLength = font->msgLength = strlen(font->msgBuf);
} else if (textId == 0xF8 && GET_PLAYER(globalCtx)->getItemId == GI_ICE_TRAP) {
switch (gSaveContext.language) {
case LANGUAGE_FRA:

View File

@ -1749,52 +1749,76 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex] |= gBitFlags[item - ITEM_KEY_BOSS];
}
return ITEM_NONE;
} else if ((item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY)) {
} else if (item == ITEM_KEY_SMALL) {
if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1;
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++;
return ITEM_NONE;
}
} else if (
(item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY) ||
(item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY) ||
(item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP) ||
(item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS)
) {
int mapIndex = gSaveContext.mapIndex;
switch (item) {
case ITEM_DEKU_TREE_MAP:
case ITEM_DEKU_TREE_COMPASS:
mapIndex = SCENE_YDAN;
break;
case ITEM_DODONGOS_CAVERN_MAP:
case ITEM_DODONGOS_CAVERN_COMPASS:
mapIndex = SCENE_DDAN;
break;
case ITEM_JABU_JABUS_BELLY_MAP:
case ITEM_JABU_JABUS_BELLY_COMPASS:
mapIndex = SCENE_BDAN;
break;
case ITEM_FOREST_TEMPLE_MAP:
case ITEM_FOREST_TEMPLE_COMPASS:
case ITEM_FOREST_TEMPLE_SMALL_KEY:
case ITEM_FOREST_TEMPLE_BOSS_KEY:
mapIndex = SCENE_BMORI1;
break;
case ITEM_FIRE_TEMPLE_MAP:
case ITEM_FIRE_TEMPLE_COMPASS:
case ITEM_FIRE_TEMPLE_SMALL_KEY:
case ITEM_FIRE_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HIDAN;
break;
case ITEM_WATER_TEMPLE_MAP:
case ITEM_WATER_TEMPLE_COMPASS:
case ITEM_WATER_TEMPLE_SMALL_KEY:
case ITEM_WATER_TEMPLE_BOSS_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case ITEM_SPIRIT_TEMPLE_MAP:
case ITEM_SPIRIT_TEMPLE_COMPASS:
case ITEM_SPIRIT_TEMPLE_SMALL_KEY:
case ITEM_SPIRIT_TEMPLE_BOSS_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case ITEM_SHADOW_TEMPLE_MAP:
case ITEM_SHADOW_TEMPLE_COMPASS:
case ITEM_SHADOW_TEMPLE_SMALL_KEY:
case ITEM_SHADOW_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HAKADAN;
break;
case ITEM_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
}
gSaveContext.inventory.dungeonItems[mapIndex] |= gBitFlags[ITEM_KEY_BOSS - ITEM_KEY_BOSS];
return ITEM_NONE;
} else if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY)) {
int mapIndex = gSaveContext.mapIndex;
switch (item) {
case ITEM_FOREST_TEMPLE_SMALL_KEY:
mapIndex = SCENE_BMORI1;
break;
case ITEM_FIRE_TEMPLE_SMALL_KEY:
mapIndex = SCENE_HIDAN;
break;
case ITEM_WATER_TEMPLE_SMALL_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case ITEM_SPIRIT_TEMPLE_SMALL_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case ITEM_SHADOW_TEMPLE_SMALL_KEY:
mapIndex = SCENE_HAKADAN;
break;
case ITEM_BOTTOM_OF_THE_WELL_MAP:
case ITEM_BOTTOM_OF_THE_WELL_COMPASS:
case ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY:
mapIndex = SCENE_HAKADANCH;
break;
case ITEM_ICE_CAVERN_MAP:
case ITEM_ICE_CAVERN_COMPASS:
mapIndex = SCENE_ICE_DOUKUTO;
break;
case ITEM_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
case ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY:
mapIndex = SCENE_MEN;
break;
@ -1805,20 +1829,26 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) {
mapIndex = SCENE_GANONTIKA;
break;
}
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
return ITEM_NONE;
if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY)) {
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
return ITEM_NONE;
}
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
return ITEM_NONE;
}
} else if (item == ITEM_KEY_SMALL) {
if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1;
return ITEM_NONE;
} else {
gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++;
int bitmask;
if ((item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP)) {
bitmask = gBitFlags[2];
} else if ((item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS)) {
bitmask = gBitFlags[1];
} else {
bitmask = gBitFlags[0];
}
gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask;
return ITEM_NONE;
}
} else if ((item == ITEM_QUIVER_30) || (item == ITEM_BOW)) {
@ -2330,7 +2360,12 @@ u8 Item_CheckObtainability(u8 item) {
} else {
return ITEM_NONE;
}
} else if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY)) {
} else if (
(item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY) ||
(item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY) ||
(item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP) ||
(item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS)
) {
return ITEM_NONE;
} else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) {
return ITEM_NONE;

View File

@ -416,28 +416,64 @@ void GiveLinkDungeonReward(GetItemID getItemId) {
}
}
void GiveLinkSmallKey(GetItemID getItemId) {
void GiveLinkDungeonItem(GetItemID getItemId, GetItemID type) {
int mapIndex;
switch (getItemId) {
case GI_DEKU_TREE_MAP:
case GI_DEKU_TREE_COMPASS:
mapIndex = SCENE_YDAN;
break;
case GI_DODONGOS_CAVERN_MAP:
case GI_DODONGOS_CAVERN_COMPASS:
mapIndex = SCENE_DDAN;
break;
case GI_JABU_JABUS_BELLY_MAP:
case GI_JABU_JABUS_BELLY_COMPASS:
mapIndex = SCENE_BDAN;
break;
case GI_FOREST_TEMPLE_MAP:
case GI_FOREST_TEMPLE_COMPASS:
case GI_FOREST_TEMPLE_SMALL_KEY:
case GI_FOREST_TEMPLE_BOSS_KEY:
mapIndex = SCENE_BMORI1;
break;
case GI_FIRE_TEMPLE_MAP:
case GI_FIRE_TEMPLE_COMPASS:
case GI_FIRE_TEMPLE_SMALL_KEY:
case GI_FIRE_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HIDAN;
break;
case GI_WATER_TEMPLE_MAP:
case GI_WATER_TEMPLE_COMPASS:
case GI_WATER_TEMPLE_SMALL_KEY:
case GI_WATER_TEMPLE_BOSS_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case GI_SPIRIT_TEMPLE_MAP:
case GI_SPIRIT_TEMPLE_COMPASS:
case GI_SPIRIT_TEMPLE_SMALL_KEY:
case GI_SPIRIT_TEMPLE_BOSS_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case GI_SHADOW_TEMPLE_MAP:
case GI_SHADOW_TEMPLE_COMPASS:
case GI_SHADOW_TEMPLE_SMALL_KEY:
case GI_SHADOW_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HAKADAN;
break;
case GI_BOTTOM_OF_THE_WELL_MAP:
case GI_BOTTOM_OF_THE_WELL_COMPASS:
case GI_BOTTOM_OF_THE_WELL_SMALL_KEY:
mapIndex = SCENE_HAKADANCH;
break;
case GI_ICE_CAVERN_MAP:
case GI_ICE_CAVERN_COMPASS:
mapIndex = SCENE_ICE_DOUKUTO;
break;
case GI_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
case GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY:
mapIndex = SCENE_MEN;
break;
@ -449,40 +485,24 @@ void GiveLinkSmallKey(GetItemID getItemId) {
break;
}
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
if (type == GI_MAP) {
uint32_t mapBitMask = 1 << 1;
gSaveContext.inventory.dungeonItems[mapIndex] |= mapBitMask;
} else if (type == GI_COMPASS) {
uint32_t compassBitMask = 1 << 2;
gSaveContext.inventory.dungeonItems[mapIndex] |= compassBitMask;
} else if (type == GI_KEY_SMALL) {
if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) {
gSaveContext.inventory.dungeonKeys[mapIndex] = 1;
} else {
gSaveContext.inventory.dungeonKeys[mapIndex]++;
}
} else if (type == GI_KEY_BOSS) {
uint32_t bossKeyBitMask = 1 << 0;
gSaveContext.inventory.dungeonItems[mapIndex] |= bossKeyBitMask;
}
}
void GiveLinkBossKey(GetItemID getItemId) {
int mapIndex;
switch (getItemId) {
case GI_FOREST_TEMPLE_BOSS_KEY:
mapIndex = SCENE_BMORI1;
break;
case GI_FIRE_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HIDAN;
break;
case GI_WATER_TEMPLE_BOSS_KEY:
mapIndex = SCENE_MIZUSIN;
break;
case GI_SPIRIT_TEMPLE_BOSS_KEY:
mapIndex = SCENE_JYASINZOU;
break;
case GI_SHADOW_TEMPLE_BOSS_KEY:
mapIndex = SCENE_HAKADAN;
break;
case GI_GANONS_CASTLE_BOSS_KEY:
mapIndex = SCENE_GANON;
break;
}
gSaveContext.inventory.dungeonItems[mapIndex] |= 1;
}
void GiveLinksPocketMedallion() {
GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LINKS_POCKET, RG_NONE);
@ -754,11 +774,11 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY;
}
if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_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;
}
}
@ -856,9 +876,13 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
} else if (giid == GI_DOUBLE_DEFENSE) {
GiveLinkDoubleDefense();
} else if (giid >= GI_GERUDO_FORTRESS_SMALL_KEY && giid <= GI_GANONS_CASTLE_SMALL_KEY) {
GiveLinkSmallKey(giid);
GiveLinkDungeonItem(giid, GI_KEY_SMALL);
} else if (giid >= GI_FOREST_TEMPLE_BOSS_KEY && giid <= GI_GANONS_CASTLE_BOSS_KEY) {
GiveLinkBossKey(giid);
GiveLinkDungeonItem(giid, GI_KEY_BOSS);
} else if (giid >= GI_DEKU_TREE_MAP && giid <= GI_ICE_CAVERN_MAP) {
GiveLinkDungeonItem(giid, GI_MAP);
} else if (giid >= GI_DEKU_TREE_COMPASS && giid <= GI_ICE_CAVERN_COMPASS) {
GiveLinkDungeonItem(giid, GI_COMPASS);
} else {
s32 iid = Randomizer_GetItemIDFromGetItemID(giid);
if (iid != -1) INV_CONTENT(iid) = iid;

View File

@ -671,6 +671,28 @@ GetItemEntry sGetItemTable[] = {
GET_ITEM(ITEM_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, 0xC7, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, 0xC7, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, 0xC7, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM(ITEM_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG),
GET_ITEM_NONE,
GET_ITEM_NONE,